MediaWiki:Common.js: Difference between revisions

From MDrivenWiki
No edit summary
No edit summary
 
(88 intermediate revisions by the same user not shown)
Line 53: Line 53:
     'use strict';
     'use strict';


    // Updated CSS for suggestions
     var css = [
     var css = [
         '#suggestion-container {',
         '#suggestion-container {',
Line 60: Line 61:
         '#suggestion-box {',
         '#suggestion-box {',
         '    position: absolute;',
         '    position: absolute;',
         '    top: 100%;',  
         '    top: 100%;',
         '    left: 0;',  
         '    left: 0;',
         '    width: 100%;',  
         '    width: 100%;',
         '    margin-top: 5px;',  
         '    margin-top: 5px;',
         '    background-color: #fff;',
         '    background-color: #fff;',
        '    border: 1px solid #ccc;',
        '    border-radius: 4px;',
        '    box-shadow: 0 2px 6px rgba(0,0,0,0.15);',
         '    z-index: 1000;',
         '    z-index: 1000;',
         '}',
         '}',
Line 75: Line 79:
         '}'
         '}'
     ].join('\n');
     ].join('\n');
    // Add the CSS to the head
     $('head').append('<style type="text/css">' + css + '</style>');
     $('head').append('<style type="text/css">' + css + '</style>');


    // Add suggestion container
     $('#suggestion-container').append('<div id="suggestion-box"></div>');
     $('#suggestion-container').append('<div id="suggestion-box"></div>');


    // Show suggestions from the new API
     function showSuggestions() {
     function showSuggestions() {
         var query = $(this).val();
         var query = $(this).val().trim();
         if (query.length > 0) {  
         if (query.length > 0) {
             var apiUrl = "https://wiki.mdriven.net/api.php";
            // Updated API URL for new suggestions
            var requestData = {
             var apiUrl = "https://search-api.mdriven.net/wiki_suggestions?q=" + encodeURIComponent(query);
                action: "bs-extendedsearch-autocomplete",
 
                format: "json",
             // Fetch suggestions from the new API
                q: JSON.stringify({
                    query: {
                        bool: {
                            must: {
                                match: {
                                    ac_ngram: {
                                        query: query
                                    }
                                }
                            }
                        }
                    },
                    size: 8
                }),
                searchData: JSON.stringify({
                    namespace: 0,
                    value: query,
                    mainpage: ""
                })
             };
             $.ajax({
             $.ajax({
                 url: apiUrl,
                 url: apiUrl,
                data: requestData,
                 dataType: "json",
                 dataType: "json",
                 method: "GET",
                 method: "GET",
                 success: function(data) {
                 success: function(data) {
                     var suggestions = data.suggestions || [];
                     var suggestions = data || [];
                     $('#suggestion-box').empty();
                     $('#suggestion-box').empty();
                    // Check if suggestions exist
                    if (suggestions.length === 0) {
                        $('#suggestion-box').hide();
                        return;
                    }
                    // Populate suggestions
                     $.each(suggestions, function(index, suggestion) {
                     $.each(suggestions, function(index, suggestion) {
                         var item = $('<div class="suggestion-item"></div>').text(suggestion.basename);
                         var item = $('<div class="suggestion-item"></div>').text(suggestion);
                         $('#suggestion-box').append(item);
                         $('#suggestion-box').append(item);
                     });
                     });
                    // Show suggestion box
                    $('#suggestion-box').show();
                 },
                 },
                 error: function(jqxhr, textStatus, error) {
                 error: function(jqxhr, textStatus, error) {
                     console.error('Error fetching suggestions:', error);
                     console.error('Error fetching suggestions:', error);
                    $('#suggestion-box').hide();
                 }
                 }
             });
             });
        } else {
            $('#suggestion-box').empty().hide();
         }
         }
     }
     }


  function hideSuggestions(event) {
    // Hide suggestions when clicking outside
    if (!$(event.target).closest('#suggestion-container').length) {
    function hideSuggestions(event) {
        $('#suggestion-box').empty();
        if (!$(event.target).closest('#suggestion-container').length) {
            $('#suggestion-box').empty().hide();
        }
     }
     }
}


function selectSuggestion(event) {
    // Handle selecting a suggestion
    event.preventDefault(); // Prevent the mousedown event from triggering blur on the search input
    function selectSuggestion(event) {
    var selectedText = $(this).text();
        event.preventDefault(); // Prevent mousedown from losing focus
    window.location.href = '/index.php?title=' + encodeURIComponent(selectedText);
        var selectedText = $(this).text().trim();
}
 
        // Redirect to Special:CustomSearch with selected query
        window.location.href = '/index.php?title=' + encodeURIComponent(selectedText);
    }


    // Attach input listener to fetch suggestions
    $('.search-inputs').on('input', showSuggestions);


  $('.search-input').on('input', showSuggestions);
    // Hide suggestions when clicking anywhere outside
$(document).on('click', hideSuggestions); 
    $(document).on('click', hideSuggestions);
$('#suggestion-box').on('mousedown', '.suggestion-item', selectSuggestion);  


    // Handle suggestion click with mousedown
    $('#suggestion-box').on('mousedown', '.suggestion-item', selectSuggestion);


})(jQuery);
})(jQuery);


$(document).ready(function() {
$(document).ready(function() {
Line 274: Line 283:
             function() { $(this).css({textDecoration: 'underline', color: '#000'}); },
             function() { $(this).css({textDecoration: 'underline', color: '#000'}); },
             function() { $(this).css({textDecoration: 'none', color: '#555'}); }
             function() { $(this).css({textDecoration: 'none', color: '#555'}); }
         );
         );
     });
     });
Line 295: Line 305:
         $inputElement.addClass('search-input');
         $inputElement.addClass('search-input');
         console.log('Class "search-input" added to the input element.');
         console.log('Class "search-input" added to the input element.');
    } else {
        console.log('Input element not found.');
    }
});
$(document).ready(function() {
        var signInLink = $('#user-info a');
        var currentUrl = encodeURIComponent(window.location.pathname + window.location.search + window.location.hash);
        signInLink.attr('href', signInLink.attr('href').replace('<CURRENT_URL>', currentUrl));
    });
document.addEventListener('DOMContentLoaded', function() {
    var images = document.querySelectorAll('.thumbimage');
    var overlay = document.createElement('div');
    overlay.className = 'image-overlay';
    document.body.appendChild(overlay);
    var overlayImage = document.createElement('img');
    overlay.appendChild(overlayImage);
    images.forEach(function(image) {
        image.addEventListener('click', function(event) {
            event.preventDefault();
            event.stopPropagation();
            overlayImage.src = image.src;
            overlay.classList.add('show');
        });
    });
    overlay.addEventListener('click', function() {
        overlay.classList.remove('show');
    });
});
// ==UserScript==
// @name        MediaWiki Clean Delete
// @namespace  MediaWikiScripts
// @description Adds a 'Clean Delete' action link to pages for admins to delete pages and clean up incoming links and redirects.
// ==/UserScript==
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'jquery'], function () {
    function addCleanDeleteLink() {
        if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) {
            if ($('#ca-cleandelete').length === 0) {
                var $link = $('<div>').attr('id', 'ca-cleandelete').attr('class', 'mw-list-item').append(
                    $('<a>').attr('href', '#').attr('class', 'ca-cleandelete').text('Clean Delete').click(function (e) {
                        e.preventDefault();
                        gatherAllDecisions(mw.config.get('wgPageName'));
                    })
                );
                $('#p-actions .tab-group').append($link);
            }
        }
    }
    function gatherAllDecisions(pageTitle) {
        var decisions = {};
        showModal('Handle Links and Redirects', '<div class="form-group">' +
            '<label>Specify how you would like to handle all incoming links and redirects:</label>' +
            '<select id="link-handling-select" class="form-control">' +
                '<option value="delete">Delete Links and Redirects</option>' +
                '<option value="change">Change Target of Links and Redirects</option>' +
            '</select>' +
        '</div>', function () {
            var choice = $('#link-handling-select').val();
            if (choice === 'change') {
                showModal('Specify New Target', '<div class="form-group">' +
                    '<label>Enter the new target page name to update all links and redirects:</label>' +
                    '<input type="text" id="new-target-input" class="form-control" placeholder="Enter new target">' +
                '</div>', function () {
                    decisions.links = $('#new-target-input').val();
                    confirmDeletion(pageTitle, decisions);
                });
            } else {
                decisions.links = '';
                confirmDeletion(pageTitle, decisions);
            }
        });
    }
    function confirmDeletion(pageTitle, decisions) {
        showModal('Confirm Page Deletion', '<p>Are you sure you want to delete "' + pageTitle + '" after handling all links and redirects?</p>', function () {
            decisions.deletion = true;
            showLoadingDialog('Performing Cleanup', function (loadingDialog, updateLoadingText, logDetail) {
                executeAllActions(pageTitle, decisions, function () {
                    loadingDialog.close().closed.then(function() {
                        location.reload();
                    });
                }, updateLoadingText, logDetail);
            });
        });
    }
    function showModal(title, body, onConfirm) {
        var modal = $(
            '<div class="modal fade" tabindex="-1" role="dialog">' +
                '<div class="modal-dialog" role="document">' +
                    '<div class="modal-content">' +
                        '<div class="modal-header">' +
                            '<h5 class="modal-title">' + title + '</h5>' +
                            '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
                                '<span aria-hidden="true">&times;</span>' +
                            '</button>' +
                        '</div>' +
                        '<div class="modal-body">' + body + '</div>' +
                        '<div class="modal-footer">' +
                            '<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>' +
                            '<button type="button" class="btn btn-primary">Confirm</button>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
            '</div>'
        );
        modal.find('.btn-primary').click(function () {
            onConfirm();
            modal.modal('hide');
        });
        modal.on('hidden.bs.modal', function () {
            modal.remove();
        });
        $('body').append(modal);
        modal.modal('show');
    }
    function showLoadingDialog(message, callback) {
        var modal = $(
            '<div class="modal fade" tabindex="-1" role="dialog">' +
                '<div class="modal-dialog" role="document">' +
                    '<div class="modal-content">' +
                        '<div class="modal-header">' +
                            '<h5 class="modal-title">Performing Cleanup</h5>' +
                        '</div>' +
                        '<div class="modal-body">' +
                            '<p id="loading-text">' + message + '</p>' +
                            '<ul id="loading-log"></ul>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
            '</div>'
        );
        $('body').append(modal);
        modal.modal('show');
        callback(modal, function (text) {
            $('#loading-text').text(text);
            $('#loading-log').append('<li>' + text + '</li>');
        }, function (detail) {
            $('#loading-log').append('<li>' + detail + '</li>');
        });
    }
    function executeAllActions(pageTitle, decisions, callback, updateLoadingText, logDetail) {
        var api = new mw.Api();
        function handleLinksAndRedirects(action, newTarget, next) {
            updateLoadingText('Fetching backlinks...');
            api.get({
                action: 'query',
                list: 'backlinks',
                bltitle: pageTitle,
                bllimit: 'max',
                blfilterredir: 'all' // Include both redirects and non-redirects
            }).done(function (data) {
                logDetail('Backlinks fetched.');
                if (data.query.backlinks) {
                    var promises = $.map(data.query.backlinks, function (link) {
                        return new $.Deferred(function (defer) {
                            api.get({
                                action: 'parse',
                                page: link.title,
                                prop: 'wikitext'
                            }).done(function (linkData) {
                                var isRedirect = linkData.parse.wikitext['*'].trim().startsWith('#REDIRECT');
                                if (isRedirect) {
                                    if (action === 'update') {
                                        updateRedirectTarget(link.title, newTarget, api, defer.resolve, logDetail);
                                    } else {
                                        logDetail('Backlink ' + link.title + ' is a redirect. Deleting...');
                                        performDeletion(link.title, defer.resolve, logDetail);
                                    }
                                } else {
                                    if (action === 'update') {
                                        updateLinkInPage(link.title, pageTitle, newTarget, api, defer.resolve, logDetail);
                                    } else {
                                        removeLinkFromPage(link.title, pageTitle, api, defer.resolve, logDetail);
                                    }
                                }
                            }).fail(function (error) {
                                logDetail('Error checking if backlink ' + link.title + ' is a redirect: ' + error);
                                defer.resolve();
                            });
                        }).promise();
                    });
                    $.when.apply($, promises).then(function () {
                        updateLoadingText(action === 'update' ? 'All links updated.' : 'All links removed.');
                        next();
                    });
                } else {
                    next();
                }
            }).fail(function (error) {
                updateLoadingText('Error fetching backlinks: ' + error);
                next();
            });
        }
        function updateLinkInPage(linkedPageTitle, originalPageTitle, newTarget, api, resolve, logDetail) {
            api.get({
                action: 'parse',
                page: linkedPageTitle,
                prop: 'wikitext'
            }).then(function (data) {
                var wikitext = data.parse.wikitext['*'];
                var regex = new RegExp('\\[\\[' + originalPageTitle.replace(/[\[\]]/g, '\\$&') + '(\\|[^\\]]+)?\\]\\]', 'g');
                var newWikitext = wikitext.replace(regex, '[[' + newTarget + '$1]]');
                if (wikitext !== newWikitext) {
                    logDetail('Updating link in ' + linkedPageTitle);
                } else {
                    logDetail('No link found in ' + linkedPageTitle);
                }
                return api.postWithToken('csrf', {
                    action: 'edit',
                    title: linkedPageTitle,
                    text: newWikitext,
                    summary: 'Updated link to [[' + newTarget + ']]'
                }).then(function (response) {
                    console.log('API response from updating link: ', response);
                    if (response.edit && response.edit.result === 'Success' && !response.edit.nochange) {
                        logDetail('Successfully updated link in ' + linkedPageTitle);
                    } else {
                        logDetail('No changes made to link in ' + linkedPageTitle);
                    }
                    resolve();
                }).fail(function (error) {
                    logDetail('Error updating link in ' + linkedPageTitle + ': ' + error);
                    resolve();
                });
            }).fail(function (error) {
                logDetail('Error fetching page content for ' + linkedPageTitle + ': ' + error);
                resolve();
            });
        }
        function updateRedirectTarget(redirectPageTitle, newTarget, api, resolve, logDetail) {
            logDetail('Updating redirect target in ' + redirectPageTitle);
            return api.postWithToken('csrf', {
                action: 'edit',
                title: redirectPageTitle,
                text: '#REDIRECT [[' + newTarget + ']]',
                summary: 'Updated redirect to [[' + newTarget + ']]'
            }).then(function (response) {
                console.log('API response from updating redirect: ', response);
                if (response.edit && response.edit.result === 'Success' && !response.edit.nochange) {
                    logDetail('Successfully updated redirect in ' + redirectPageTitle);
                } else {
                    logDetail('No changes made to redirect in ' + redirectPageTitle);
                }
                resolve();
            }).fail(function (error) {
                logDetail('Error updating redirect in ' + redirectPageTitle + ': ' + error);
                resolve();
            });
        }
        function removeLinkFromPage(linkedPageTitle, originalPageTitle, api, resolve, logDetail) {
            api.get({
                action: 'parse',
                page: linkedPageTitle,
                prop: 'wikitext'
            }).then(function (data) {
                var wikitext = data.parse.wikitext['*'];
                var regex = new RegExp('\\[\\[' + originalPageTitle.replace(/[\[\]]/g, '\\$&') + '(\\|[^\\]]+)?\\]\\]', 'g');
                var newWikitext = wikitext.replace(regex, function(match, p1) {
                    return p1 ? p1.substring(1) : originalPageTitle;
                });
                if (wikitext !== newWikitext) {
                    logDetail('Removing link from ' + linkedPageTitle);
                } else {
                    logDetail('No link found in ' + linkedPageTitle);
                }
                return api.postWithToken('csrf', {
                    action: 'edit',
                    title: linkedPageTitle,
                    text: newWikitext,
                    summary: 'Removed link to [[' + originalPageTitle + ']]'
                }).then(function (response) {
                    console.log('API response from removing link: ', response);
                    if (response.edit && response.edit.result === 'Success' && !response.edit.nochange) {
                        logDetail('Successfully removed link from ' + linkedPageTitle);
                    } else {
                        logDetail('No changes made to link in ' + linkedPageTitle);
                    }
                    resolve();
                }).fail(function (error) {
                    logDetail('Error removing link from ' + linkedPageTitle + ': ' + error);
                    resolve();
                });
            }).fail(function (error) {
                logDetail('Error fetching page content for ' + linkedPageTitle + ': ' + error);
                resolve();
            });
        }
        function handleRedirects(next) {
            updateLoadingText('Fetching redirects...');
            api.get({
                action: 'query',
                titles: pageTitle,
                redirects: true
            }).done(function (data) {
                logDetail('Redirects fetched.');
                var redirects = data.query.pages[Object.keys(data.query.pages)[0]].redirects;
                if (redirects) {
                    var promises = $.map(redirects, function (redirect) {
                        return new $.Deferred(function (defer) {
                            logDetail('Found redirect: ' + redirect.title);
                            performDeletion(redirect.title, defer.resolve, logDetail);
                        }).promise();
                    });
                    $.when.apply($, promises).then(function () {
                        next();
                    });
                } else {
                    next();
                }
            }).fail(function (error) {
                updateLoadingText('Error fetching redirects: ' + error);
                next();
            });
        }
        function performDeletion(pageTitle, resolve, logDetail) {
            updateLoadingText('Deleting the page: ' + pageTitle);
            api.postWithToken('csrf', {
                action: 'delete',
                title: pageTitle,
                reason: 'Automated clean delete by admin'
            }).done(function (response) {
                console.log('API response from deleting page: ', response);
                if (response.delete && response.delete.title) {
                    logDetail('Successfully deleted page: ' + response.delete.title);
                } else {
                    logDetail('No deletion performed for ' + pageTitle);
                }
                resolve();
            }).fail(function (error) {
                logDetail('Error during clean deletion of ' + pageTitle + ': ' + error);
                resolve();
            });
        }
        var tasks = [
            function (resolve) {
                if (decisions.links === '') {
                    handleLinksAndRedirects('remove', '', resolve);
                } else {
                    handleLinksAndRedirects('update', decisions.links, resolve);
                }
            },
            function (resolve) {
                if (decisions.deletion) {
                    handleRedirects(resolve);
                } else {
                    resolve();
                }
            },
            function (resolve) {
                if (decisions.deletion) {
                    performDeletion(pageTitle, resolve, logDetail);
                } else {
                    resolve();
                }
            }
        ];
        (function executeTasks(i) {
            if (i < tasks.length) {
                tasks[i](function () {
                    executeTasks(i + 1);
                });
            } else {
                callback();
            }
        })(0);
     }
     }
    mw.hook('wikipage.content').add(addCleanDeleteLink);
});
function isLoggedOut() {
  return mw.config.get('wgUserName') === null;
}
jQuery(document).ready(function ($) {
  if (isLoggedOut()) {
    $('body').append('<div class="darken-overlay"></div>');
    $('img').each(function () {
      var imgSrc = $(this).attr('src');
     
      if (imgSrc !== '/images/MDrivenLogo.png') {
        $(this).addClass('enlargeable');
      }
    });
    $('img.enlargeable').click(function (event) {
      event.preventDefault();
      event.stopPropagation();
      if ($(this).hasClass('enlarged')) {
        $(this).removeClass('enlarged');
        $('.darken-overlay').hide();
      } else {
        $('img.enlargeable').removeClass('enlarged');
        $(this).addClass('enlarged');
        $('.darken-overlay').show();
       
        var fullSizeSrc = $(this).attr('src').replace('/thumb', '').replace(/\/\d+px-.+$/, '');
        $(this).attr('src', fullSizeSrc);
      }
    });
    $('.darken-overlay').click(function () {
      $('img.enlargeable').removeClass('enlarged');
      $(this).hide();
    });
  }
});
});
/**
* Fixed LeftMenu Editor with Tags Feature - ES5 Compatible
* Top collapsible design, clean colors, working structure display
*/
(function (mw, $) {
    'use strict';
    // Abort for anonymous visitors
    if (!mw.config.get('wgUserId')) { return; }
    // Load dependencies
    mw.loader.using(['mediawiki.api', 'jquery.ui']).done(function () {
        var LeftMenuEditor = {
            api: new mw.Api(),
            menuData: null, // Start as null to detect if loaded
            namespace: (mw.config.get('wgCanonicalNamespace') || 'Main').replace(/ /g, '_'), // Replace spaces with underscores
            currentPage: mw.config.get('wgPageName'),
            pageName: mw.config.get('wgTitle'),
            isEditMode: false,
            isCollapsed: true,
            $menu: null,
            $editorBox: null,
            $preview: null,
            selectedItem: null,
            suggestedTags: [], // Store suggested tags
            selectedTags: [] // Store selected tags
        };
        // Clean, professional CSS without gradients
        function addStyles() {
            var css = [
                // Main container at top of content
                '.leftmenu-editor-container{position:relative;background:#ffffff;border:1px solid #ddd;margin:0 0 20px 0;box-shadow:0 2px 4px rgba(0,0,0,0.08);overflow:hidden;transition:all 0.3s ease}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-body{max-height:0;padding:0 20px}',
               
                // Header - clean design
                '.leftmenu-editor-header{background:#f8f9fa;border-bottom:1px solid #ddd;padding:15px 20px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;user-select:none}',
                '.leftmenu-editor-header:hover{background:#f0f1f3}',
                '.leftmenu-editor-header h3{margin:0;font-size:16px;font-weight:600;color:#333}',
                '.leftmenu-editor-toggle{font-size:12px;color:#666;transition:transform 0.3s}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-toggle{transform:rotate(-90deg)}',
               
                // Body layout
                '.leftmenu-editor-body{display:grid;grid-template-columns:1fr 380px;gap:20px;padding:20px;max-height:600px;overflow-y:scroll;transition:all 0.3s ease}',
               
                // Menu preview panel
                '.leftmenu-preview-panel{background:#fafafa;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;max-height:560px}',
                '.leftmenu-preview-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}',
                '.leftmenu-preview-header h4{margin:0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
                '.leftmenu-search{padding:6px 12px;border:1px solid #ddd;border-radius:4px;width:200px;font-size:13px}',
                '.leftmenu-search:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
               
                // Menu tree structure
                '.leftmenu-preview-tree{font-size:14px}',
               
                // Menu items - clean cards
                '.leftmenu-visual-item{background:#fff;border:1px solid #e0e0e0;padding:10px 14px;margin:4px 0;cursor:move;transition:all 0.2s;display:flex;justify-content:space-between;align-items:center;color:#333;position:relative}',
                '.leftmenu-visual-item:hover{background:#f8f9fa;border-color:#4a90e2;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-visual-item.is-current-page{background:#e8f4fd;border-color:#4a90e2;font-weight:600}',
                '.leftmenu-visual-item.selected{background:#4a90e2;color:#fff;border-color:#3a7bc8}',
               
                // Sections - hierarchical design
                '.leftmenu-visual-section{background:#fff;border:1px solid #ddd;margin:8px 0;overflow:visible}',
                '.leftmenu-visual-section-header{background:#f0f0f0;padding:10px 14px;cursor:pointer;display:flex;align-items:center;font-weight:600;color:#333;font-size:14px;border-bottom:1px solid #ddd;user-select:none}',
                '.leftmenu-visual-section-header:hover{background:#e8e8e8}',
                '.leftmenu-section-toggle{font-size:10px;color:#666;margin-right:8px;transition:transform 0.2s}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-toggle{transform:rotate(-90deg)}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-items{display:none}',
                '.leftmenu-section-items{padding:8px;background:#fafafa;min-height:20px}',
               
                // Nested sections - clear hierarchy
                '.leftmenu-section-items .leftmenu-visual-section{margin:4px 0;border-color:#e0e0e0}',
                '.leftmenu-section-items .leftmenu-visual-section-header{background:#f8f8f8;font-size:13px;padding:8px 12px}',
                '.leftmenu-section-items .leftmenu-visual-item{font-size:13px}',
               
                // Drag placeholder at correct level
                '.ui-sortable-helper{opacity:0.8 !important}',
                '.leftmenu-section-items .leftmenu-drag-placeholder{margin-left:0 !important}',
               
                // Direct links - distinct style
                '.leftmenu-visual-item.direct-link{background:#fffbf0;border-color:#f0ad4e}',
                '.leftmenu-visual-item.direct-link:hover{background:#fff8e1;border-color:#ec971f}',
               
                // Item count badge
                '.leftmenu-item-count{background:#4a90e2;color:#fff;padding:2px 6px;border-radius:10px;font-size:11px;margin-left:auto;margin-right:10px}',
               
                // Icons
                '.leftmenu-icon{display:inline-block;width:16px;text-align:center;margin-right:6px;opacity:0.6}',
               
                // Drag and drop
                '.leftmenu-dragging{opacity:0.4}',
                '.leftmenu-drag-placeholder{background:#4a90e2;opacity:0.2;height:36px;margin:4px 0;border:2px dashed #4a90e2}',
               
                // Action buttons
                '.leftmenu-item-actions{opacity:0;transition:opacity 0.2s;display:flex;gap:4px}',
                '.leftmenu-visual-item:hover .leftmenu-item-actions,.leftmenu-visual-section-header:hover .leftmenu-item-actions{opacity:1}',
                '.leftmenu-visual-item.selected .leftmenu-item-actions{opacity:1}',
                '.leftmenu-item-actions button{background:#fff;border:1px solid #ddd;width:28px;height:28px;border-radius:4px;cursor:pointer;font-size:12px;transition:all 0.15s;padding:0;display:flex;align-items:center;justify-content:center}',
                '.leftmenu-item-actions button:hover{background:#f8f9fa;border-color:#999}',
                '.leftmenu-item-edit{color:#4a90e2}',
                '.leftmenu-item-delete{color:#d9534f}',
                '.leftmenu-item-duplicate{color:#5cb85c}',
               
                // Control panel
                '.leftmenu-controls{background:#fff;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;display:flex;flex-direction:column}',
                '.leftmenu-controls h4{margin:0 0 16px 0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
               
                // Quick actions
                '.leftmenu-quick-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px}',
                '.leftmenu-quick-action{background:#f8f9fa;border:1px solid #ddd;padding:12px;text-align:center;cursor:pointer;transition:all 0.2s;border-radius:4px}',
                '.leftmenu-quick-action:hover{border-color:#4a90e2;background:#fff;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-quick-action-icon{font-size:20px;margin-bottom:4px;display:block}',
                '.leftmenu-quick-action-label{font-size:12px;color:#666}',
               
                // Form inputs
                '.leftmenu-form-group{margin-bottom:16px}',
                '.leftmenu-form-label{display:block;margin-bottom:4px;color:#333;font-size:13px;font-weight:600}',
                '.leftmenu-form-input,.leftmenu-form-select{width:100%;padding:8px 12px;border:1px solid #ddd;border-radius:4px;font-size:13px}',
                '.leftmenu-form-input:focus,.leftmenu-form-select:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
               
                // Buttons
                '.leftmenu-button{padding:8px 16px;border:1px solid #ddd;border-radius:4px;font-size:13px;font-weight:600;cursor:pointer;transition:all 0.2s;background:#fff}',
                '.leftmenu-button:hover{background:#f8f9fa}',
                '.leftmenu-button.primary{background:#4a90e2;color:#fff;border-color:#4a90e2}',
                '.leftmenu-button.primary:hover{background:#3a7bc8;border-color:#3a7bc8}',
                '.leftmenu-button.secondary{background:#f8f9fa;color:#333}',
                '.leftmenu-button.danger{background:#d9534f;color:#fff;border-color:#d9534f}',
                '.leftmenu-button.success{background:#5cb85c;color:#fff;border-color:#5cb85c}',
                '.leftmenu-button:disabled{opacity:0.6;cursor:not-allowed}',
               
                // Status messages
                '.leftmenu-status{padding:10px 12px;margin:10px 0;font-size:13px;display:none;border-radius:4px}',
                '.leftmenu-status.success{background:#dff0d8;color:#3c763d;border:1px solid #d6e9c6}',
                '.leftmenu-status.error{background:#f2dede;color:#a94442;border:1px solid #ebccd1}',
                '.leftmenu-status.info{background:#d9edf7;color:#31708f;border:1px solid #bce8f1}',
               
                // JSON view
                '.leftmenu-json-view{background:#f5f5f5;border:1px solid #ddd;padding:12px;font-family:monospace;font-size:12px;line-height:1.4;border-radius:4px;max-height:300px;overflow-y:auto}',
               
                // Loading
                '.leftmenu-loading{text-align:center;padding:40px;color:#999}',
                '.leftmenu-spinner{display:inline-block;width:20px;height:20px;border:2px solid #f3f3f3;border-top:2px solid #4a90e2;border-radius:50%;animation:spin 1s linear infinite}',
                '@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}',
               
                // Empty state
                '.leftmenu-empty-state{text-align:center;padding:40px;color:#999}',
                '.leftmenu-empty-state button{margin-top:10px}',
               
                // Responsive
                '@media (max-width: 900px){.leftmenu-editor-body{grid-template-columns:1fr;height:auto}.leftmenu-controls{border-top:1px solid #e0e0e0;margin-top:20px}}'
            ].join('');
            $('<style>').text(css).appendTo('head');
        }
        // Create the interface
        function createInterface() {
            var $container = $('<div>', { 'class': 'leftmenu-editor-container collapsed' });
           
            var $header = $('<div>', { 'class': 'leftmenu-editor-header' }).html(
                '<h3>🛠️ Wiki Tools - Menu Editor, AI Assistant & Page Management</h3>' +
                '<span class="leftmenu-editor-toggle">▼</span>'
            );
           
            var $body = $('<div>', { 'class': 'leftmenu-editor-body' });
           
            // Create tabbed interface
            var $tabs = $('<div>', { 'class': 'wiki-tools-tabs' }).html(
                '<div class="tab-buttons">' +
                    '<button class="tab-button active" data-tab="menu-editor">📋 Menu Editor</button>' +
                    '<button class="tab-button" data-tab="ai-tools">🤖 AI Tools</button>' +
                    '<button class="tab-button" data-tab="page-tools">📄 Page Tools</button>' +
                '</div>'
            );
           
            // Menu Editor Tab
            var $menuTab = $('<div>', { 'class': 'tab-content active', 'id': 'menu-editor-tab' }).html(
                '<div class="leftmenu-preview-panel">' +
                    '<div class="leftmenu-preview-header">' +
                        '<h4>Menu Structure - ' + LeftMenuEditor.namespace + '</h4>' +
                        '<input type="text" class="leftmenu-search" placeholder="Search items...">' +
                    '</div>' +
                    '<div class="leftmenu-preview-tree"></div>' +
                    '<div class="leftmenu-empty-state" style="display:none">' +
                        '<p>No menu items yet</p>' +
                        '<button class="leftmenu-button primary leftmenu-empty-add">Add First Item</button>' +
                    '</div>' +
                '</div>' +
                '<div class="leftmenu-controls">' +
                    '<h4>Actions</h4>' +
                    '<div class="leftmenu-quick-actions">' +
                        '<div class="leftmenu-quick-action" data-action="add-section">' +
                            '<span class="leftmenu-quick-action-icon">📁</span>' +
                            '<span class="leftmenu-quick-action-label">Add Section</span>' +
                        '</div>' +
                        '<div class="leftmenu-quick-action" data-action="add-page">' +
                            '<span class="leftmenu-quick-action-icon">📄</span>' +
                            '<span class="leftmenu-quick-action-label">Add Page</span>' +
                        '</div>' +
                        '<div class="leftmenu-quick-action" data-action="add-current">' +
                            '<span class="leftmenu-quick-action-icon">📌</span>' +
                            '<span class="leftmenu-quick-action-label">Current Page</span>' +
                        '</div>' +
                        '<div class="leftmenu-quick-action" data-action="import">' +
                            '<span class="leftmenu-quick-action-icon">📥</span>' +
                            '<span class="leftmenu-quick-action-label">Import</span>' +
                        '</div>' +
                    '</div>' +
                    '<div class="leftmenu-status"></div>' +
                    '<div class="leftmenu-action-panel" style="display:none;margin-bottom:20px">' +
                        '<div class="leftmenu-form"></div>' +
                    '</div>' +
                    '<div style="margin-top:auto">' +
                        '<button class="leftmenu-button primary leftmenu-save" style="width:100%;margin-bottom:10px">Save Changes</button>' +
                        '<div style="display:flex;gap:10px">' +
                            '<button class="leftmenu-button secondary leftmenu-reset" style="flex:1">Reset</button>' +
                            '<button class="leftmenu-button secondary leftmenu-view-json" style="flex:1">View JSON</button>' +
                        '</div>' +
                    '</div>' +
                    '<div class="leftmenu-json-view" style="display:none;margin-top:20px"></div>' +
                '</div>'
            );
           
            // AI Tools Tab
            var $aiTab = $('<div>', { 'class': 'tab-content', 'id': 'ai-tools-tab' }).html(
                '<div class="ai-tools-container">' +
                    '<div class="ai-section">' +
                        '<h4>AI Content Assistant</h4>' +
                        '<div class="ai-actions">' +
                            '<button class="ai-button primary" id="ai-summarize">' +
                                '<span class="button-icon">📝</span> Summarize Page' +
                            '</button>' +
                            '<button class="ai-button primary" id="ai-fix-spelling">' +
                                '<span class="button-icon">✓</span> Fix Spelling' +
                            '</button>' +
                            '<button class="ai-button primary" id="ai-suggest-tags">' +
                                '<span class="button-icon">🏷️</span> Suggest Tags' +
                            '</button>' +
                        '</div>' +
                        '<div class="ai-result" id="ai-result" style="display:none">' +
                            '<div class="ai-result-header">' +
                                '<h5>Result</h5>' +
                                '<button class="ai-button-small" id="ai-copy">📋 Copy</button>' +
                            '</div>' +
                            '<div class="ai-result-content"></div>' +
                            '<div class="ai-result-actions">' +
                                '<button class="ai-button success" id="ai-apply-nutshell" style="display:none">🥜 Add as Nutshell</button>' +
                                '<button class="ai-button success" id="ai-apply-spelling" style="display:none">✅ Apply Corrections</button>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                   
                    '<div class="ai-section" id="tags-section" style="display:none">' +
                        '<h4>Page Tags</h4>' +
                        '<div class="tags-container">' +
                            '<div class="suggested-tags-section">' +
                                '<h5>AI Suggested Tags</h5>' +
                                '<div class="suggested-tags" id="suggested-tags"></div>' +
                            '</div>' +
                            '<div class="custom-tags-section">' +
                                '<h5>Add Custom Tags</h5>' +
                                '<div class="custom-tag-input">' +
                                    '<input type="text" id="custom-tag-input" class="form-input" placeholder="Type a tag and press Enter">' +
                                    '<button class="ai-button-small primary" id="add-custom-tag">+ Add</button>' +
                                '</div>' +
                            '</div>' +
                            '<div class="selected-tags-section">' +
                                '<h5>Selected Tags</h5>' +
                                '<div class="selected-tags" id="selected-tags"></div>' +
                            '</div>' +
                            '<div class="tags-actions">' +
                                '<button class="ai-button success" id="apply-tags">Apply Tags to Page</button>' +
                                '<button class="ai-button secondary" id="clear-tags">Clear All</button>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                   
                    '<div class="ai-status" style="display:none"></div>' +
                '</div>'
            );
           
            // Page Tools Tab
            var $pageTab = $('<div>', { 'class': 'tab-content', 'id': 'page-tools-tab' }).html(
                '<div class="page-tools-container">' +
                    '<div class="page-section">' +
                        '<h4>Rename Page</h4>' +
                        '<div class="form-group-inline">' +
                            '<input type="text" id="new-page-name" class="form-input" placeholder="Enter new page name">' +
                            '<button class="ai-button primary" id="rename-page">Rename</button>' +
                        '</div>' +
                    '</div>' +
                    '<div class="page-section">' +
                        '<h4>Move to Namespace</h4>' +
                        '<div class="form-group-inline">' +
                            '<select id="target-namespace" class="form-select">' +
                                '<option value="">Loading namespaces...</option>' +
                            '</select>' +
                            '<button class="ai-button primary" id="move-namespace">Move Page</button>' +
                        '</div>' +
                    '</div>' +
                    '<div class="page-info">' +
                        '<h4>Current Page Info</h4>' +
                        '<div class="info-item"><strong>Page:</strong> <span id="current-page-name">' + mw.config.get('wgPageName') + '</span></div>' +
                        '<div class="info-item"><strong>Namespace:</strong> <span id="current-namespace">' + (mw.config.get('wgCanonicalNamespace') || 'Main') + '</span></div>' +
                    '</div>' +
                    '<div class="page-status" style="display:none"></div>' +
                '</div>'
            );
           
            $body.append($tabs);
            $body.append($('<div class="tab-contents">').append($menuTab, $aiTab, $pageTab));
           
            $container.append($header, $body);
           
            // Insert at top of content
            var $content = $('#content, #mw-content-text, .mw-body-content').first();
            $content.prepend($container);
           
            LeftMenuEditor.$editorBox = $container;
            LeftMenuEditor.$preview = $container.find('.leftmenu-preview-tree');
           
            // Add unified styles
            addUnifiedStyles();
           
            // Bind tab events
            bindTabEvents();
           
            // Bind all events
            bindAIEvents();
            bindPageToolsEvents();
            bindTagsEvents();
           
            // Load namespaces
            loadNamespaces();
        }
       
        // Add unified styles
        function addUnifiedStyles() {
            var existingStyles = $('style').filter(function() {
                return $(this).text().indexOf('.leftmenu-editor-container') > -1;
            });
            existingStyles.remove();
           
            var css = [
                // Keep all existing menu editor styles...
                '.leftmenu-editor-container{position:relative;background:#ffffff;border:1px solid #ddd;margin:0 0 20px 0;box-shadow:0 2px 4px rgba(0,0,0,0.08);overflow:hidden;transition:all 0.3s ease}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-body{max-height:0;padding:0 20px}',
                '.leftmenu-editor-header{background:#f8f9fa;border-bottom:1px solid #ddd;padding:15px 20px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;user-select:none}',
                '.leftmenu-editor-header:hover{background:#f0f1f3}',
                '.leftmenu-editor-header h3{margin:0;font-size:16px;font-weight:600;color:#333}',
                '.leftmenu-editor-toggle{font-size:12px;color:#666;transition:transform 0.3s}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-toggle{transform:rotate(-90deg)}',
                '.leftmenu-editor-body{padding:0;max-height:700px;overflow-y:scroll;transition:all 0.3s ease}',
               
                // Tab styles
                '.wiki-tools-tabs{background:#f0f0f0;border-bottom:1px solid #ddd}',
                '.tab-buttons{display:flex;padding:0}',
                '.tab-button{flex:1;padding:12px 20px;border:none;background:transparent;cursor:pointer;font-size:14px;font-weight:500;color:#666;transition:all 0.2s;border-bottom:3px solid transparent}',
                '.tab-button:hover{background:#e8e8e8}',
                '.tab-button.active{color:#4a90e2;border-bottom-color:#4a90e2;background:#fff}',
                '.tab-contents{background:#fff}',
                '.tab-content{display:none;animation:fadeIn 0.3s}',
                '.tab-content.active{display:grid;grid-template-columns:1fr 380px;gap:20px;padding:20px}',
                '#ai-tools-tab.active, #page-tools-tab.active{display:block;padding:20px}',
                '@keyframes fadeIn{from{opacity:0}to{opacity:1}}',
               
                // Menu editor styles (keep existing)
                '.leftmenu-preview-panel{background:#fafafa;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;max-height:560px}',
                '.leftmenu-preview-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}',
                '.leftmenu-preview-header h4{margin:0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
                '.leftmenu-search{padding:6px 12px;border:1px solid #ddd;border-radius:4px;width:200px;font-size:13px}',
                '.leftmenu-search:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
                '.leftmenu-preview-tree{font-size:14px}',
                '.leftmenu-visual-item{background:#fff;border:1px solid #e0e0e0;padding:10px 14px;margin:4px 0;cursor:move;transition:all 0.2s;display:flex;justify-content:space-between;align-items:center;color:#333;position:relative}',
                '.leftmenu-visual-item:hover{background:#f8f9fa;border-color:#4a90e2;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-visual-item.is-current-page{background:#e8f4fd;border-color:#4a90e2;font-weight:600}',
                '.leftmenu-visual-item.selected{background:#4a90e2;color:#fff;border-color:#3a7bc8}',
                '.leftmenu-visual-section{background:#fff;border:1px solid #ddd;margin:8px 0;overflow:visible}',
                '.leftmenu-visual-section-header{background:#f0f0f0;padding:10px 14px;cursor:pointer;display:flex;align-items:center;font-weight:600;color:#333;font-size:14px;border-bottom:1px solid #ddd;user-select:none}',
                '.leftmenu-visual-section-header:hover{background:#e8e8e8}',
                '.leftmenu-section-toggle{font-size:10px;color:#666;margin-right:8px;transition:transform 0.2s}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-toggle{transform:rotate(-90deg)}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-items{display:none}',
                '.leftmenu-section-items{padding:8px;background:#fafafa;min-height:20px}',
                '.leftmenu-section-items .leftmenu-visual-section{margin:4px 0;border-color:#e0e0e0}',
                '.leftmenu-section-items .leftmenu-visual-section-header{background:#f8f8f8;font-size:13px;padding:8px 12px}',
                '.leftmenu-section-items .leftmenu-visual-item{font-size:13px}',
                '.ui-sortable-helper{opacity:0.8 !important}',
                '.leftmenu-section-items .leftmenu-drag-placeholder{margin-left:0 !important}',
                '.leftmenu-visual-item.direct-link{background:#fffbf0;border-color:#f0ad4e}',
                '.leftmenu-visual-item.direct-link:hover{background:#fff8e1;border-color:#ec971f}',
                '.leftmenu-item-count{background:#4a90e2;color:#fff;padding:2px 6px;border-radius:10px;font-size:11px;margin-left:auto;margin-right:10px}',
                '.leftmenu-icon{display:inline-block;width:16px;text-align:center;margin-right:6px;opacity:0.6}',
                '.leftmenu-dragging{opacity:0.4}',
                '.leftmenu-drag-placeholder{background:#4a90e2;opacity:0.2;height:36px;margin:4px 0;border:2px dashed #4a90e2}',
                '.leftmenu-item-actions{opacity:0;transition:opacity 0.2s;display:flex;gap:4px}',
                '.leftmenu-visual-item:hover .leftmenu-item-actions,.leftmenu-visual-section-header:hover .leftmenu-item-actions{opacity:1}',
                '.leftmenu-visual-item.selected .leftmenu-item-actions{opacity:1}',
                '.leftmenu-item-actions button{background:#fff;border:1px solid #ddd;width:28px;height:28px;border-radius:4px;cursor:pointer;font-size:12px;transition:all 0.15s;padding:0;display:flex;align-items:center;justify-content:center}',
                '.leftmenu-item-actions button:hover{background:#f8f9fa;border-color:#999}',
                '.leftmenu-item-edit{color:#4a90e2}',
                '.leftmenu-item-delete{color:#d9534f}',
                '.leftmenu-item-duplicate{color:#5cb85c}',
                '.leftmenu-controls{background:#fff;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;display:flex;flex-direction:column}',
                '.leftmenu-controls h4{margin:0 0 16px 0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
                '.leftmenu-quick-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px}',
                '.leftmenu-quick-action{background:#f8f9fa;border:1px solid #ddd;padding:12px;text-align:center;cursor:pointer;transition:all 0.2s;border-radius:4px}',
                '.leftmenu-quick-action:hover{border-color:#4a90e2;background:#fff;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-quick-action-icon{font-size:20px;margin-bottom:4px;display:block}',
                '.leftmenu-quick-action-label{font-size:12px;color:#666}',
                '.leftmenu-form-group{margin-bottom:16px}',
                '.leftmenu-form-label{display:block;margin-bottom:4px;color:#333;font-size:13px;font-weight:600}',
                '.leftmenu-form-input,.leftmenu-form-select{width:100%;padding:8px 12px;border:1px solid #ddd;border-radius:4px;font-size:13px}',
                '.leftmenu-form-input:focus,.leftmenu-form-select:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
                '.leftmenu-button{padding:8px 16px;border:1px solid #ddd;border-radius:4px;font-size:13px;font-weight:600;cursor:pointer;transition:all 0.2s;background:#fff}',
                '.leftmenu-button:hover{background:#f8f9fa}',
                '.leftmenu-button.primary{background:#4a90e2;color:#fff;border-color:#4a90e2}',
                '.leftmenu-button.primary:hover{background:#3a7bc8;border-color:#3a7bc8}',
                '.leftmenu-button.secondary{background:#f8f9fa;color:#333}',
                '.leftmenu-button.danger{background:#d9534f;color:#fff;border-color:#d9534f}',
                '.leftmenu-button.success{background:#5cb85c;color:#fff;border-color:#5cb85c}',
                '.leftmenu-button:disabled{opacity:0.6;cursor:not-allowed}',
                '.leftmenu-status{padding:10px 12px;margin:10px 0;font-size:13px;display:none;border-radius:4px}',
                '.leftmenu-status.success{background:#dff0d8;color:#3c763d;border:1px solid #d6e9c6}',
                '.leftmenu-status.error{background:#f2dede;color:#a94442;border:1px solid #ebccd1}',
                '.leftmenu-status.info{background:#d9edf7;color:#31708f;border:1px solid #bce8f1}',
                '.leftmenu-json-view{background:#f5f5f5;border:1px solid #ddd;padding:12px;font-family:monospace;font-size:12px;line-height:1.4;border-radius:4px;max-height:300px;overflow-y:auto}',
                '.leftmenu-loading{text-align:center;padding:40px;color:#999}',
                '.leftmenu-spinner{display:inline-block;width:20px;height:20px;border:2px solid #f3f3f3;border-top:2px solid #4a90e2;border-radius:50%;animation:spin 1s linear infinite}',
                '@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}',
                '.leftmenu-empty-state{text-align:center;padding:40px;color:#999}',
                '.leftmenu-empty-state button{margin-top:10px}',
               
                // AI Tools styles
                '.ai-tools-container{max-width:800px;margin:0 auto}',
                '.ai-section, .page-section{background:#fafafa;border:1px solid #e0e0e0;padding:25px;margin-bottom:20px;border-radius:8px}',
                '.ai-section h4, .page-section h4{margin:0 0 20px 0;color:#333;font-size:16px;font-weight:600}',
                '.ai-section h5{margin:0 0 10px 0;color:#555;font-size:14px;font-weight:600}',
                '.ai-actions{display:flex;gap:15px;flex-wrap:wrap}',
                '.ai-button, .ai-button-small{padding:12px 24px;border:none;border-radius:6px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.2s;display:inline-flex;align-items:center;gap:8px}',
                '.ai-button-small{padding:6px 12px;font-size:12px}',
                '.button-icon{font-size:18px}',
                '.ai-button.primary{background:#4a90e2;color:#fff}',
                '.ai-button.primary:hover{background:#3a7bc8;transform:translateY(-1px);box-shadow:0 4px 12px rgba(74,144,226,0.3)}',
                '.ai-button.success{background:#5cb85c;color:#fff}',
                '.ai-button.success:hover{background:#4cae4c}',
                '.ai-button.secondary{background:#6c757d;color:#fff}',
                '.ai-button.secondary:hover{background:#5a6268}',
                '.ai-button:disabled{opacity:0.6;cursor:not-allowed;transform:none !important}',
                '.ai-result{margin-top:20px;background:#fff;border:1px solid #ddd;border-radius:8px;overflow:hidden}',
                '.ai-result-header{background:#f8f9fa;padding:15px 20px;border-bottom:1px solid #e0e0e0;display:flex;justify-content:space-between;align-items:center}',
                '.ai-result-header h5{margin:0;color:#333;font-size:14px;font-weight:600}',
                '.ai-result-content{padding:20px;font-size:14px;line-height:1.8;color:#333;max-height:300px;overflow-y:auto}',
                '.ai-result-actions{padding:15px 20px;background:#f8f9fa;border-top:1px solid #e0e0e0;display:flex;gap:10px}',
                '.ai-status, .page-status{padding:15px 20px;margin-top:20px;border-radius:8px;font-size:14px;font-weight:500}',
                '.ai-status.success, .page-status.success{background:#d4edda;color:#155724;border:1px solid #c3e6cb}',
                '.ai-status.error, .page-status.error{background:#f8d7da;color:#721c24;border:1px solid #f5c6cb}',
                '.ai-status.info, .page-status.info{background:#d1ecf1;color:#0c5460;border:1px solid #bee5eb}',
                '.ai-loading{display:inline-block;width:16px;height:16px;border:2px solid #f3f3f3;border-top:2px solid #4a90e2;border-radius:50%;animation:spin 1s linear infinite;margin-left:10px}',
               
                // Tags styles
                '.tags-container{display:flex;flex-direction:column;gap:20px}',
                '.suggested-tags-section, .custom-tags-section, .selected-tags-section{background:#fff;padding:15px;border:1px solid #e0e0e0;border-radius:6px}',
                '.suggested-tags, .selected-tags{display:flex;flex-wrap:wrap;gap:8px;min-height:40px;padding:10px;background:#f8f9fa;border:1px solid #e0e0e0;border-radius:4px}',
                '.tag{padding:6px 12px;background:#e0e0e0;border-radius:20px;font-size:13px;cursor:pointer;transition:all 0.2s;display:inline-flex;align-items:center;gap:6px}',
                '.tag:hover{background:#d0d0d0;transform:translateY(-1px)}',
                '.tag.suggested{background:#e3f2fd;color:#1976d2}',
                '.tag.suggested:hover{background:#bbdefb}',
                '.tag.selected{background:#4a90e2;color:#fff}',
                '.tag-remove{font-size:16px;cursor:pointer;margin-left:4px;opacity:0.7}',
                '.tag-remove:hover{opacity:1}',
                '.custom-tag-input{display:flex;gap:10px;align-items:center}',
                '.custom-tag-input input{flex:1}',
                '.tags-actions{display:flex;gap:10px;margin-top:15px}',
               
                // Page Tools styles
                '.page-tools-container{max-width:800px;margin:0 auto}',
                '.form-group-inline{display:flex;gap:15px;align-items:center}',
                '.form-group-inline .form-input, .form-group-inline .form-select{flex:1}',
                '.form-input, .form-select{padding:10px 15px;border:1px solid #ddd;border-radius:6px;font-size:14px}',
                '.form-input:focus, .form-select:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 3px rgba(74,144,226,0.1)}',
                '.page-info{background:#e8f4fd;border:1px solid #bee5eb;padding:20px;border-radius:8px;margin-top:20px}',
                '.page-info h4{margin:0 0 15px 0;color:#0c5460}',
                '.info-item{font-size:14px;margin-bottom:8px}',
                '.info-item strong{color:#333}',
               
                // Responsive
                '@media (max-width: 900px){',
                '.tab-content.active{grid-template-columns:1fr}',
                '.leftmenu-controls{border-top:1px solid #e0e0e0;margin-top:20px}',
                '.tab-button{font-size:12px;padding:10px}',
                '.button-icon{font-size:16px}',
                '}'
            ].join('');
           
            $('<style>').text(css).appendTo('head');
        }
       
        // Bind tab events
        function bindTabEvents() {
            $('.tab-button').on('click', function() {
                var $btn = $(this);
                var targetTab = $btn.data('tab');
               
                // Update buttons
                $('.tab-button').removeClass('active');
                $btn.addClass('active');
               
                // Update content
                $('.tab-content').removeClass('active');
                $('#' + targetTab + '-tab').addClass('active');
               
                // Load menu data when switching to menu editor
                if (targetTab === 'menu-editor' && !LeftMenuEditor.menuData) {
                    loadMenuData();
                }
            });
        }
       
        // Bind AI events
        function bindAIEvents() {
            // Summarize
            $('#ai-summarize').on('click', function() {
                var $btn = $(this);
                $btn.prop('disabled', true).html('<span class="button-icon">⏳</span> Summarizing...');
               
                getPageContent(function(content) {
                    $.ajax({
                        url: 'https://chat.mdriven.net/data/summarize',
                        method: 'POST',
                        contentType: 'application/json',
                        data: JSON.stringify({ content: content }),
                        success: function(response) {
                            var summary = response.summary || response.result || response;
                            displayAIResult(summary, 'summary');
                            $btn.prop('disabled', false).html('<span class="button-icon">📝</span> Summarize Page');
                        },
                        error: function(xhr) {
                            showAIStatus('Error: ' + (xhr.responseText || 'Failed to summarize'), 'error');
                            $btn.prop('disabled', false).html('<span class="button-icon">📝</span> Summarize Page');
                        }
                    });
                });
            });
           
            // Fix spelling
            $('#ai-fix-spelling').on('click', function() {
                var $btn = $(this);
                $btn.prop('disabled', true).html('<span class="button-icon">⏳</span> Checking...');
               
                getPageContent(function(content) {
                    $.ajax({
                        url: 'https://chat.mdriven.net/data/fix-spelling',
                        method: 'POST',
                        contentType: 'application/json',
                        data: JSON.stringify({ content: content }),
                        success: function(response) {
                            var fixed = response.fixed_content || response.result || response;
                            displayAIResult(fixed, 'spelling');
                            $btn.prop('disabled', false).html('<span class="button-icon">✓</span> Fix Spelling');
                        },
                        error: function(xhr) {
                            showAIStatus('Error: ' + (xhr.responseText || 'Failed to fix spelling'), 'error');
                            $btn.prop('disabled', false).html('<span class="button-icon">✓</span> Fix Spelling');
                        }
                    });
                });
            });
           
            // Suggest tags
            $('#ai-suggest-tags').on('click', function() {
                var $btn = $(this);
                $btn.prop('disabled', true).html('<span class="button-icon">⏳</span> Analyzing...');
               
                getPageContent(function(content) {
                    $.ajax({
                        url: 'https://chat.mdriven.net/data/suggest-tags',
                        method: 'POST',
                        contentType: 'application/json',
                        data: JSON.stringify({ content: content }),
                        success: function(response) {
                            var tags = response.tags || [];
                            if (typeof tags === 'string') {
                                try {
                                    tags = JSON.parse(tags);
                                } catch(e) {
                                    tags = [];
                                }
                            }
                           
                            LeftMenuEditor.suggestedTags = tags;
                            displayTagsSuggestions(tags);
                            $('#tags-section').slideDown();
                            $btn.prop('disabled', false).html('<span class="button-icon">🏷️</span> Suggest Tags');
                        },
                        error: function(xhr) {
                            showAIStatus('Error: ' + (xhr.responseText || 'Failed to suggest tags'), 'error');
                            $btn.prop('disabled', false).html('<span class="button-icon">🏷️</span> Suggest Tags');
                        }
                    });
                });
            });
           
            // Copy result
            $('#ai-copy').on('click', function() {
                var text = $('.ai-result-content').text();
                copyToClipboard(text);
                $(this).text('✓ Copied!');
                setTimeout(function() {
                    $('#ai-copy').html('📋 Copy');
                }, 2000);
            });
           
            // Apply nutshell
            $('#ai-apply-nutshell').on('click', function() {
                var summary = $('.ai-result-content').text();
                addNutshellToPage(summary);
            });
           
            // Apply spelling corrections
            $('#ai-apply-spelling').on('click', function() {
                var correctedContent = $('.ai-result-content').text();
               
                LeftMenuEditor.api.postWithToken('csrf', {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    text: correctedContent,
                    summary: 'Applied spelling corrections',
                    contentformat: 'text/x-wiki',
                    contentmodel: 'wikitext'
                }).done(function() {
                    showAIStatus('Spelling corrections applied! Reloading...', 'success');
                    setTimeout(function() {
                        window.location.reload();
                    }, 1500);
                }).fail(function(err) {
                    showAIStatus('Failed to apply corrections: ' + (err.error ? err.error.info : err), 'error');
                });
            });
        }
       
        // Bind tags events
        function bindTagsEvents() {
            // Add custom tag on Enter
            $('#custom-tag-input').on('keypress', function(e) {
                if (e.which === 13) {
                    e.preventDefault();
                    $('#add-custom-tag').click();
                }
            });
           
            // Add custom tag button
            $('#add-custom-tag').on('click', function() {
                var tagText = $('#custom-tag-input').val().trim();
                if (tagText && !isTagSelected(tagText)) {
                    addTagToSelected(tagText, false);
                    $('#custom-tag-input').val('');
                }
            });
           
            // Apply tags to page
            $('#apply-tags').on('click', function() {
                if (LeftMenuEditor.selectedTags.length === 0) {
                    showAIStatus('Please select at least one tag', 'error');
                    return;
                }
               
                var $btn = $(this);
                $btn.prop('disabled', true).text('Applying tags...');
               
                addTagsToPage(LeftMenuEditor.selectedTags);
            });
           
            // Clear all tags
            $('#clear-tags').on('click', function() {
                LeftMenuEditor.selectedTags = [];
                updateSelectedTagsDisplay();
                $('.tag.suggested').removeClass('selected');
            });
        }
       
        // Display tags suggestions
        function displayTagsSuggestions(tags) {
            var $container = $('#suggested-tags');
            $container.empty();
           
            if (tags.length === 0) {
                $container.html('<span style="color:#999">No tags suggested</span>');
                return;
            }
           
            for (var i = 0; i < tags.length; i++) {
                var tag = tags[i];
                var $tag = $('<span>', {
                    'class': 'tag suggested',
                    'data-tag': tag,
                    'text': tag
                });
               
                $tag.on('click', function() {
                    toggleSuggestedTag($(this));
                });
               
                $container.append($tag);
            }
        }
       
        // Toggle suggested tag
        function toggleSuggestedTag($tag) {
            var tagText = $tag.data('tag');
           
            if ($tag.hasClass('selected')) {
                $tag.removeClass('selected');
                removeTagFromSelected(tagText);
            } else {
                $tag.addClass('selected');
                addTagToSelected(tagText, true);
            }
        }
       
        // Add tag to selected
        function addTagToSelected(tagText, isSuggested) {
            if (!isTagSelected(tagText)) {
                LeftMenuEditor.selectedTags.push(tagText);
                updateSelectedTagsDisplay();
            }
        }
       
        // Remove tag from selected
        function removeTagFromSelected(tagText) {
            var newTags = [];
            for (var i = 0; i < LeftMenuEditor.selectedTags.length; i++) {
                if (LeftMenuEditor.selectedTags[i] !== tagText) {
                    newTags.push(LeftMenuEditor.selectedTags[i]);
                }
            }
            LeftMenuEditor.selectedTags = newTags;
            updateSelectedTagsDisplay();
        }
       
        // Check if tag is selected
        function isTagSelected(tagText) {
            return LeftMenuEditor.selectedTags.indexOf(tagText) !== -1;
        }
       
        // Update selected tags display
        function updateSelectedTagsDisplay() {
            var $container = $('#selected-tags');
            $container.empty();
           
            if (LeftMenuEditor.selectedTags.length === 0) {
                $container.html('<span style="color:#999">No tags selected</span>');
                return;
            }
           
            for (var i = 0; i < LeftMenuEditor.selectedTags.length; i++) {
                var tag = LeftMenuEditor.selectedTags[i];
                var $tag = $('<span>', {
                    'class': 'tag selected',
                    'html': tag + '<span class="tag-remove">×</span>'
                });
               
                (function(tagText) {
                    $tag.find('.tag-remove').on('click', function(e) {
                        e.stopPropagation();
                        removeTagFromSelected(tagText);
                        // Also unselect from suggested tags
                        $('.tag.suggested[data-tag="' + tagText + '"]').removeClass('selected');
                    });
                })(tag);
               
                $container.append($tag);
            }
        }
       
        // Add tags to page
        function addTagsToPage(tags) {
            var tagsMarkup = '<tags> ' + tags.join(', ') + ' </tags>\n\n';
           
            getPageContent(function(content) {
                // Check if tags already exist
                var tagsRegex = /<tags>[\s\S]*?<\/tags>/;
                var newContent;
               
                if (tagsRegex.test(content)) {
                    // Replace existing tags
                    newContent = content.replace(tagsRegex, tagsMarkup.trim());
                } else {
                    // Add tags after nutshell if exists, otherwise at the beginning
                    var nutshellRegex = /<nutshell>[\s\S]*?<\/nutshell>/;
                    if (nutshellRegex.test(content)) {
                        newContent = content.replace(nutshellRegex, function(match) {
                            return match + '\n\n' + tagsMarkup.trim();
                        });
                    } else {
                        newContent = tagsMarkup + content;
                    }
                }
               
                LeftMenuEditor.api.postWithToken('csrf', {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    text: newContent,
                    summary: 'Updated page tags',
                    contentformat: 'text/x-wiki',
                    contentmodel: 'wikitext'
                }).done(function() {
                    showAIStatus('Tags applied successfully! Reloading...', 'success');
                    setTimeout(function() {
                        window.location.reload();
                    }, 1500);
                }).fail(function(err) {
                    showAIStatus('Failed to apply tags: ' + (err.error ? err.error.info : err), 'error');
                    $('#apply-tags').prop('disabled', false).text('Apply Tags to Page');
                });
            });
        }
       
        // Bind page tools events
        function bindPageToolsEvents() {
            // Rename page
            $('#rename-page').on('click', function() {
                var newName = $('#new-page-name').val().trim();
                if (!newName) {
                    showPageStatus('Please enter a new page name', 'error');
                    return;
                }
               
                var $btn = $(this);
                $btn.prop('disabled', true).text('Renaming...');
               
                renamePage(newName, function(success, error) {
                    if (success) {
                        showPageStatus('Page renamed successfully! Redirecting...', 'success');
                        setTimeout(function() {
                            window.location.href = mw.util.getUrl(newName);
                        }, 1500);
                    } else {
                        showPageStatus('Error: ' + error, 'error');
                        $btn.prop('disabled', false).text('Rename');
                    }
                });
            });
           
            // Move namespace
            $('#move-namespace').on('click', function() {
                var targetNs = $('#target-namespace').val();
                if (!targetNs && targetNs !== '0') {
                    showPageStatus('Please select a namespace', 'error');
                    return;
                }
               
                var $btn = $(this);
                $btn.prop('disabled', true).text('Moving...');
               
                moveToNamespace(targetNs, function(success, error) {
                    if (success) {
                        showPageStatus('Page moved successfully! Redirecting...', 'success');
                        setTimeout(function() {
                            window.location.reload();
                        }, 1500);
                    } else {
                        showPageStatus('Error: ' + error, 'error');
                        $btn.prop('disabled', false).text('Move Page');
                    }
                });
            });
        }
       
        // Helper functions
        function copyToClipboard(text) {
            var $temp = $('<textarea>');
            $('body').append($temp);
            $temp.val(text).select();
            document.execCommand('copy');
            $temp.remove();
        }
       
        function getPageContent(callback) {
            LeftMenuEditor.api.get({
                action: 'query',
                prop: 'revisions',
                titles: mw.config.get('wgPageName'),
                rvprop: 'content',
                rvslots: 'main',
                formatversion: 2
            }).done(function(data) {
                var content = '';
                if (data.query && data.query.pages && data.query.pages[0]) {
                    var page = data.query.pages[0];
                    if (page.revisions && page.revisions[0]) {
                        content = page.revisions[0].slots.main.content || '';
                    }
                }
                callback(content);
            }).fail(function() {
                showAIStatus('Failed to get page content', 'error');
                callback('');
            });
        }
       
        function displayAIResult(content, type) {
            $('.ai-result-content').text(content);
            $('#ai-result').slideDown();
           
            // Show appropriate action button
            $('#ai-apply-nutshell').toggle(type === 'summary');
            $('#ai-apply-spelling').toggle(type === 'spelling');
        }
       
        function addNutshellToPage(summary) {
            var nutshell = '<nutshell> ' + summary + ' </nutshell>\n\n';
           
            getPageContent(function(content) {
                var newContent = nutshell + content;
               
                LeftMenuEditor.api.postWithToken('csrf', {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    text: newContent,
                    summary: 'Added AI-generated summary in nutshell',
                    contentformat: 'text/x-wiki',
                    contentmodel: 'wikitext'
                }).done(function() {
                    showAIStatus('Nutshell added successfully! Reloading...', 'success');
                    setTimeout(function() {
                        window.location.reload();
                    }, 1500);
                }).fail(function(err) {
                    showAIStatus('Failed to add nutshell: ' + (err.error ? err.error.info : err), 'error');
                });
            });
        }
       
        function loadNamespaces() {
            LeftMenuEditor.api.get({
                action: 'query',
                meta: 'siteinfo',
                siprop: 'namespaces',
                formatversion: 2
            }).done(function(data) {
                var $select = $('#target-namespace');
                $select.empty();
               
                $select.append('<option value="0">(Main)</option>');
               
                if (data.query && data.query.namespaces) {
                    for (var id in data.query.namespaces) {
                        var ns = data.query.namespaces[id];
                        if (ns.id >= 0 && ns.id !== 0 && ns.canonical !== 'Special' && ns.canonical !== 'Media') {
                            $select.append('<option value="' + ns.id + '">' + (ns.name || ns.canonical) + '</option>');
                        }
                    }
                }
               
                var currentNsId = mw.config.get('wgNamespaceNumber');
                $select.val(currentNsId);
            });
        }
       
        function renamePage(newName, callback) {
            LeftMenuEditor.api.postWithToken('csrf', {
                action: 'move',
                from: mw.config.get('wgPageName'),
                to: newName,
                reason: 'Renamed via Wiki Tools',
                movetalk: true,
                movesubpages: true
            }).done(function() {
                callback(true);
            }).fail(function(err) {
                callback(false, err.error ? err.error.info : 'Unknown error');
            });
        }
       
        function moveToNamespace(targetNsId, callback) {
            var nsInfo = mw.config.get('wgFormattedNamespaces');
            var targetPrefix = '';
           
            if (targetNsId !== '0' && nsInfo && nsInfo[targetNsId]) {
                targetPrefix = nsInfo[targetNsId] + ':';
            }
           
            var currentTitle = mw.config.get('wgTitle');
            var newTitle = targetPrefix + currentTitle;
           
            LeftMenuEditor.api.postWithToken('csrf', {
                action: 'move',
                from: mw.config.get('wgPageName'),
                to: newTitle,
                reason: 'Moved to ' + (targetPrefix || 'Main') + ' namespace via Wiki Tools',
                movetalk: true,
                movesubpages: true
            }).done(function() {
                callback(true);
            }).fail(function(err) {
                callback(false, err.error ? err.error.info : 'Unknown error');
            });
        }
       
        function showAIStatus(msg, type) {
            $('.ai-status')
                .removeClass('success error info')
                .addClass(type)
                .text(msg)
                .slideDown()
                .delay(5000)
                .slideUp();
        }
       
        function showPageStatus(msg, type) {
            $('.page-status')
                .removeClass('success error info')
                .addClass(type)
                .text(msg)
                .slideDown()
                .delay(5000)
                .slideUp();
        }
        // Parse and render menu structure
        function parseMenuItem(key, value, level) {
            level = level || 0;
           
            // Handle different value types
            if (value === null || value === undefined || value === '') {
                // Item with no value
                return createVisualItem(key, '', 'item', level);
            } else if (typeof value === 'string') {
                // String value
                if (key.indexOf('//') === 0) {
                    return createVisualItem(key, value, 'direct', level);
                } else {
                    return createVisualItem(key, value, 'item', level);
                }
            } else if (Array.isArray(value)) {
                // Array handling
                if (value.length === 0) {
                    return createVisualItem(key, '', 'item', level);
                } else if (value.length === 1 && typeof value[0] === 'string') {
                    return createVisualItem(key, value[0], 'item', level);
                } else {
                    // Create section for array with multiple items
                    var $section = createVisualSection(key, level);
                    var $items = $section.find('.leftmenu-section-items');
                   
                    for (var i = 0; i < value.length; i++) {
                        if (typeof value[i] === 'string') {
                            $items.append(createVisualItem(value[i], value[i], 'item', level + 1));
                        } else if (typeof value[i] === 'object') {
                            for (var subKey in value[i]) {
                                if (value[i].hasOwnProperty(subKey)) {
                                    $items.append(parseMenuItem(subKey, value[i][subKey], level + 1));
                                }
                            }
                        }
                    }
                    return $section;
                }
            } else if (typeof value === 'object' && value !== null) {
                // Object - create section
                if (key.indexOf('//') === 0 && Object.keys(value).length === 0) {
                    return createVisualItem(key, '', 'direct', level);
                }
               
                var $section = createVisualSection(key, level);
                var $items = $section.find('.leftmenu-section-items');
               
                // Process nested items
                for (var subKey in value) {
                    if (value.hasOwnProperty(subKey)) {
                        $items.append(parseMenuItem(subKey, value[subKey], level + 1));
                    }
                }
               
                return $section;
            }
           
            // Fallback
            return createVisualItem(key, String(value), 'item', level);
        }
        // Render visual menu
        function renderVisualMenu() {
            var $preview = LeftMenuEditor.$preview;
            var $empty = $('.leftmenu-empty-state');
           
            $preview.empty();
           
            // Check if menuData is null or empty
            if (!LeftMenuEditor.menuData || Object.keys(LeftMenuEditor.menuData).length === 0) {
                $preview.hide();
                $empty.show();
                console.log('Showing empty state - menuData is:', LeftMenuEditor.menuData);
            } else {
                $preview.show();
                $empty.hide();
                console.log('Rendering menu with data:', LeftMenuEditor.menuData);
               
                // Render each top-level item
                for (var key in LeftMenuEditor.menuData) {
                    if (LeftMenuEditor.menuData.hasOwnProperty(key)) {
                        var $element = parseMenuItem(key, LeftMenuEditor.menuData[key], 0);
                        if ($element) {
                            $preview.append($element);
                        }
                    }
                }
               
                makeSortable();
                updateSectionCounts();
            }
        }
        // Create visual item
        function createVisualItem(key, value, type, level) {
            var displayText = key;
            var targetPage = value || key;
           
            // Parse display text
            if (type === 'direct' && key.match(/^\/\/(.+?)\s*\|\s*(.+)$/)) {
                var match = key.match(/^\/\/(.+?)\s*\|\s*(.+)$/);
                displayText = match[2].trim();
                targetPage = match[1].trim();
            } else if (value && typeof value === 'string') {
                if (value.indexOf('|') > -1) {
                    var parts = value.split('|');
                    targetPage = parts[0].trim();
                    displayText = parts[1].trim();
                } else if (value.match(/^\[([^\]]+)\]\s*\|\s*(.+)$/)) {
                    var bracketMatch = value.match(/^\[([^\]]+)\]\s*\|\s*(.+)$/);
                    targetPage = bracketMatch[1];
                    displayText = bracketMatch[2];
                }
            }
           
            var isCurrentPage = (targetPage === LeftMenuEditor.currentPage ||
                              targetPage === LeftMenuEditor.pageName ||
                              key === LeftMenuEditor.currentPage ||
                              key === LeftMenuEditor.pageName);
           
            var icon = type === 'direct' ? '→' : '•';
           
            var $item = $('<div>', {
                'class': 'leftmenu-visual-item' + (type === 'direct' ? ' direct-link' : '') +
                        (isCurrentPage ? ' is-current-page' : ''),
                'data-key': key,
                'data-value': value || '',
                'data-type': type,
                'data-level': level
            }).css('margin-left', (level * 20) + 'px').html(
                '<span><span class="leftmenu-icon">' + icon + '</span>' + escapeHtml(displayText) + '</span>' +
                '<div class="leftmenu-item-actions">' +
                    '<button class="leftmenu-item-duplicate" title="Duplicate">⊕</button>' +
                    '<button class="leftmenu-item-edit" title="Edit">✎</button>' +
                    '<button class="leftmenu-item-delete" title="Delete">×</button>' +
                '</div>'
            );
           
            // Event handlers
            $item.on('click', function(e) {
                if (!$(e.target).closest('.leftmenu-item-actions').length) {
                    selectItem($item);
                }
            });
           
            $item.find('.leftmenu-item-edit').on('click', function(e) {
                e.stopPropagation();
                editItemInline($item);
            });
           
            $item.find('.leftmenu-item-delete').on('click', function(e) {
                e.stopPropagation();
                deleteItem($item);
            });
           
            $item.find('.leftmenu-item-duplicate').on('click', function(e) {
                e.stopPropagation();
                duplicateItem($item);
            });
           
            return $item;
        }
        // Create visual section
        function createVisualSection(title, level) {
            var $section = $('<div>', {
                'class': 'leftmenu-visual-section',
                'data-section': title,
                'data-level': level
            }).css('margin-left', (level * 20) + 'px').html(
                '<div class="leftmenu-visual-section-header">' +
                    '<span class="leftmenu-section-toggle">▼</span>' +
                    '<span>' + escapeHtml(title) + '</span>' +
                    '<div class="leftmenu-item-actions" style="margin-left:auto">' +
                        '<button class="leftmenu-item-edit" title="Rename">✎</button>' +
                        '<button class="leftmenu-item-delete" title="Delete">×</button>' +
                    '</div>' +
                '</div>' +
                '<div class="leftmenu-section-items"></div>'
            );
           
            $section.find('.leftmenu-visual-section-header').on('click', function(e) {
                if (!$(e.target).closest('.leftmenu-item-actions').length) {
                    $section.toggleClass('collapsed');
                }
            });
           
            $section.find('.leftmenu-item-edit').on('click', function(e) {
                e.stopPropagation();
                editSectionInline($section);
            });
           
            $section.find('.leftmenu-item-delete').on('click', function(e) {
                e.stopPropagation();
                deleteSection($section);
            });
           
            return $section;
        }
        // Update section counts
        function updateSectionCounts() {
            $('.leftmenu-visual-section').each(function() {
                var $section = $(this);
                var count = $section.find('.leftmenu-section-items > *').length;
                var $header = $section.find('.leftmenu-visual-section-header');
               
                $header.find('.leftmenu-item-count').remove();
                if (count > 0) {
                    var $count = $('<span class="leftmenu-item-count">' + count + '</span>');
                    $header.find('.leftmenu-item-actions').before($count);
                }
            });
        }
        // Select item
        function selectItem($item) {
            $('.leftmenu-visual-item, .leftmenu-visual-section').removeClass('selected');
            $item.addClass('selected');
        }
        // Edit item inline
        function editItemInline($item) {
            var $span = $item.find('span').first();
            var currentText = $span.text().replace(/^[•→]\s*/, '');
           
            var $input = $('<input>', {
                'type': 'text',
                'class': 'leftmenu-form-input',
                'value': currentText,
                'style': 'width:calc(100% - 100px);margin:0'
            });
           
            $span.html($input);
            $input.focus().select();
           
            function saveEdit() {
                var newText = $input.val().trim();
                if (newText && newText !== currentText) {
                    updateItemDisplay($item, newText);
                    showStatus('Item updated', 'success');
                } else {
                    $span.html('<span class="leftmenu-icon">' +
                        ($item.hasClass('direct-link') ? '→' : '•') +
                        '</span>' + escapeHtml(currentText));
                }
            }
           
            $input.on('blur', saveEdit);
            $input.on('keypress', function(e) {
                if (e.which === 13) {
                    e.preventDefault();
                    saveEdit();
                }
            });
        }
        // Update item display
        function updateItemDisplay($item, newDisplay) {
            var key = $item.data('key');
            var currentValue = $item.data('value') || '';
            var basePage = key;
           
            if (currentValue && currentValue.indexOf('|') > -1) {
                basePage = currentValue.split('|')[0];
            } else if (currentValue.match(/^\[([^\]]+)\]/)) {
                basePage = currentValue.match(/^(\[[^\]]+\])/)[1];
            }
           
            var newValue = basePage + '|' + newDisplay;
            $item.data('value', newValue);
            $item.find('span').first().html(
                '<span class="leftmenu-icon">' +
                ($item.hasClass('direct-link') ? '→' : '•') +
                '</span>' + escapeHtml(newDisplay)
            );
           
            updateMenuFromVisual();
        }
        // Delete item
        function deleteItem($item) {
            var name = $item.find('span').first().text().replace(/^[•→]\s*/, '');
            if (confirm('Delete "' + name + '"?')) {
                $item.slideUp(200, function() {
                    $(this).remove();
                    updateMenuFromVisual();
                    updateSectionCounts();
                    showStatus('Item deleted', 'success');
                });
            }
        }
        // Duplicate item
        function duplicateItem($item) {
            var key = $item.data('key');
            var value = $item.data('value');
            var level = $item.data('level') || 0;
            var newKey = key + '_copy';
            var counter = 1;
           
            // Find unique key
            while (isKeyExists(newKey)) {
                counter++;
                newKey = key + '_copy' + counter;
            }
           
            // Clone and insert
            var $clone = $item.clone();
            $clone.data('key', newKey);
            $clone.data('level', level); // Preserve the level
            $clone.css('margin-left', (level * 20) + 'px'); // Apply correct margin
            $clone.insertAfter($item);
           
            // Re-bind events
            bindItemEvents($clone);
           
            // Update and highlight
            updateMenuFromVisual();
            $clone.hide().slideDown(200);
            showStatus('Item duplicated', 'success');
        }
        // Edit section inline
        function editSectionInline($section) {
            var $header = $section.find('.leftmenu-visual-section-header');
            var $span = $header.find('span').eq(1);
            var currentName = $section.data('section');
           
            var $input = $('<input>', {
                'type': 'text',
                'class': 'leftmenu-form-input',
                'value': currentName,
                'style': 'width:200px;margin:0'
            });
           
            $span.html($input);
            $input.focus().select();
           
            function saveEdit() {
                var newName = $input.val().trim();
                if (newName && newName !== currentName) {
                    $section.data('section', newName);
                    $span.text(newName);
                    updateMenuFromVisual();
                    showStatus('Section renamed', 'success');
                } else {
                    $span.text(currentName);
                }
            }
           
            $input.on('blur', saveEdit);
            $input.on('keypress', function(e) {
                if (e.which === 13) {
                    e.preventDefault();
                    saveEdit();
                }
            });
        }
        // Delete section
        function deleteSection($section) {
            var name = $section.data('section');
            var itemCount = $section.find('.leftmenu-section-items > *').length;
           
            var message = 'Delete section "' + name + '"?';
            if (itemCount > 0) {
                message += '\n\nThis will also delete ' + itemCount + ' item' + (itemCount > 1 ? 's' : '') + '.';
            }
           
            if (confirm(message)) {
                $section.slideUp(200, function() {
                    $(this).remove();
                    updateMenuFromVisual();
                    showStatus('Section deleted', 'success');
                });
            }
        }
        // Make sortable
        function makeSortable() {
            $('.leftmenu-preview-tree, .leftmenu-section-items').sortable({
                items: '> .leftmenu-visual-item, > .leftmenu-visual-section',
                connectWith: '.leftmenu-preview-tree, .leftmenu-section-items',
                placeholder: 'leftmenu-drag-placeholder',
                tolerance: 'pointer',
                cursor: 'move',
                start: function(event, ui) {
                    ui.item.addClass('leftmenu-dragging');
                },
                stop: function(event, ui) {
                    ui.item.removeClass('leftmenu-dragging');
                   
                    // Get the new parent container
                    var $newParent = ui.item.parent();
                    var newLevel = 0;
                   
                    // Calculate new level based on parent
                    if ($newParent.hasClass('leftmenu-section-items')) {
                        // Find the parent section
                        var $parentSection = $newParent.closest('.leftmenu-visual-section');
                        newLevel = parseInt($parentSection.data('level') || 0) + 1;
                    }
                   
                    // Update the item's level
                    ui.item.data('level', newLevel);
                    ui.item.css('margin-left', (newLevel * 20) + 'px');
                   
                    // If this is a section, update all children's levels recursively
                    if (ui.item.hasClass('leftmenu-visual-section')) {
                        updateChildLevels(ui.item, newLevel);
                    }
                   
                    updateMenuFromVisual();
                    updateSectionCounts();
                }
            });
        }
       
        // Update child levels recursively
        function updateChildLevels($section, parentLevel) {
            var childLevel = parentLevel + 1;
            $section.find('> .leftmenu-section-items > *').each(function() {
                var $child = $(this);
                $child.data('level', childLevel);
                $child.css('margin-left', (childLevel * 20) + 'px');
               
                if ($child.hasClass('leftmenu-visual-section')) {
                    updateChildLevels($child, childLevel);
                }
            });
        }
        // Update menu from visual
        function updateMenuFromVisual() {
            var newData = {};
           
            function processLevel($container, targetObj) {
                $container.children().each(function() {
                    var $elem = $(this);
                   
                    if ($elem.hasClass('leftmenu-visual-section')) {
                        var sectionTitle = $elem.data('section');
                        var sectionData = {};
                       
                        processLevel($elem.find('.leftmenu-section-items').first(), sectionData);
                       
                        targetObj[sectionTitle] = sectionData;
                    } else if ($elem.hasClass('leftmenu-visual-item')) {
                        var key = $elem.data('key');
                        var value = $elem.data('value');
                       
                        if (!value || value === key) {
                            targetObj[key] = key;
                        } else {
                            targetObj[key] = value;
                        }
                    }
                });
            }
           
            processLevel(LeftMenuEditor.$preview, newData);
            LeftMenuEditor.menuData = newData;
        }
        // Show add form
        function showAddForm(type) {
            var $panel = $('.leftmenu-action-panel');
            var $form = $panel.find('.leftmenu-form');
           
            $panel.slideDown();
           
            if (type === 'section') {
                $form.html(
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Section Name</label>' +
                        '<input type="text" class="leftmenu-form-input" id="leftmenu-section-name" placeholder="e.g., Documentation">' +
                    '</div>' +
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Parent Section (optional)</label>' +
                        '<select class="leftmenu-form-select" id="leftmenu-parent-section">' +
                            '<option value="">[Root Level]</option>' +
                        '</select>' +
                    '</div>' +
                    '<div style="display:flex;gap:10px">' +
                        '<button class="leftmenu-button primary" id="leftmenu-confirm-add">Add Section</button>' +
                        '<button class="leftmenu-button secondary" id="leftmenu-cancel-add">Cancel</button>' +
                    '</div>'
                );
               
                // Populate sections
                populateSections('#leftmenu-parent-section');
               
                $('#leftmenu-confirm-add').on('click', function() {
                    confirmAddSection();
                });
               
            } else if (type === 'page') {
                $form.html(
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Page Name</label>' +
                        '<input type="text" class="leftmenu-form-input" id="leftmenu-page-name" placeholder="e.g., Help:Contents">' +
                    '</div>' +
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Display Name (optional)</label>' +
                        '<input type="text" class="leftmenu-form-input" id="leftmenu-display-name" placeholder="e.g., Help & Support">' +
                    '</div>' +
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Add to Section</label>' +
                        '<select class="leftmenu-form-select" id="leftmenu-target-section">' +
                            '<option value="">[Root Level]</option>' +
                        '</select>' +
                    '</div>' +
                    '<div style="display:flex;gap:10px">' +
                        '<button class="leftmenu-button primary" id="leftmenu-confirm-add">Add Page</button>' +
                        '<button class="leftmenu-button secondary" id="leftmenu-cancel-add">Cancel</button>' +
                    '</div>'
                );
               
                populateSections('#leftmenu-target-section');
               
                $('#leftmenu-confirm-add').on('click', function() {
                    confirmAddPage();
                });
            }
           
            $('#leftmenu-cancel-add').on('click', function() {
                $panel.slideUp();
            });
           
            setTimeout(function() {
                $form.find('input:first').focus();
            }, 300);
        }
        // Populate sections dropdown
        function populateSections(selector) {
            var $select = $(selector);
           
            function addOptions(obj, prefix, level) {
                for (var key in obj) {
                    if (obj.hasOwnProperty(key) && typeof obj[key] === 'object' &&
                        !Array.isArray(obj[key]) && key.indexOf('//') !== 0) {
                        var indent = '';
                        for (var i = 0; i < level; i++) indent += ' ';
                        $select.append('<option value="' + prefix + key + '">' + indent + key + '</option>');
                        addOptions(obj[key], prefix + key + ' > ', level + 1);
                    }
                }
            }
           
            addOptions(LeftMenuEditor.menuData, '', 0);
        }
        // Confirm add section
        function confirmAddSection() {
            var name = $('#leftmenu-section-name').val().trim();
            var parent = $('#leftmenu-parent-section').val();
           
            if (!name) {
                showStatus('Please enter a section name', 'error');
                return;
            }
           
            var target = LeftMenuEditor.menuData;
            if (parent) {
                var parts = parent.split(' > ');
                for (var i = 0; i < parts.length; i++) {
                    if (!target[parts[i]]) target[parts[i]] = {};
                    target = target[parts[i]];
                }
            }
           
            if (target[name]) {
                showStatus('Section already exists', 'error');
                return;
            }
           
            target[name] = {};
           
            renderVisualMenu();
            showStatus('Section added', 'success');
            $('.leftmenu-action-panel').slideUp();
        }
        // Confirm add page
        function confirmAddPage() {
            var pageName = $('#leftmenu-page-name').val().trim();
            var displayName = $('#leftmenu-display-name').val().trim() || pageName;
            var section = $('#leftmenu-target-section').val();
           
            if (!pageName) {
                showStatus('Please enter a page name', 'error');
                return;
            }
           
            var target = LeftMenuEditor.menuData;
            if (section) {
                var parts = section.split(' > ');
                for (var i = 0; i < parts.length; i++) {
                    if (!target[parts[i]]) target[parts[i]] = {};
                    target = target[parts[i]];
                }
            }
           
            var value = displayName !== pageName ? pageName + '|' + displayName : pageName;
            target[pageName] = value;
           
            renderVisualMenu();
            showStatus('Page added', 'success');
            $('.leftmenu-action-panel').slideUp();
        }
        // Add current page
        function addCurrentPage() {
            if (isPageInMenu()) {
                showStatus('This page is already in the menu', 'error');
                return;
            }
           
            // Create a temporary draggable item
            var $item = createVisualItem(
                LeftMenuEditor.pageName,
                LeftMenuEditor.currentPage,
                'item',
                0
            );
           
            $item.css('background', '#e8f4fd').css('border-color', '#4a90e2');
           
            // Create a placeholder message
            var $placeholder = $('<div class="leftmenu-drag-message" style="text-align:center;padding:20px;background:#f0f8ff;border:2px dashed #4a90e2;margin:10px 0;border-radius:4px;">' +
                '<strong>Drag the item below to any section or position</strong>' +
                '</div>');
           
            LeftMenuEditor.$preview.prepend($placeholder);
            LeftMenuEditor.$preview.prepend($item);
           
            showStatus('Drag the current page to position it in the menu', 'info');
           
            // Make it draggable but still connected to sortable
            makeSortable(); // Re-initialize sortable to include the new item
           
            // Remove placeholder when drag starts
            $item.on('sortstart', function() {
                $placeholder.remove();
            });
           
            // The sortable stop event in makeSortable() will handle the level updates
        }
        // Re-bind events
        function bindItemEvents($item) {
            $item.off('click').on('click', function(e) {
                if (!$(e.target).closest('.leftmenu-item-actions').length) {
                    selectItem($item);
                }
            });
           
            $item.find('.leftmenu-item-edit').off('click').on('click', function(e) {
                e.stopPropagation();
                editItemInline($item);
            });
           
            $item.find('.leftmenu-item-delete').off('click').on('click', function(e) {
                e.stopPropagation();
                deleteItem($item);
            });
           
            $item.find('.leftmenu-item-duplicate').off('click').on('click', function(e) {
                e.stopPropagation();
                duplicateItem($item);
            });
        }
        // Check if key exists
        function isKeyExists(key) {
            function check(obj) {
                for (var k in obj) {
                    if (obj.hasOwnProperty(k)) {
                        if (k === key) return true;
                        if (typeof obj[k] === 'object' && check(obj[k])) return true;
                    }
                }
                return false;
            }
            return check(LeftMenuEditor.menuData);
        }
        // Check if page in menu
        function isPageInMenu() {
            var targets = [LeftMenuEditor.currentPage, LeftMenuEditor.pageName];
           
            function walk(obj) {
                for (var k in obj) {
                    if (obj.hasOwnProperty(k)) {
                        for (var i = 0; i < targets.length; i++) {
                            if (k === targets[i]) return true;
                        }
                       
                        var v = obj[k];
                        if (typeof v === 'string') {
                            var page = v.split('|')[0].replace(/\[|\]/g, '');
                            for (var j = 0; j < targets.length; j++) {
                                if (page === targets[j] || v === targets[j]) return true;
                            }
                        } else if (Array.isArray(v)) {
                            for (var a = 0; a < v.length; a++) {
                                if (typeof v[a] === 'string') {
                                    for (var t = 0; t < targets.length; t++) {
                                        if (v[a] === targets[t]) return true;
                                    }
                                }
                            }
                        } else if (typeof v === 'object' && v !== null) {
                            if (walk(v)) return true;
                        }
                    }
                }
                return false;
            }
           
            return walk(LeftMenuEditor.menuData);
        }
        // Load menu data
        function loadMenuData(callback) {
            var page = 'MediaWiki:Menu-' + LeftMenuEditor.namespace;
           
            showStatus('Loading menu from: ' + page, 'info');
            console.log('Loading from page:', page);
           
            LeftMenuEditor.api.get({
                action: 'query',
                prop: 'revisions',
                titles: page,
                rvprop: 'content',
                rvslots: 'main',
                formatversion: 2
            }).done(function (data) {
                console.log('API response:', data);
               
                var raw = '';
                // Check if page exists and has content
                if (data.query && data.query.pages && data.query.pages.length > 0) {
                    var page = data.query.pages[0];
                    console.log('Page data:', page);
                   
                    if (page.revisions && page.revisions.length > 0) {
                        var revision = page.revisions[0];
                        console.log('Revision data:', revision);
                       
                        if (revision.slots && revision.slots.main) {
                            raw = revision.slots.main.content || '';
                            console.log('Raw content:', raw);
                        }
                    } else if (page.missing) {
                        console.log('Page does not exist yet');
                        showStatus('Menu page does not exist yet. Add items to create it.', 'info');
                    }
                }
               
                // Parse JSON
                if (raw) {
                    try {
                        LeftMenuEditor.menuData = JSON.parse(raw);
                        console.log('Parsed menu data:', LeftMenuEditor.menuData);
                    } catch (e) {
                        console.error('Failed to parse menu JSON:', e);
                        console.error('Raw content that failed to parse:', raw);
                        LeftMenuEditor.menuData = {};
                        showStatus('Error parsing menu data: ' + e.message, 'error');
                    }
                } else {
                    LeftMenuEditor.menuData = {};
                    console.log('No content found, starting with empty menu');
                }
               
                renderVisualMenu();
                $('.leftmenu-status').fadeOut(3000);
                if (typeof callback === 'function') { callback(); }
            }).fail(function(error) {
                console.error('API request failed:', error);
                showStatus('Failed to load menu data: ' + (error.error ? error.error.info : 'Unknown error'), 'error');
                LeftMenuEditor.menuData = {};
                renderVisualMenu();
            });
        }
        // Save menu
        function saveMenu() {
            var page = 'MediaWiki:Menu-' + LeftMenuEditor.namespace;
            var json = JSON.stringify(LeftMenuEditor.menuData, null, 2);
            $('.leftmenu-save').prop('disabled', true).text('Saving...');
            LeftMenuEditor.api.postWithToken('csrf', {
                action: 'edit',
                title: page,
                text: json,
                summary: 'Updated menu structure',
                contentformat: 'text/x-wiki',
                contentmodel: 'wikitext'
            }).done(function () {
                showStatus('Menu saved successfully!', 'success');
                $('.leftmenu-save').text('Saved!');
                setTimeout(function () {
                    location.reload();
                }, 1500);
            }).fail(function (err) {
                showStatus('Failed to save: ' + (err.error ? err.error.info : err), 'error');
                $('.leftmenu-save').prop('disabled', false).text('Save Changes');
            });
        }
        // Reset menu
        function resetMenu() {
            if (confirm('Discard all changes and reload?')) {
                loadMenuData(function() {
                    showStatus('Menu reset', 'info');
                });
            }
        }
        // Toggle JSON view
        function toggleJsonView() {
            var $jsonView = $('.leftmenu-json-view');
            if ($jsonView.is(':visible')) {
                $jsonView.slideUp();
                $('.leftmenu-view-json').text('View JSON');
            } else {
                $jsonView.text(JSON.stringify(LeftMenuEditor.menuData, null, 2)).slideDown();
                $('.leftmenu-view-json').text('Hide JSON');
            }
        }
        // Show status
        function showStatus(msg, type) {
            $('.leftmenu-status')
                .removeClass('success error info')
                .addClass(type)
                .text(msg)
                .slideDown()
                .delay(3000)
                .slideUp();
        }
        // HTML escape
        function escapeHtml(text) {
            var map = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#039;'
            };
            return String(text).replace(/[&<>"']/g, function(m) { return map[m]; });
        }
        // Event bindings
        function bindEvents() {
            // Header toggle - make the container collapsible
            $('.leftmenu-editor-header').on('click', function() {
                $('.leftmenu-editor-container').toggleClass('collapsed');
                // Load menu data if expanding and on menu tab
                if (!$('.leftmenu-editor-container').hasClass('collapsed')) {
                    if ($('#menu-editor-tab').hasClass('active') && !LeftMenuEditor.menuData) {
                        loadMenuData();
                    }
                }
            });
           
            // Quick actions
            $('.leftmenu-quick-action').on('click', function() {
                var action = $(this).data('action');
               
                switch(action) {
                    case 'add-section':
                        showAddForm('section');
                        break;
                    case 'add-page':
                        showAddForm('page');
                        break;
                    case 'add-current':
                        addCurrentPage();
                        break;
                    case 'import':
                        showStatus('Import feature coming soon', 'info');
                        break;
                }
            });
           
            // Search
            $('.leftmenu-search').on('input', function() {
                var query = $(this).val().toLowerCase();
               
                $('.leftmenu-visual-item, .leftmenu-visual-section').each(function() {
                    var $item = $(this);
                    var text = $item.text().toLowerCase();
                   
                    if (!query || text.indexOf(query) > -1) {
                        $item.show();
                        // Show parent sections
                        if (query) {
                            $item.parents('.leftmenu-visual-section').show().removeClass('collapsed');
                        }
                    } else {
                        $item.hide();
                    }
                });
            });
           
            // Empty state button
            $('.leftmenu-empty-add').on('click', function() {
                showAddForm('page');
            });
           
            // Control buttons
            $('.leftmenu-save').on('click', saveMenu);
            $('.leftmenu-reset').on('click', resetMenu);
            $('.leftmenu-view-json').on('click', toggleJsonView);
        }
        // Initialize
        addStyles();
        createInterface();
        bindEvents();
    });
})(mediaWiki, jQuery);

Latest revision as of 12:59, 2 June 2025

This page was created by Edgar on 2023-10-09. Last edited by Edgar on 2025-06-02.
/* Any JavaScript here will be loaded for all users on every page load. */
$(document).ready(function () {
    $.get(mw.util.wikiScript('api'), {
        action: 'query',
        meta: 'userinfo',
        format: 'json'
    }).done(function (data) {
        if (data.query.userinfo.id !== 0) { 
            var username = data.query.userinfo.name;
            var userLink = mw.util.getUrl('User:' + username);
            var logoutLink = mw.util.getUrl('Special:Logout');
            $('#user-info').html('<a href="' + userLink + '" class="text-white">' + username + '</a>' + 
                                 ' &nbsp;|&nbsp; <a href="' + logoutLink + '" class="text-white">Logout</a>');
        }
    });
});


document.getElementById('offcanvas-toggler').addEventListener('click', function() {
    var sidebar = document.getElementById('offcanvas-menu');
    if (sidebar.classList.contains('show')) {
        sidebar.classList.remove('show');
    } else {
        sidebar.classList.add('show');
    }
});




$(document).ready(function() {
    $('#offcanvas-close').on('click', function() {
        $('#offcanvas-menu').removeClass('show');
    });
});

document.addEventListener('DOMContentLoaded', function() {
    var form = document.querySelector('.namespace-search-form');
    if (form) {
        form.addEventListener('submit', function(e) {
            var input = form.querySelector('#bs-extendedsearch-input');
            if (input) {
                var namespace = mw.config.get('wgCanonicalNamespace');
                if (namespace && namespace.length > 0) {
                    input.value = namespace + ": " + input.value;
                }
            }
        });
    }
});

(function($) {
    'use strict';

    // Updated CSS for suggestions
    var css = [
        '#suggestion-container {',
        '    position: relative;',
        '    width: 100%;',
        '}',
        '#suggestion-box {',
        '    position: absolute;',
        '    top: 100%;',
        '    left: 0;',
        '    width: 100%;',
        '    margin-top: 5px;',
        '    background-color: #fff;',
        '    border: 1px solid #ccc;',
        '    border-radius: 4px;',
        '    box-shadow: 0 2px 6px rgba(0,0,0,0.15);',
        '    z-index: 1000;',
        '}',
        '.suggestion-item {',
        '    padding: 8px;',
        '    cursor: pointer;',
        '}',
        '.suggestion-item:hover {',
        '    background-color: #e0e0e0;',
        '}'
    ].join('\n');

    // Add the CSS to the head
    $('head').append('<style type="text/css">' + css + '</style>');

    // Add suggestion container
    $('#suggestion-container').append('<div id="suggestion-box"></div>');

    // Show suggestions from the new API
    function showSuggestions() {
        var query = $(this).val().trim();
        if (query.length > 0) {
            // Updated API URL for new suggestions
            var apiUrl = "https://search-api.mdriven.net/wiki_suggestions?q=" + encodeURIComponent(query);

            // Fetch suggestions from the new API
            $.ajax({
                url: apiUrl,
                dataType: "json",
                method: "GET",
                success: function(data) {
                    var suggestions = data || [];
                    $('#suggestion-box').empty();

                    // Check if suggestions exist
                    if (suggestions.length === 0) {
                        $('#suggestion-box').hide();
                        return;
                    }

                    // Populate suggestions
                    $.each(suggestions, function(index, suggestion) {
                        var item = $('<div class="suggestion-item"></div>').text(suggestion);
                        $('#suggestion-box').append(item);
                    });

                    // Show suggestion box
                    $('#suggestion-box').show();
                },
                error: function(jqxhr, textStatus, error) {
                    console.error('Error fetching suggestions:', error);
                    $('#suggestion-box').hide();
                }
            });
        } else {
            $('#suggestion-box').empty().hide();
        }
    }

    // Hide suggestions when clicking outside
    function hideSuggestions(event) {
        if (!$(event.target).closest('#suggestion-container').length) {
            $('#suggestion-box').empty().hide();
        }
    }

    // Handle selecting a suggestion
    function selectSuggestion(event) {
        event.preventDefault(); // Prevent mousedown from losing focus
        var selectedText = $(this).text().trim();

        // Redirect to Special:CustomSearch with selected query
        window.location.href = '/index.php?title=' + encodeURIComponent(selectedText);
    }

    // Attach input listener to fetch suggestions
    $('.search-inputs').on('input', showSuggestions);

    // Hide suggestions when clicking anywhere outside
    $(document).on('click', hideSuggestions);

    // Handle suggestion click with mousedown
    $('#suggestion-box').on('mousedown', '.suggestion-item', selectSuggestion);

})(jQuery);


$(document).ready(function() {
    // Function to toggle a section open or closed
    function toggleSection(element) {
        var submenu = $(element).next('.submenu');
        submenu.toggle();
    }

    // Function to open the submenu containing the current page link and scroll to it
    function openCurrentPageSubmenuAndScroll() {
        var currentPageLink = $('#navMenu .current-page');
        if (currentPageLink.length) {
            // Open the parent submenu(s) of the current page link
            currentPageLink.parents('.submenu').show();

            // Delay the scrolling to allow for any dynamic layout changes
            setTimeout(function() {
                // Calculate the position of the current page link
                var position = currentPageLink.offset().top - $('#navMenu').offset().top + $('#navMenu').scrollTop();

                // Scroll the menu to the active item
                $('#navMenu').animate({
                    scrollTop: position
                }, 500);
            }, 100); // Delay of 100 milliseconds
        }
    }

    // Event delegation for dynamically loaded content
    $('#navMenu').on('click', '.menu-header', function() {
        toggleSection(this);
    });

    // Open the submenu containing the current page link and scroll to it
    openCurrentPageSubmenuAndScroll();
});

document.getElementById('menu-toggle').addEventListener('click', function() {
    var navMenu = document.getElementById('navMenu');
    var bodyContent = document.getElementById('bodyContent');

    if (navMenu.style.display === 'none' || navMenu.style.display === '') {
        navMenu.style.display = 'block';
        bodyContent.style.display = 'none';  // Hide body content when nav menu is displayed
    } else {
        navMenu.style.display = 'none';
        bodyContent.style.display = 'block';  // Show body content when nav menu is hidden
    }
});

$(document).ready(function() {
    $('.video__navigation .navigation-item').click(function() {
        var videoID = $(this).data('video');
        var startTime = $(this).data('start');
        var newSrc = 'https://www.youtube.com/embed/' + videoID + '?start=' + startTime + '&autoplay=1';
        
        $('.video__wrapper iframe').attr('src', newSrc);
    });
});

$(document).ready(function() {
        $('.bs-extendedsearch-filter-button-button').each(function() {
            $(this).append('<span class="fa fa-chevron-down"></span>');
        });
});

document.addEventListener("scroll", function() {
    var sidebar = document.getElementById("navMenu");
    var footerHeight = 100;
    var windowHeight = window.innerHeight;

    var scrollBottomPosition = window.scrollY + windowHeight;
    var footerTopPosition = document.documentElement.offsetHeight - footerHeight;

    if (scrollBottomPosition <= footerTopPosition) {
        sidebar.style.height = "100vh";
    } else {
        sidebar.style.height = "calc(100vh - 110px)";
    }
});

mw.loader.using('jquery', function() {
    $(document).ready(function() {
        var $toc = $('#toc').clone();
        $('#toc').remove(); 
        $('#tocContainer').html($toc);

   
        $('#tocContainer').css({
            position: '-webkit-sticky', 
            position: 'sticky',
            top: '0', 
            padding: '15px',
            margin: '0 auto', 
            borderRadius: '5px', 
            maxWidth: '280px',
            maxHeight: 'max-content',
            overflowY: 'auto',
            height: '90vh',
            zIndex: 1000
        });

        $('#tocContainer .toctitle').css({
            fontSize: '16px',
            fontWeight: '600',
            color: '#555',
            borderBottom: '1px solid #ccc',
            paddingBottom: '10px',
            marginBottom: '10px'
        });

        $('#tocContainer ul').css({
            margin: 0,
            padding: '0 0 0 20px',
            listStyleType: 'none',
            fontSize: '14px',
            lineHeight: '1.6' 
        });

        $('#tocContainer li').css({
            marginBottom: '5px', 
        });

        $('#tocContainer a').css({
            color: '#555', 
            textDecoration: 'none',
        }).hover(
            function() { $(this).css({textDecoration: 'underline', color: '#000'}); },
            function() { $(this).css({textDecoration: 'none', color: '#555'}); }

        );
    });
});

$(document).ready(function() {
    var $inputElement = $('.oo-ui-textInputWidget-type-search .oo-ui-inputWidget-input');
    if ($inputElement.length) {
        $inputElement.on('keydown', function(event) {
            if (event.key === 'Enter') {
                event.preventDefault();
                $inputElement.addClass('search-input');
            }
        });
    }
});

$(document).ready(function() {
    var $inputElement = $('.oo-ui-textInputWidget-type-search .oo-ui-inputWidget-input');
    if ($inputElement.length) {
        $inputElement.addClass('search-input');
        console.log('Class "search-input" added to the input element.');
    } else {
        console.log('Input element not found.');
    }
});

$(document).ready(function() {
        var signInLink = $('#user-info a');
        var currentUrl = encodeURIComponent(window.location.pathname + window.location.search + window.location.hash);
        signInLink.attr('href', signInLink.attr('href').replace('<CURRENT_URL>', currentUrl));
    });


document.addEventListener('DOMContentLoaded', function() {
    var images = document.querySelectorAll('.thumbimage');
    var overlay = document.createElement('div');
    overlay.className = 'image-overlay';
    document.body.appendChild(overlay);

    var overlayImage = document.createElement('img');
    overlay.appendChild(overlayImage);

    images.forEach(function(image) {
        image.addEventListener('click', function(event) {
            event.preventDefault();
            event.stopPropagation();

            overlayImage.src = image.src;
            overlay.classList.add('show');
        });
    });

    overlay.addEventListener('click', function() {
        overlay.classList.remove('show');
    });
});

// ==UserScript==
// @name        MediaWiki Clean Delete
// @namespace   MediaWikiScripts
// @description Adds a 'Clean Delete' action link to pages for admins to delete pages and clean up incoming links and redirects.
// ==/UserScript==

mw.loader.using(['mediawiki.api', 'mediawiki.util', 'jquery'], function () {
    function addCleanDeleteLink() {
        if (mw.config.get('wgUserGroups').indexOf('sysop') !== -1) {
            if ($('#ca-cleandelete').length === 0) {
                var $link = $('<div>').attr('id', 'ca-cleandelete').attr('class', 'mw-list-item').append(
                    $('<a>').attr('href', '#').attr('class', 'ca-cleandelete').text('Clean Delete').click(function (e) {
                        e.preventDefault();
                        gatherAllDecisions(mw.config.get('wgPageName'));
                    })
                );
                $('#p-actions .tab-group').append($link);
            }
        }
    }

    function gatherAllDecisions(pageTitle) {
        var decisions = {};
        showModal('Handle Links and Redirects', '<div class="form-group">' +
            '<label>Specify how you would like to handle all incoming links and redirects:</label>' +
            '<select id="link-handling-select" class="form-control">' +
                '<option value="delete">Delete Links and Redirects</option>' +
                '<option value="change">Change Target of Links and Redirects</option>' +
            '</select>' +
        '</div>', function () {
            var choice = $('#link-handling-select').val();
            if (choice === 'change') {
                showModal('Specify New Target', '<div class="form-group">' +
                    '<label>Enter the new target page name to update all links and redirects:</label>' +
                    '<input type="text" id="new-target-input" class="form-control" placeholder="Enter new target">' +
                '</div>', function () {
                    decisions.links = $('#new-target-input').val();
                    confirmDeletion(pageTitle, decisions);
                });
            } else {
                decisions.links = '';
                confirmDeletion(pageTitle, decisions);
            }
        });
    }

    function confirmDeletion(pageTitle, decisions) {
        showModal('Confirm Page Deletion', '<p>Are you sure you want to delete "' + pageTitle + '" after handling all links and redirects?</p>', function () {
            decisions.deletion = true;
            showLoadingDialog('Performing Cleanup', function (loadingDialog, updateLoadingText, logDetail) {
                executeAllActions(pageTitle, decisions, function () {
                    loadingDialog.close().closed.then(function() {
                        location.reload();
                    });
                }, updateLoadingText, logDetail);
            });
        });
    }

    function showModal(title, body, onConfirm) {
        var modal = $(
            '<div class="modal fade" tabindex="-1" role="dialog">' +
                '<div class="modal-dialog" role="document">' +
                    '<div class="modal-content">' +
                        '<div class="modal-header">' +
                            '<h5 class="modal-title">' + title + '</h5>' +
                            '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
                                '<span aria-hidden="true">&times;</span>' +
                            '</button>' +
                        '</div>' +
                        '<div class="modal-body">' + body + '</div>' +
                        '<div class="modal-footer">' +
                            '<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>' +
                            '<button type="button" class="btn btn-primary">Confirm</button>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
            '</div>'
        );

        modal.find('.btn-primary').click(function () {
            onConfirm();
            modal.modal('hide');
        });

        modal.on('hidden.bs.modal', function () {
            modal.remove();
        });

        $('body').append(modal);
        modal.modal('show');
    }

    function showLoadingDialog(message, callback) {
        var modal = $(
            '<div class="modal fade" tabindex="-1" role="dialog">' +
                '<div class="modal-dialog" role="document">' +
                    '<div class="modal-content">' +
                        '<div class="modal-header">' +
                            '<h5 class="modal-title">Performing Cleanup</h5>' +
                        '</div>' +
                        '<div class="modal-body">' +
                            '<p id="loading-text">' + message + '</p>' +
                            '<ul id="loading-log"></ul>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
            '</div>'
        );

        $('body').append(modal);
        modal.modal('show');

        callback(modal, function (text) {
            $('#loading-text').text(text);
            $('#loading-log').append('<li>' + text + '</li>');
        }, function (detail) {
            $('#loading-log').append('<li>' + detail + '</li>');
        });
    }

    function executeAllActions(pageTitle, decisions, callback, updateLoadingText, logDetail) {
        var api = new mw.Api();

        function handleLinksAndRedirects(action, newTarget, next) {
            updateLoadingText('Fetching backlinks...');
            api.get({
                action: 'query',
                list: 'backlinks',
                bltitle: pageTitle,
                bllimit: 'max',
                blfilterredir: 'all' // Include both redirects and non-redirects
            }).done(function (data) {
                logDetail('Backlinks fetched.');
                if (data.query.backlinks) {
                    var promises = $.map(data.query.backlinks, function (link) {
                        return new $.Deferred(function (defer) {
                            api.get({
                                action: 'parse',
                                page: link.title,
                                prop: 'wikitext'
                            }).done(function (linkData) {
                                var isRedirect = linkData.parse.wikitext['*'].trim().startsWith('#REDIRECT');
                                if (isRedirect) {
                                    if (action === 'update') {
                                        updateRedirectTarget(link.title, newTarget, api, defer.resolve, logDetail);
                                    } else {
                                        logDetail('Backlink ' + link.title + ' is a redirect. Deleting...');
                                        performDeletion(link.title, defer.resolve, logDetail);
                                    }
                                } else {
                                    if (action === 'update') {
                                        updateLinkInPage(link.title, pageTitle, newTarget, api, defer.resolve, logDetail);
                                    } else {
                                        removeLinkFromPage(link.title, pageTitle, api, defer.resolve, logDetail);
                                    }
                                }
                            }).fail(function (error) {
                                logDetail('Error checking if backlink ' + link.title + ' is a redirect: ' + error);
                                defer.resolve();
                            });
                        }).promise();
                    });
                    $.when.apply($, promises).then(function () {
                        updateLoadingText(action === 'update' ? 'All links updated.' : 'All links removed.');
                        next();
                    });
                } else {
                    next();
                }
            }).fail(function (error) {
                updateLoadingText('Error fetching backlinks: ' + error);
                next();
            });
        }

        function updateLinkInPage(linkedPageTitle, originalPageTitle, newTarget, api, resolve, logDetail) {
            api.get({
                action: 'parse',
                page: linkedPageTitle,
                prop: 'wikitext'
            }).then(function (data) {
                var wikitext = data.parse.wikitext['*'];
                var regex = new RegExp('\\[\\[' + originalPageTitle.replace(/[\[\]]/g, '\\$&') + '(\\|[^\\]]+)?\\]\\]', 'g');
                var newWikitext = wikitext.replace(regex, '[[' + newTarget + '$1]]');
                if (wikitext !== newWikitext) {
                    logDetail('Updating link in ' + linkedPageTitle);
                } else {
                    logDetail('No link found in ' + linkedPageTitle);
                }
                return api.postWithToken('csrf', {
                    action: 'edit',
                    title: linkedPageTitle,
                    text: newWikitext,
                    summary: 'Updated link to [[' + newTarget + ']]'
                }).then(function (response) {
                    console.log('API response from updating link: ', response);
                    if (response.edit && response.edit.result === 'Success' && !response.edit.nochange) {
                        logDetail('Successfully updated link in ' + linkedPageTitle);
                    } else {
                        logDetail('No changes made to link in ' + linkedPageTitle);
                    }
                    resolve();
                }).fail(function (error) {
                    logDetail('Error updating link in ' + linkedPageTitle + ': ' + error);
                    resolve();
                });
            }).fail(function (error) {
                logDetail('Error fetching page content for ' + linkedPageTitle + ': ' + error);
                resolve();
            });
        }

        function updateRedirectTarget(redirectPageTitle, newTarget, api, resolve, logDetail) {
            logDetail('Updating redirect target in ' + redirectPageTitle);
            return api.postWithToken('csrf', {
                action: 'edit',
                title: redirectPageTitle,
                text: '#REDIRECT [[' + newTarget + ']]',
                summary: 'Updated redirect to [[' + newTarget + ']]'
            }).then(function (response) {
                console.log('API response from updating redirect: ', response);
                if (response.edit && response.edit.result === 'Success' && !response.edit.nochange) {
                    logDetail('Successfully updated redirect in ' + redirectPageTitle);
                } else {
                    logDetail('No changes made to redirect in ' + redirectPageTitle);
                }
                resolve();
            }).fail(function (error) {
                logDetail('Error updating redirect in ' + redirectPageTitle + ': ' + error);
                resolve();
            });
        }

        function removeLinkFromPage(linkedPageTitle, originalPageTitle, api, resolve, logDetail) {
            api.get({
                action: 'parse',
                page: linkedPageTitle,
                prop: 'wikitext'
            }).then(function (data) {
                var wikitext = data.parse.wikitext['*'];
                var regex = new RegExp('\\[\\[' + originalPageTitle.replace(/[\[\]]/g, '\\$&') + '(\\|[^\\]]+)?\\]\\]', 'g');
                var newWikitext = wikitext.replace(regex, function(match, p1) {
                    return p1 ? p1.substring(1) : originalPageTitle;
                });
                if (wikitext !== newWikitext) {
                    logDetail('Removing link from ' + linkedPageTitle);
                } else {
                    logDetail('No link found in ' + linkedPageTitle);
                }
                return api.postWithToken('csrf', {
                    action: 'edit',
                    title: linkedPageTitle,
                    text: newWikitext,
                    summary: 'Removed link to [[' + originalPageTitle + ']]'
                }).then(function (response) {
                    console.log('API response from removing link: ', response);
                    if (response.edit && response.edit.result === 'Success' && !response.edit.nochange) {
                        logDetail('Successfully removed link from ' + linkedPageTitle);
                    } else {
                        logDetail('No changes made to link in ' + linkedPageTitle);
                    }
                    resolve();
                }).fail(function (error) {
                    logDetail('Error removing link from ' + linkedPageTitle + ': ' + error);
                    resolve();
                });
            }).fail(function (error) {
                logDetail('Error fetching page content for ' + linkedPageTitle + ': ' + error);
                resolve();
            });
        }

        function handleRedirects(next) {
            updateLoadingText('Fetching redirects...');
            api.get({
                action: 'query',
                titles: pageTitle,
                redirects: true
            }).done(function (data) {
                logDetail('Redirects fetched.');
                var redirects = data.query.pages[Object.keys(data.query.pages)[0]].redirects;
                if (redirects) {
                    var promises = $.map(redirects, function (redirect) {
                        return new $.Deferred(function (defer) {
                            logDetail('Found redirect: ' + redirect.title);
                            performDeletion(redirect.title, defer.resolve, logDetail);
                        }).promise();
                    });
                    $.when.apply($, promises).then(function () {
                        next();
                    });
                } else {
                    next();
                }
            }).fail(function (error) {
                updateLoadingText('Error fetching redirects: ' + error);
                next();
            });
        }

        function performDeletion(pageTitle, resolve, logDetail) {
            updateLoadingText('Deleting the page: ' + pageTitle);
            api.postWithToken('csrf', {
                action: 'delete',
                title: pageTitle,
                reason: 'Automated clean delete by admin'
            }).done(function (response) {
                console.log('API response from deleting page: ', response);
                if (response.delete && response.delete.title) {
                    logDetail('Successfully deleted page: ' + response.delete.title);
                } else {
                    logDetail('No deletion performed for ' + pageTitle);
                }
                resolve();
            }).fail(function (error) {
                logDetail('Error during clean deletion of ' + pageTitle + ': ' + error);
                resolve();
            });
        }

        var tasks = [
            function (resolve) {
                if (decisions.links === '') {
                    handleLinksAndRedirects('remove', '', resolve);
                } else {
                    handleLinksAndRedirects('update', decisions.links, resolve);
                }
            },
            function (resolve) {
                if (decisions.deletion) {
                    handleRedirects(resolve);
                } else {
                    resolve();
                }
            },
            function (resolve) {
                if (decisions.deletion) {
                    performDeletion(pageTitle, resolve, logDetail);
                } else {
                    resolve();
                }
            }
        ];

        (function executeTasks(i) {
            if (i < tasks.length) {
                tasks[i](function () {
                    executeTasks(i + 1);
                });
            } else {
                callback();
            }
        })(0);
    }

    mw.hook('wikipage.content').add(addCleanDeleteLink);
});

function isLoggedOut() {
  return mw.config.get('wgUserName') === null;
}

jQuery(document).ready(function ($) {
  if (isLoggedOut()) {
    $('body').append('<div class="darken-overlay"></div>');

    $('img').each(function () {
      var imgSrc = $(this).attr('src');
      
      if (imgSrc !== '/images/MDrivenLogo.png') {
        $(this).addClass('enlargeable');
      }
    });

    $('img.enlargeable').click(function (event) {
      event.preventDefault();
      event.stopPropagation();

      if ($(this).hasClass('enlarged')) {
        $(this).removeClass('enlarged');
        $('.darken-overlay').hide();
      } else {
        $('img.enlargeable').removeClass('enlarged');
        $(this).addClass('enlarged');
        $('.darken-overlay').show();
        
        var fullSizeSrc = $(this).attr('src').replace('/thumb', '').replace(/\/\d+px-.+$/, '');
        $(this).attr('src', fullSizeSrc);
      }
    });

    $('.darken-overlay').click(function () {
      $('img.enlargeable').removeClass('enlarged');
      $(this).hide();
    });
  }
});




/**
 * Fixed LeftMenu Editor with Tags Feature - ES5 Compatible
 * Top collapsible design, clean colors, working structure display
 */
(function (mw, $) {
    'use strict';

    // Abort for anonymous visitors
    if (!mw.config.get('wgUserId')) { return; }

    // Load dependencies
    mw.loader.using(['mediawiki.api', 'jquery.ui']).done(function () {

        var LeftMenuEditor = {
            api: new mw.Api(),
            menuData: null, // Start as null to detect if loaded
            namespace: (mw.config.get('wgCanonicalNamespace') || 'Main').replace(/ /g, '_'), // Replace spaces with underscores
            currentPage: mw.config.get('wgPageName'),
            pageName: mw.config.get('wgTitle'),
            isEditMode: false,
            isCollapsed: true,
            $menu: null,
            $editorBox: null,
            $preview: null,
            selectedItem: null,
            suggestedTags: [], // Store suggested tags
            selectedTags: [] // Store selected tags
        };

        // Clean, professional CSS without gradients
        function addStyles() {
            var css = [
                // Main container at top of content
                '.leftmenu-editor-container{position:relative;background:#ffffff;border:1px solid #ddd;margin:0 0 20px 0;box-shadow:0 2px 4px rgba(0,0,0,0.08);overflow:hidden;transition:all 0.3s ease}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-body{max-height:0;padding:0 20px}',
                
                // Header - clean design
                '.leftmenu-editor-header{background:#f8f9fa;border-bottom:1px solid #ddd;padding:15px 20px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;user-select:none}',
                '.leftmenu-editor-header:hover{background:#f0f1f3}',
                '.leftmenu-editor-header h3{margin:0;font-size:16px;font-weight:600;color:#333}',
                '.leftmenu-editor-toggle{font-size:12px;color:#666;transition:transform 0.3s}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-toggle{transform:rotate(-90deg)}',
                
                // Body layout
                '.leftmenu-editor-body{display:grid;grid-template-columns:1fr 380px;gap:20px;padding:20px;max-height:600px;overflow-y:scroll;transition:all 0.3s ease}',
                
                // Menu preview panel
                '.leftmenu-preview-panel{background:#fafafa;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;max-height:560px}',
                '.leftmenu-preview-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}',
                '.leftmenu-preview-header h4{margin:0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
                '.leftmenu-search{padding:6px 12px;border:1px solid #ddd;border-radius:4px;width:200px;font-size:13px}',
                '.leftmenu-search:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
                
                // Menu tree structure
                '.leftmenu-preview-tree{font-size:14px}',
                
                // Menu items - clean cards
                '.leftmenu-visual-item{background:#fff;border:1px solid #e0e0e0;padding:10px 14px;margin:4px 0;cursor:move;transition:all 0.2s;display:flex;justify-content:space-between;align-items:center;color:#333;position:relative}',
                '.leftmenu-visual-item:hover{background:#f8f9fa;border-color:#4a90e2;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-visual-item.is-current-page{background:#e8f4fd;border-color:#4a90e2;font-weight:600}',
                '.leftmenu-visual-item.selected{background:#4a90e2;color:#fff;border-color:#3a7bc8}',
                
                // Sections - hierarchical design
                '.leftmenu-visual-section{background:#fff;border:1px solid #ddd;margin:8px 0;overflow:visible}',
                '.leftmenu-visual-section-header{background:#f0f0f0;padding:10px 14px;cursor:pointer;display:flex;align-items:center;font-weight:600;color:#333;font-size:14px;border-bottom:1px solid #ddd;user-select:none}',
                '.leftmenu-visual-section-header:hover{background:#e8e8e8}',
                '.leftmenu-section-toggle{font-size:10px;color:#666;margin-right:8px;transition:transform 0.2s}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-toggle{transform:rotate(-90deg)}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-items{display:none}',
                '.leftmenu-section-items{padding:8px;background:#fafafa;min-height:20px}',
                
                // Nested sections - clear hierarchy
                '.leftmenu-section-items .leftmenu-visual-section{margin:4px 0;border-color:#e0e0e0}',
                '.leftmenu-section-items .leftmenu-visual-section-header{background:#f8f8f8;font-size:13px;padding:8px 12px}',
                '.leftmenu-section-items .leftmenu-visual-item{font-size:13px}',
                
                // Drag placeholder at correct level
                '.ui-sortable-helper{opacity:0.8 !important}',
                '.leftmenu-section-items .leftmenu-drag-placeholder{margin-left:0 !important}',
                
                // Direct links - distinct style
                '.leftmenu-visual-item.direct-link{background:#fffbf0;border-color:#f0ad4e}',
                '.leftmenu-visual-item.direct-link:hover{background:#fff8e1;border-color:#ec971f}',
                
                // Item count badge
                '.leftmenu-item-count{background:#4a90e2;color:#fff;padding:2px 6px;border-radius:10px;font-size:11px;margin-left:auto;margin-right:10px}',
                
                // Icons
                '.leftmenu-icon{display:inline-block;width:16px;text-align:center;margin-right:6px;opacity:0.6}',
                
                // Drag and drop
                '.leftmenu-dragging{opacity:0.4}',
                '.leftmenu-drag-placeholder{background:#4a90e2;opacity:0.2;height:36px;margin:4px 0;border:2px dashed #4a90e2}',
                
                // Action buttons
                '.leftmenu-item-actions{opacity:0;transition:opacity 0.2s;display:flex;gap:4px}',
                '.leftmenu-visual-item:hover .leftmenu-item-actions,.leftmenu-visual-section-header:hover .leftmenu-item-actions{opacity:1}',
                '.leftmenu-visual-item.selected .leftmenu-item-actions{opacity:1}',
                '.leftmenu-item-actions button{background:#fff;border:1px solid #ddd;width:28px;height:28px;border-radius:4px;cursor:pointer;font-size:12px;transition:all 0.15s;padding:0;display:flex;align-items:center;justify-content:center}',
                '.leftmenu-item-actions button:hover{background:#f8f9fa;border-color:#999}',
                '.leftmenu-item-edit{color:#4a90e2}',
                '.leftmenu-item-delete{color:#d9534f}',
                '.leftmenu-item-duplicate{color:#5cb85c}',
                
                // Control panel
                '.leftmenu-controls{background:#fff;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;display:flex;flex-direction:column}',
                '.leftmenu-controls h4{margin:0 0 16px 0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
                
                // Quick actions
                '.leftmenu-quick-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px}',
                '.leftmenu-quick-action{background:#f8f9fa;border:1px solid #ddd;padding:12px;text-align:center;cursor:pointer;transition:all 0.2s;border-radius:4px}',
                '.leftmenu-quick-action:hover{border-color:#4a90e2;background:#fff;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-quick-action-icon{font-size:20px;margin-bottom:4px;display:block}',
                '.leftmenu-quick-action-label{font-size:12px;color:#666}',
                
                // Form inputs
                '.leftmenu-form-group{margin-bottom:16px}',
                '.leftmenu-form-label{display:block;margin-bottom:4px;color:#333;font-size:13px;font-weight:600}',
                '.leftmenu-form-input,.leftmenu-form-select{width:100%;padding:8px 12px;border:1px solid #ddd;border-radius:4px;font-size:13px}',
                '.leftmenu-form-input:focus,.leftmenu-form-select:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
                
                // Buttons
                '.leftmenu-button{padding:8px 16px;border:1px solid #ddd;border-radius:4px;font-size:13px;font-weight:600;cursor:pointer;transition:all 0.2s;background:#fff}',
                '.leftmenu-button:hover{background:#f8f9fa}',
                '.leftmenu-button.primary{background:#4a90e2;color:#fff;border-color:#4a90e2}',
                '.leftmenu-button.primary:hover{background:#3a7bc8;border-color:#3a7bc8}',
                '.leftmenu-button.secondary{background:#f8f9fa;color:#333}',
                '.leftmenu-button.danger{background:#d9534f;color:#fff;border-color:#d9534f}',
                '.leftmenu-button.success{background:#5cb85c;color:#fff;border-color:#5cb85c}',
                '.leftmenu-button:disabled{opacity:0.6;cursor:not-allowed}',
                
                // Status messages
                '.leftmenu-status{padding:10px 12px;margin:10px 0;font-size:13px;display:none;border-radius:4px}',
                '.leftmenu-status.success{background:#dff0d8;color:#3c763d;border:1px solid #d6e9c6}',
                '.leftmenu-status.error{background:#f2dede;color:#a94442;border:1px solid #ebccd1}',
                '.leftmenu-status.info{background:#d9edf7;color:#31708f;border:1px solid #bce8f1}',
                
                // JSON view
                '.leftmenu-json-view{background:#f5f5f5;border:1px solid #ddd;padding:12px;font-family:monospace;font-size:12px;line-height:1.4;border-radius:4px;max-height:300px;overflow-y:auto}',
                
                // Loading
                '.leftmenu-loading{text-align:center;padding:40px;color:#999}',
                '.leftmenu-spinner{display:inline-block;width:20px;height:20px;border:2px solid #f3f3f3;border-top:2px solid #4a90e2;border-radius:50%;animation:spin 1s linear infinite}',
                '@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}',
                
                // Empty state
                '.leftmenu-empty-state{text-align:center;padding:40px;color:#999}',
                '.leftmenu-empty-state button{margin-top:10px}',
                
                // Responsive
                '@media (max-width: 900px){.leftmenu-editor-body{grid-template-columns:1fr;height:auto}.leftmenu-controls{border-top:1px solid #e0e0e0;margin-top:20px}}'
            ].join('');
            $('<style>').text(css).appendTo('head');
        }

        // Create the interface
        function createInterface() {
            var $container = $('<div>', { 'class': 'leftmenu-editor-container collapsed' });
            
            var $header = $('<div>', { 'class': 'leftmenu-editor-header' }).html(
                '<h3>🛠️ Wiki Tools - Menu Editor, AI Assistant & Page Management</h3>' +
                '<span class="leftmenu-editor-toggle">▼</span>'
            );
            
            var $body = $('<div>', { 'class': 'leftmenu-editor-body' });
            
            // Create tabbed interface
            var $tabs = $('<div>', { 'class': 'wiki-tools-tabs' }).html(
                '<div class="tab-buttons">' +
                    '<button class="tab-button active" data-tab="menu-editor">📋 Menu Editor</button>' +
                    '<button class="tab-button" data-tab="ai-tools">🤖 AI Tools</button>' +
                    '<button class="tab-button" data-tab="page-tools">📄 Page Tools</button>' +
                '</div>'
            );
            
            // Menu Editor Tab
            var $menuTab = $('<div>', { 'class': 'tab-content active', 'id': 'menu-editor-tab' }).html(
                '<div class="leftmenu-preview-panel">' +
                    '<div class="leftmenu-preview-header">' +
                        '<h4>Menu Structure - ' + LeftMenuEditor.namespace + '</h4>' +
                        '<input type="text" class="leftmenu-search" placeholder="Search items...">' +
                    '</div>' +
                    '<div class="leftmenu-preview-tree"></div>' +
                    '<div class="leftmenu-empty-state" style="display:none">' +
                        '<p>No menu items yet</p>' +
                        '<button class="leftmenu-button primary leftmenu-empty-add">Add First Item</button>' +
                    '</div>' +
                '</div>' +
                '<div class="leftmenu-controls">' +
                    '<h4>Actions</h4>' +
                    '<div class="leftmenu-quick-actions">' +
                        '<div class="leftmenu-quick-action" data-action="add-section">' +
                            '<span class="leftmenu-quick-action-icon">📁</span>' +
                            '<span class="leftmenu-quick-action-label">Add Section</span>' +
                        '</div>' +
                        '<div class="leftmenu-quick-action" data-action="add-page">' +
                            '<span class="leftmenu-quick-action-icon">📄</span>' +
                            '<span class="leftmenu-quick-action-label">Add Page</span>' +
                        '</div>' +
                        '<div class="leftmenu-quick-action" data-action="add-current">' +
                            '<span class="leftmenu-quick-action-icon">📌</span>' +
                            '<span class="leftmenu-quick-action-label">Current Page</span>' +
                        '</div>' +
                        '<div class="leftmenu-quick-action" data-action="import">' +
                            '<span class="leftmenu-quick-action-icon">📥</span>' +
                            '<span class="leftmenu-quick-action-label">Import</span>' +
                        '</div>' +
                    '</div>' +
                    '<div class="leftmenu-status"></div>' +
                    '<div class="leftmenu-action-panel" style="display:none;margin-bottom:20px">' +
                        '<div class="leftmenu-form"></div>' +
                    '</div>' +
                    '<div style="margin-top:auto">' +
                        '<button class="leftmenu-button primary leftmenu-save" style="width:100%;margin-bottom:10px">Save Changes</button>' +
                        '<div style="display:flex;gap:10px">' +
                            '<button class="leftmenu-button secondary leftmenu-reset" style="flex:1">Reset</button>' +
                            '<button class="leftmenu-button secondary leftmenu-view-json" style="flex:1">View JSON</button>' +
                        '</div>' +
                    '</div>' +
                    '<div class="leftmenu-json-view" style="display:none;margin-top:20px"></div>' +
                '</div>'
            );
            
            // AI Tools Tab
            var $aiTab = $('<div>', { 'class': 'tab-content', 'id': 'ai-tools-tab' }).html(
                '<div class="ai-tools-container">' +
                    '<div class="ai-section">' +
                        '<h4>AI Content Assistant</h4>' +
                        '<div class="ai-actions">' +
                            '<button class="ai-button primary" id="ai-summarize">' +
                                '<span class="button-icon">📝</span> Summarize Page' +
                            '</button>' +
                            '<button class="ai-button primary" id="ai-fix-spelling">' +
                                '<span class="button-icon">✓</span> Fix Spelling' +
                            '</button>' +
                            '<button class="ai-button primary" id="ai-suggest-tags">' +
                                '<span class="button-icon">🏷️</span> Suggest Tags' +
                            '</button>' +
                        '</div>' +
                        '<div class="ai-result" id="ai-result" style="display:none">' +
                            '<div class="ai-result-header">' +
                                '<h5>Result</h5>' +
                                '<button class="ai-button-small" id="ai-copy">📋 Copy</button>' +
                            '</div>' +
                            '<div class="ai-result-content"></div>' +
                            '<div class="ai-result-actions">' +
                                '<button class="ai-button success" id="ai-apply-nutshell" style="display:none">🥜 Add as Nutshell</button>' +
                                '<button class="ai-button success" id="ai-apply-spelling" style="display:none">✅ Apply Corrections</button>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                    
                    '<div class="ai-section" id="tags-section" style="display:none">' +
                        '<h4>Page Tags</h4>' +
                        '<div class="tags-container">' +
                            '<div class="suggested-tags-section">' +
                                '<h5>AI Suggested Tags</h5>' +
                                '<div class="suggested-tags" id="suggested-tags"></div>' +
                            '</div>' +
                            '<div class="custom-tags-section">' +
                                '<h5>Add Custom Tags</h5>' +
                                '<div class="custom-tag-input">' +
                                    '<input type="text" id="custom-tag-input" class="form-input" placeholder="Type a tag and press Enter">' +
                                    '<button class="ai-button-small primary" id="add-custom-tag">+ Add</button>' +
                                '</div>' +
                            '</div>' +
                            '<div class="selected-tags-section">' +
                                '<h5>Selected Tags</h5>' +
                                '<div class="selected-tags" id="selected-tags"></div>' +
                            '</div>' +
                            '<div class="tags-actions">' +
                                '<button class="ai-button success" id="apply-tags">Apply Tags to Page</button>' +
                                '<button class="ai-button secondary" id="clear-tags">Clear All</button>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                    
                    '<div class="ai-status" style="display:none"></div>' +
                '</div>'
            );
            
            // Page Tools Tab
            var $pageTab = $('<div>', { 'class': 'tab-content', 'id': 'page-tools-tab' }).html(
                '<div class="page-tools-container">' +
                    '<div class="page-section">' +
                        '<h4>Rename Page</h4>' +
                        '<div class="form-group-inline">' +
                            '<input type="text" id="new-page-name" class="form-input" placeholder="Enter new page name">' +
                            '<button class="ai-button primary" id="rename-page">Rename</button>' +
                        '</div>' +
                    '</div>' +
                    '<div class="page-section">' +
                        '<h4>Move to Namespace</h4>' +
                        '<div class="form-group-inline">' +
                            '<select id="target-namespace" class="form-select">' +
                                '<option value="">Loading namespaces...</option>' +
                            '</select>' +
                            '<button class="ai-button primary" id="move-namespace">Move Page</button>' +
                        '</div>' +
                    '</div>' +
                    '<div class="page-info">' +
                        '<h4>Current Page Info</h4>' +
                        '<div class="info-item"><strong>Page:</strong> <span id="current-page-name">' + mw.config.get('wgPageName') + '</span></div>' +
                        '<div class="info-item"><strong>Namespace:</strong> <span id="current-namespace">' + (mw.config.get('wgCanonicalNamespace') || 'Main') + '</span></div>' +
                    '</div>' +
                    '<div class="page-status" style="display:none"></div>' +
                '</div>'
            );
            
            $body.append($tabs);
            $body.append($('<div class="tab-contents">').append($menuTab, $aiTab, $pageTab));
            
            $container.append($header, $body);
            
            // Insert at top of content
            var $content = $('#content, #mw-content-text, .mw-body-content').first();
            $content.prepend($container);
            
            LeftMenuEditor.$editorBox = $container;
            LeftMenuEditor.$preview = $container.find('.leftmenu-preview-tree');
            
            // Add unified styles
            addUnifiedStyles();
            
            // Bind tab events
            bindTabEvents();
            
            // Bind all events
            bindAIEvents();
            bindPageToolsEvents();
            bindTagsEvents();
            
            // Load namespaces
            loadNamespaces();
        }
        
        // Add unified styles
        function addUnifiedStyles() {
            var existingStyles = $('style').filter(function() {
                return $(this).text().indexOf('.leftmenu-editor-container') > -1;
            });
            existingStyles.remove();
            
            var css = [
                // Keep all existing menu editor styles...
                '.leftmenu-editor-container{position:relative;background:#ffffff;border:1px solid #ddd;margin:0 0 20px 0;box-shadow:0 2px 4px rgba(0,0,0,0.08);overflow:hidden;transition:all 0.3s ease}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-body{max-height:0;padding:0 20px}',
                '.leftmenu-editor-header{background:#f8f9fa;border-bottom:1px solid #ddd;padding:15px 20px;cursor:pointer;display:flex;justify-content:space-between;align-items:center;user-select:none}',
                '.leftmenu-editor-header:hover{background:#f0f1f3}',
                '.leftmenu-editor-header h3{margin:0;font-size:16px;font-weight:600;color:#333}',
                '.leftmenu-editor-toggle{font-size:12px;color:#666;transition:transform 0.3s}',
                '.leftmenu-editor-container.collapsed .leftmenu-editor-toggle{transform:rotate(-90deg)}',
                '.leftmenu-editor-body{padding:0;max-height:700px;overflow-y:scroll;transition:all 0.3s ease}',
                
                // Tab styles
                '.wiki-tools-tabs{background:#f0f0f0;border-bottom:1px solid #ddd}',
                '.tab-buttons{display:flex;padding:0}',
                '.tab-button{flex:1;padding:12px 20px;border:none;background:transparent;cursor:pointer;font-size:14px;font-weight:500;color:#666;transition:all 0.2s;border-bottom:3px solid transparent}',
                '.tab-button:hover{background:#e8e8e8}',
                '.tab-button.active{color:#4a90e2;border-bottom-color:#4a90e2;background:#fff}',
                '.tab-contents{background:#fff}',
                '.tab-content{display:none;animation:fadeIn 0.3s}',
                '.tab-content.active{display:grid;grid-template-columns:1fr 380px;gap:20px;padding:20px}',
                '#ai-tools-tab.active, #page-tools-tab.active{display:block;padding:20px}',
                '@keyframes fadeIn{from{opacity:0}to{opacity:1}}',
                
                // Menu editor styles (keep existing)
                '.leftmenu-preview-panel{background:#fafafa;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;max-height:560px}',
                '.leftmenu-preview-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}',
                '.leftmenu-preview-header h4{margin:0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
                '.leftmenu-search{padding:6px 12px;border:1px solid #ddd;border-radius:4px;width:200px;font-size:13px}',
                '.leftmenu-search:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
                '.leftmenu-preview-tree{font-size:14px}',
                '.leftmenu-visual-item{background:#fff;border:1px solid #e0e0e0;padding:10px 14px;margin:4px 0;cursor:move;transition:all 0.2s;display:flex;justify-content:space-between;align-items:center;color:#333;position:relative}',
                '.leftmenu-visual-item:hover{background:#f8f9fa;border-color:#4a90e2;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-visual-item.is-current-page{background:#e8f4fd;border-color:#4a90e2;font-weight:600}',
                '.leftmenu-visual-item.selected{background:#4a90e2;color:#fff;border-color:#3a7bc8}',
                '.leftmenu-visual-section{background:#fff;border:1px solid #ddd;margin:8px 0;overflow:visible}',
                '.leftmenu-visual-section-header{background:#f0f0f0;padding:10px 14px;cursor:pointer;display:flex;align-items:center;font-weight:600;color:#333;font-size:14px;border-bottom:1px solid #ddd;user-select:none}',
                '.leftmenu-visual-section-header:hover{background:#e8e8e8}',
                '.leftmenu-section-toggle{font-size:10px;color:#666;margin-right:8px;transition:transform 0.2s}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-toggle{transform:rotate(-90deg)}',
                '.leftmenu-visual-section.collapsed .leftmenu-section-items{display:none}',
                '.leftmenu-section-items{padding:8px;background:#fafafa;min-height:20px}',
                '.leftmenu-section-items .leftmenu-visual-section{margin:4px 0;border-color:#e0e0e0}',
                '.leftmenu-section-items .leftmenu-visual-section-header{background:#f8f8f8;font-size:13px;padding:8px 12px}',
                '.leftmenu-section-items .leftmenu-visual-item{font-size:13px}',
                '.ui-sortable-helper{opacity:0.8 !important}',
                '.leftmenu-section-items .leftmenu-drag-placeholder{margin-left:0 !important}',
                '.leftmenu-visual-item.direct-link{background:#fffbf0;border-color:#f0ad4e}',
                '.leftmenu-visual-item.direct-link:hover{background:#fff8e1;border-color:#ec971f}',
                '.leftmenu-item-count{background:#4a90e2;color:#fff;padding:2px 6px;border-radius:10px;font-size:11px;margin-left:auto;margin-right:10px}',
                '.leftmenu-icon{display:inline-block;width:16px;text-align:center;margin-right:6px;opacity:0.6}',
                '.leftmenu-dragging{opacity:0.4}',
                '.leftmenu-drag-placeholder{background:#4a90e2;opacity:0.2;height:36px;margin:4px 0;border:2px dashed #4a90e2}',
                '.leftmenu-item-actions{opacity:0;transition:opacity 0.2s;display:flex;gap:4px}',
                '.leftmenu-visual-item:hover .leftmenu-item-actions,.leftmenu-visual-section-header:hover .leftmenu-item-actions{opacity:1}',
                '.leftmenu-visual-item.selected .leftmenu-item-actions{opacity:1}',
                '.leftmenu-item-actions button{background:#fff;border:1px solid #ddd;width:28px;height:28px;border-radius:4px;cursor:pointer;font-size:12px;transition:all 0.15s;padding:0;display:flex;align-items:center;justify-content:center}',
                '.leftmenu-item-actions button:hover{background:#f8f9fa;border-color:#999}',
                '.leftmenu-item-edit{color:#4a90e2}',
                '.leftmenu-item-delete{color:#d9534f}',
                '.leftmenu-item-duplicate{color:#5cb85c}',
                '.leftmenu-controls{background:#fff;border:1px solid #e0e0e0;padding:20px;overflow-y:auto;display:flex;flex-direction:column}',
                '.leftmenu-controls h4{margin:0 0 16px 0;color:#333;font-size:14px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px}',
                '.leftmenu-quick-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px}',
                '.leftmenu-quick-action{background:#f8f9fa;border:1px solid #ddd;padding:12px;text-align:center;cursor:pointer;transition:all 0.2s;border-radius:4px}',
                '.leftmenu-quick-action:hover{border-color:#4a90e2;background:#fff;box-shadow:0 2px 4px rgba(0,0,0,0.08)}',
                '.leftmenu-quick-action-icon{font-size:20px;margin-bottom:4px;display:block}',
                '.leftmenu-quick-action-label{font-size:12px;color:#666}',
                '.leftmenu-form-group{margin-bottom:16px}',
                '.leftmenu-form-label{display:block;margin-bottom:4px;color:#333;font-size:13px;font-weight:600}',
                '.leftmenu-form-input,.leftmenu-form-select{width:100%;padding:8px 12px;border:1px solid #ddd;border-radius:4px;font-size:13px}',
                '.leftmenu-form-input:focus,.leftmenu-form-select:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 2px rgba(74,144,226,0.2)}',
                '.leftmenu-button{padding:8px 16px;border:1px solid #ddd;border-radius:4px;font-size:13px;font-weight:600;cursor:pointer;transition:all 0.2s;background:#fff}',
                '.leftmenu-button:hover{background:#f8f9fa}',
                '.leftmenu-button.primary{background:#4a90e2;color:#fff;border-color:#4a90e2}',
                '.leftmenu-button.primary:hover{background:#3a7bc8;border-color:#3a7bc8}',
                '.leftmenu-button.secondary{background:#f8f9fa;color:#333}',
                '.leftmenu-button.danger{background:#d9534f;color:#fff;border-color:#d9534f}',
                '.leftmenu-button.success{background:#5cb85c;color:#fff;border-color:#5cb85c}',
                '.leftmenu-button:disabled{opacity:0.6;cursor:not-allowed}',
                '.leftmenu-status{padding:10px 12px;margin:10px 0;font-size:13px;display:none;border-radius:4px}',
                '.leftmenu-status.success{background:#dff0d8;color:#3c763d;border:1px solid #d6e9c6}',
                '.leftmenu-status.error{background:#f2dede;color:#a94442;border:1px solid #ebccd1}',
                '.leftmenu-status.info{background:#d9edf7;color:#31708f;border:1px solid #bce8f1}',
                '.leftmenu-json-view{background:#f5f5f5;border:1px solid #ddd;padding:12px;font-family:monospace;font-size:12px;line-height:1.4;border-radius:4px;max-height:300px;overflow-y:auto}',
                '.leftmenu-loading{text-align:center;padding:40px;color:#999}',
                '.leftmenu-spinner{display:inline-block;width:20px;height:20px;border:2px solid #f3f3f3;border-top:2px solid #4a90e2;border-radius:50%;animation:spin 1s linear infinite}',
                '@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}',
                '.leftmenu-empty-state{text-align:center;padding:40px;color:#999}',
                '.leftmenu-empty-state button{margin-top:10px}',
                
                // AI Tools styles
                '.ai-tools-container{max-width:800px;margin:0 auto}',
                '.ai-section, .page-section{background:#fafafa;border:1px solid #e0e0e0;padding:25px;margin-bottom:20px;border-radius:8px}',
                '.ai-section h4, .page-section h4{margin:0 0 20px 0;color:#333;font-size:16px;font-weight:600}',
                '.ai-section h5{margin:0 0 10px 0;color:#555;font-size:14px;font-weight:600}',
                '.ai-actions{display:flex;gap:15px;flex-wrap:wrap}',
                '.ai-button, .ai-button-small{padding:12px 24px;border:none;border-radius:6px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.2s;display:inline-flex;align-items:center;gap:8px}',
                '.ai-button-small{padding:6px 12px;font-size:12px}',
                '.button-icon{font-size:18px}',
                '.ai-button.primary{background:#4a90e2;color:#fff}',
                '.ai-button.primary:hover{background:#3a7bc8;transform:translateY(-1px);box-shadow:0 4px 12px rgba(74,144,226,0.3)}',
                '.ai-button.success{background:#5cb85c;color:#fff}',
                '.ai-button.success:hover{background:#4cae4c}',
                '.ai-button.secondary{background:#6c757d;color:#fff}',
                '.ai-button.secondary:hover{background:#5a6268}',
                '.ai-button:disabled{opacity:0.6;cursor:not-allowed;transform:none !important}',
                '.ai-result{margin-top:20px;background:#fff;border:1px solid #ddd;border-radius:8px;overflow:hidden}',
                '.ai-result-header{background:#f8f9fa;padding:15px 20px;border-bottom:1px solid #e0e0e0;display:flex;justify-content:space-between;align-items:center}',
                '.ai-result-header h5{margin:0;color:#333;font-size:14px;font-weight:600}',
                '.ai-result-content{padding:20px;font-size:14px;line-height:1.8;color:#333;max-height:300px;overflow-y:auto}',
                '.ai-result-actions{padding:15px 20px;background:#f8f9fa;border-top:1px solid #e0e0e0;display:flex;gap:10px}',
                '.ai-status, .page-status{padding:15px 20px;margin-top:20px;border-radius:8px;font-size:14px;font-weight:500}',
                '.ai-status.success, .page-status.success{background:#d4edda;color:#155724;border:1px solid #c3e6cb}',
                '.ai-status.error, .page-status.error{background:#f8d7da;color:#721c24;border:1px solid #f5c6cb}',
                '.ai-status.info, .page-status.info{background:#d1ecf1;color:#0c5460;border:1px solid #bee5eb}',
                '.ai-loading{display:inline-block;width:16px;height:16px;border:2px solid #f3f3f3;border-top:2px solid #4a90e2;border-radius:50%;animation:spin 1s linear infinite;margin-left:10px}',
                
                // Tags styles
                '.tags-container{display:flex;flex-direction:column;gap:20px}',
                '.suggested-tags-section, .custom-tags-section, .selected-tags-section{background:#fff;padding:15px;border:1px solid #e0e0e0;border-radius:6px}',
                '.suggested-tags, .selected-tags{display:flex;flex-wrap:wrap;gap:8px;min-height:40px;padding:10px;background:#f8f9fa;border:1px solid #e0e0e0;border-radius:4px}',
                '.tag{padding:6px 12px;background:#e0e0e0;border-radius:20px;font-size:13px;cursor:pointer;transition:all 0.2s;display:inline-flex;align-items:center;gap:6px}',
                '.tag:hover{background:#d0d0d0;transform:translateY(-1px)}',
                '.tag.suggested{background:#e3f2fd;color:#1976d2}',
                '.tag.suggested:hover{background:#bbdefb}',
                '.tag.selected{background:#4a90e2;color:#fff}',
                '.tag-remove{font-size:16px;cursor:pointer;margin-left:4px;opacity:0.7}',
                '.tag-remove:hover{opacity:1}',
                '.custom-tag-input{display:flex;gap:10px;align-items:center}',
                '.custom-tag-input input{flex:1}',
                '.tags-actions{display:flex;gap:10px;margin-top:15px}',
                
                // Page Tools styles
                '.page-tools-container{max-width:800px;margin:0 auto}',
                '.form-group-inline{display:flex;gap:15px;align-items:center}',
                '.form-group-inline .form-input, .form-group-inline .form-select{flex:1}',
                '.form-input, .form-select{padding:10px 15px;border:1px solid #ddd;border-radius:6px;font-size:14px}',
                '.form-input:focus, .form-select:focus{outline:none;border-color:#4a90e2;box-shadow:0 0 0 3px rgba(74,144,226,0.1)}',
                '.page-info{background:#e8f4fd;border:1px solid #bee5eb;padding:20px;border-radius:8px;margin-top:20px}',
                '.page-info h4{margin:0 0 15px 0;color:#0c5460}',
                '.info-item{font-size:14px;margin-bottom:8px}',
                '.info-item strong{color:#333}',
                
                // Responsive
                '@media (max-width: 900px){',
                '.tab-content.active{grid-template-columns:1fr}',
                '.leftmenu-controls{border-top:1px solid #e0e0e0;margin-top:20px}',
                '.tab-button{font-size:12px;padding:10px}',
                '.button-icon{font-size:16px}',
                '}'
            ].join('');
            
            $('<style>').text(css).appendTo('head');
        }
        
        // Bind tab events
        function bindTabEvents() {
            $('.tab-button').on('click', function() {
                var $btn = $(this);
                var targetTab = $btn.data('tab');
                
                // Update buttons
                $('.tab-button').removeClass('active');
                $btn.addClass('active');
                
                // Update content
                $('.tab-content').removeClass('active');
                $('#' + targetTab + '-tab').addClass('active');
                
                // Load menu data when switching to menu editor
                if (targetTab === 'menu-editor' && !LeftMenuEditor.menuData) {
                    loadMenuData();
                }
            });
        }
        
        // Bind AI events
        function bindAIEvents() {
            // Summarize
            $('#ai-summarize').on('click', function() {
                var $btn = $(this);
                $btn.prop('disabled', true).html('<span class="button-icon">⏳</span> Summarizing...');
                
                getPageContent(function(content) {
                    $.ajax({
                        url: 'https://chat.mdriven.net/data/summarize',
                        method: 'POST',
                        contentType: 'application/json',
                        data: JSON.stringify({ content: content }),
                        success: function(response) {
                            var summary = response.summary || response.result || response;
                            displayAIResult(summary, 'summary');
                            $btn.prop('disabled', false).html('<span class="button-icon">📝</span> Summarize Page');
                        },
                        error: function(xhr) {
                            showAIStatus('Error: ' + (xhr.responseText || 'Failed to summarize'), 'error');
                            $btn.prop('disabled', false).html('<span class="button-icon">📝</span> Summarize Page');
                        }
                    });
                });
            });
            
            // Fix spelling
            $('#ai-fix-spelling').on('click', function() {
                var $btn = $(this);
                $btn.prop('disabled', true).html('<span class="button-icon">⏳</span> Checking...');
                
                getPageContent(function(content) {
                    $.ajax({
                        url: 'https://chat.mdriven.net/data/fix-spelling',
                        method: 'POST',
                        contentType: 'application/json',
                        data: JSON.stringify({ content: content }),
                        success: function(response) {
                            var fixed = response.fixed_content || response.result || response;
                            displayAIResult(fixed, 'spelling');
                            $btn.prop('disabled', false).html('<span class="button-icon">✓</span> Fix Spelling');
                        },
                        error: function(xhr) {
                            showAIStatus('Error: ' + (xhr.responseText || 'Failed to fix spelling'), 'error');
                            $btn.prop('disabled', false).html('<span class="button-icon">✓</span> Fix Spelling');
                        }
                    });
                });
            });
            
            // Suggest tags
            $('#ai-suggest-tags').on('click', function() {
                var $btn = $(this);
                $btn.prop('disabled', true).html('<span class="button-icon">⏳</span> Analyzing...');
                
                getPageContent(function(content) {
                    $.ajax({
                        url: 'https://chat.mdriven.net/data/suggest-tags',
                        method: 'POST',
                        contentType: 'application/json',
                        data: JSON.stringify({ content: content }),
                        success: function(response) {
                            var tags = response.tags || [];
                            if (typeof tags === 'string') {
                                try {
                                    tags = JSON.parse(tags);
                                } catch(e) {
                                    tags = [];
                                }
                            }
                            
                            LeftMenuEditor.suggestedTags = tags;
                            displayTagsSuggestions(tags);
                            $('#tags-section').slideDown();
                            $btn.prop('disabled', false).html('<span class="button-icon">🏷️</span> Suggest Tags');
                        },
                        error: function(xhr) {
                            showAIStatus('Error: ' + (xhr.responseText || 'Failed to suggest tags'), 'error');
                            $btn.prop('disabled', false).html('<span class="button-icon">🏷️</span> Suggest Tags');
                        }
                    });
                });
            });
            
            // Copy result
            $('#ai-copy').on('click', function() {
                var text = $('.ai-result-content').text();
                copyToClipboard(text);
                $(this).text('✓ Copied!');
                setTimeout(function() {
                    $('#ai-copy').html('📋 Copy');
                }, 2000);
            });
            
            // Apply nutshell
            $('#ai-apply-nutshell').on('click', function() {
                var summary = $('.ai-result-content').text();
                addNutshellToPage(summary);
            });
            
            // Apply spelling corrections
            $('#ai-apply-spelling').on('click', function() {
                var correctedContent = $('.ai-result-content').text();
                
                LeftMenuEditor.api.postWithToken('csrf', {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    text: correctedContent,
                    summary: 'Applied spelling corrections',
                    contentformat: 'text/x-wiki',
                    contentmodel: 'wikitext'
                }).done(function() {
                    showAIStatus('Spelling corrections applied! Reloading...', 'success');
                    setTimeout(function() {
                        window.location.reload();
                    }, 1500);
                }).fail(function(err) {
                    showAIStatus('Failed to apply corrections: ' + (err.error ? err.error.info : err), 'error');
                });
            });
        }
        
        // Bind tags events
        function bindTagsEvents() {
            // Add custom tag on Enter
            $('#custom-tag-input').on('keypress', function(e) {
                if (e.which === 13) {
                    e.preventDefault();
                    $('#add-custom-tag').click();
                }
            });
            
            // Add custom tag button
            $('#add-custom-tag').on('click', function() {
                var tagText = $('#custom-tag-input').val().trim();
                if (tagText && !isTagSelected(tagText)) {
                    addTagToSelected(tagText, false);
                    $('#custom-tag-input').val('');
                }
            });
            
            // Apply tags to page
            $('#apply-tags').on('click', function() {
                if (LeftMenuEditor.selectedTags.length === 0) {
                    showAIStatus('Please select at least one tag', 'error');
                    return;
                }
                
                var $btn = $(this);
                $btn.prop('disabled', true).text('Applying tags...');
                
                addTagsToPage(LeftMenuEditor.selectedTags);
            });
            
            // Clear all tags
            $('#clear-tags').on('click', function() {
                LeftMenuEditor.selectedTags = [];
                updateSelectedTagsDisplay();
                $('.tag.suggested').removeClass('selected');
            });
        }
        
        // Display tags suggestions
        function displayTagsSuggestions(tags) {
            var $container = $('#suggested-tags');
            $container.empty();
            
            if (tags.length === 0) {
                $container.html('<span style="color:#999">No tags suggested</span>');
                return;
            }
            
            for (var i = 0; i < tags.length; i++) {
                var tag = tags[i];
                var $tag = $('<span>', {
                    'class': 'tag suggested',
                    'data-tag': tag,
                    'text': tag
                });
                
                $tag.on('click', function() {
                    toggleSuggestedTag($(this));
                });
                
                $container.append($tag);
            }
        }
        
        // Toggle suggested tag
        function toggleSuggestedTag($tag) {
            var tagText = $tag.data('tag');
            
            if ($tag.hasClass('selected')) {
                $tag.removeClass('selected');
                removeTagFromSelected(tagText);
            } else {
                $tag.addClass('selected');
                addTagToSelected(tagText, true);
            }
        }
        
        // Add tag to selected
        function addTagToSelected(tagText, isSuggested) {
            if (!isTagSelected(tagText)) {
                LeftMenuEditor.selectedTags.push(tagText);
                updateSelectedTagsDisplay();
            }
        }
        
        // Remove tag from selected
        function removeTagFromSelected(tagText) {
            var newTags = [];
            for (var i = 0; i < LeftMenuEditor.selectedTags.length; i++) {
                if (LeftMenuEditor.selectedTags[i] !== tagText) {
                    newTags.push(LeftMenuEditor.selectedTags[i]);
                }
            }
            LeftMenuEditor.selectedTags = newTags;
            updateSelectedTagsDisplay();
        }
        
        // Check if tag is selected
        function isTagSelected(tagText) {
            return LeftMenuEditor.selectedTags.indexOf(tagText) !== -1;
        }
        
        // Update selected tags display
        function updateSelectedTagsDisplay() {
            var $container = $('#selected-tags');
            $container.empty();
            
            if (LeftMenuEditor.selectedTags.length === 0) {
                $container.html('<span style="color:#999">No tags selected</span>');
                return;
            }
            
            for (var i = 0; i < LeftMenuEditor.selectedTags.length; i++) {
                var tag = LeftMenuEditor.selectedTags[i];
                var $tag = $('<span>', {
                    'class': 'tag selected',
                    'html': tag + '<span class="tag-remove">×</span>'
                });
                
                (function(tagText) {
                    $tag.find('.tag-remove').on('click', function(e) {
                        e.stopPropagation();
                        removeTagFromSelected(tagText);
                        // Also unselect from suggested tags
                        $('.tag.suggested[data-tag="' + tagText + '"]').removeClass('selected');
                    });
                })(tag);
                
                $container.append($tag);
            }
        }
        
        // Add tags to page
        function addTagsToPage(tags) {
            var tagsMarkup = '<tags> ' + tags.join(', ') + ' </tags>\n\n';
            
            getPageContent(function(content) {
                // Check if tags already exist
                var tagsRegex = /<tags>[\s\S]*?<\/tags>/;
                var newContent;
                
                if (tagsRegex.test(content)) {
                    // Replace existing tags
                    newContent = content.replace(tagsRegex, tagsMarkup.trim());
                } else {
                    // Add tags after nutshell if exists, otherwise at the beginning
                    var nutshellRegex = /<nutshell>[\s\S]*?<\/nutshell>/;
                    if (nutshellRegex.test(content)) {
                        newContent = content.replace(nutshellRegex, function(match) {
                            return match + '\n\n' + tagsMarkup.trim();
                        });
                    } else {
                        newContent = tagsMarkup + content;
                    }
                }
                
                LeftMenuEditor.api.postWithToken('csrf', {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    text: newContent,
                    summary: 'Updated page tags',
                    contentformat: 'text/x-wiki',
                    contentmodel: 'wikitext'
                }).done(function() {
                    showAIStatus('Tags applied successfully! Reloading...', 'success');
                    setTimeout(function() {
                        window.location.reload();
                    }, 1500);
                }).fail(function(err) {
                    showAIStatus('Failed to apply tags: ' + (err.error ? err.error.info : err), 'error');
                    $('#apply-tags').prop('disabled', false).text('Apply Tags to Page');
                });
            });
        }
        
        // Bind page tools events
        function bindPageToolsEvents() {
            // Rename page
            $('#rename-page').on('click', function() {
                var newName = $('#new-page-name').val().trim();
                if (!newName) {
                    showPageStatus('Please enter a new page name', 'error');
                    return;
                }
                
                var $btn = $(this);
                $btn.prop('disabled', true).text('Renaming...');
                
                renamePage(newName, function(success, error) {
                    if (success) {
                        showPageStatus('Page renamed successfully! Redirecting...', 'success');
                        setTimeout(function() {
                            window.location.href = mw.util.getUrl(newName);
                        }, 1500);
                    } else {
                        showPageStatus('Error: ' + error, 'error');
                        $btn.prop('disabled', false).text('Rename');
                    }
                });
            });
            
            // Move namespace
            $('#move-namespace').on('click', function() {
                var targetNs = $('#target-namespace').val();
                if (!targetNs && targetNs !== '0') {
                    showPageStatus('Please select a namespace', 'error');
                    return;
                }
                
                var $btn = $(this);
                $btn.prop('disabled', true).text('Moving...');
                
                moveToNamespace(targetNs, function(success, error) {
                    if (success) {
                        showPageStatus('Page moved successfully! Redirecting...', 'success');
                        setTimeout(function() {
                            window.location.reload();
                        }, 1500);
                    } else {
                        showPageStatus('Error: ' + error, 'error');
                        $btn.prop('disabled', false).text('Move Page');
                    }
                });
            });
        }
        
        // Helper functions
        function copyToClipboard(text) {
            var $temp = $('<textarea>');
            $('body').append($temp);
            $temp.val(text).select();
            document.execCommand('copy');
            $temp.remove();
        }
        
        function getPageContent(callback) {
            LeftMenuEditor.api.get({
                action: 'query',
                prop: 'revisions',
                titles: mw.config.get('wgPageName'),
                rvprop: 'content',
                rvslots: 'main',
                formatversion: 2
            }).done(function(data) {
                var content = '';
                if (data.query && data.query.pages && data.query.pages[0]) {
                    var page = data.query.pages[0];
                    if (page.revisions && page.revisions[0]) {
                        content = page.revisions[0].slots.main.content || '';
                    }
                }
                callback(content);
            }).fail(function() {
                showAIStatus('Failed to get page content', 'error');
                callback('');
            });
        }
        
        function displayAIResult(content, type) {
            $('.ai-result-content').text(content);
            $('#ai-result').slideDown();
            
            // Show appropriate action button
            $('#ai-apply-nutshell').toggle(type === 'summary');
            $('#ai-apply-spelling').toggle(type === 'spelling');
        }
        
        function addNutshellToPage(summary) {
            var nutshell = '<nutshell> ' + summary + ' </nutshell>\n\n';
            
            getPageContent(function(content) {
                var newContent = nutshell + content;
                
                LeftMenuEditor.api.postWithToken('csrf', {
                    action: 'edit',
                    title: mw.config.get('wgPageName'),
                    text: newContent,
                    summary: 'Added AI-generated summary in nutshell',
                    contentformat: 'text/x-wiki',
                    contentmodel: 'wikitext'
                }).done(function() {
                    showAIStatus('Nutshell added successfully! Reloading...', 'success');
                    setTimeout(function() {
                        window.location.reload();
                    }, 1500);
                }).fail(function(err) {
                    showAIStatus('Failed to add nutshell: ' + (err.error ? err.error.info : err), 'error');
                });
            });
        }
        
        function loadNamespaces() {
            LeftMenuEditor.api.get({
                action: 'query',
                meta: 'siteinfo',
                siprop: 'namespaces',
                formatversion: 2
            }).done(function(data) {
                var $select = $('#target-namespace');
                $select.empty();
                
                $select.append('<option value="0">(Main)</option>');
                
                if (data.query && data.query.namespaces) {
                    for (var id in data.query.namespaces) {
                        var ns = data.query.namespaces[id];
                        if (ns.id >= 0 && ns.id !== 0 && ns.canonical !== 'Special' && ns.canonical !== 'Media') {
                            $select.append('<option value="' + ns.id + '">' + (ns.name || ns.canonical) + '</option>');
                        }
                    }
                }
                
                var currentNsId = mw.config.get('wgNamespaceNumber');
                $select.val(currentNsId);
            });
        }
        
        function renamePage(newName, callback) {
            LeftMenuEditor.api.postWithToken('csrf', {
                action: 'move',
                from: mw.config.get('wgPageName'),
                to: newName,
                reason: 'Renamed via Wiki Tools',
                movetalk: true,
                movesubpages: true
            }).done(function() {
                callback(true);
            }).fail(function(err) {
                callback(false, err.error ? err.error.info : 'Unknown error');
            });
        }
        
        function moveToNamespace(targetNsId, callback) {
            var nsInfo = mw.config.get('wgFormattedNamespaces');
            var targetPrefix = '';
            
            if (targetNsId !== '0' && nsInfo && nsInfo[targetNsId]) {
                targetPrefix = nsInfo[targetNsId] + ':';
            }
            
            var currentTitle = mw.config.get('wgTitle');
            var newTitle = targetPrefix + currentTitle;
            
            LeftMenuEditor.api.postWithToken('csrf', {
                action: 'move',
                from: mw.config.get('wgPageName'),
                to: newTitle,
                reason: 'Moved to ' + (targetPrefix || 'Main') + ' namespace via Wiki Tools',
                movetalk: true,
                movesubpages: true
            }).done(function() {
                callback(true);
            }).fail(function(err) {
                callback(false, err.error ? err.error.info : 'Unknown error');
            });
        }
        
        function showAIStatus(msg, type) {
            $('.ai-status')
                .removeClass('success error info')
                .addClass(type)
                .text(msg)
                .slideDown()
                .delay(5000)
                .slideUp();
        }
        
        function showPageStatus(msg, type) {
            $('.page-status')
                .removeClass('success error info')
                .addClass(type)
                .text(msg)
                .slideDown()
                .delay(5000)
                .slideUp();
        }

        // Parse and render menu structure
        function parseMenuItem(key, value, level) {
            level = level || 0;
            
            // Handle different value types
            if (value === null || value === undefined || value === '') {
                // Item with no value
                return createVisualItem(key, '', 'item', level);
            } else if (typeof value === 'string') {
                // String value
                if (key.indexOf('//') === 0) {
                    return createVisualItem(key, value, 'direct', level);
                } else {
                    return createVisualItem(key, value, 'item', level);
                }
            } else if (Array.isArray(value)) {
                // Array handling
                if (value.length === 0) {
                    return createVisualItem(key, '', 'item', level);
                } else if (value.length === 1 && typeof value[0] === 'string') {
                    return createVisualItem(key, value[0], 'item', level);
                } else {
                    // Create section for array with multiple items
                    var $section = createVisualSection(key, level);
                    var $items = $section.find('.leftmenu-section-items');
                    
                    for (var i = 0; i < value.length; i++) {
                        if (typeof value[i] === 'string') {
                            $items.append(createVisualItem(value[i], value[i], 'item', level + 1));
                        } else if (typeof value[i] === 'object') {
                            for (var subKey in value[i]) {
                                if (value[i].hasOwnProperty(subKey)) {
                                    $items.append(parseMenuItem(subKey, value[i][subKey], level + 1));
                                }
                            }
                        }
                    }
                    return $section;
                }
            } else if (typeof value === 'object' && value !== null) {
                // Object - create section
                if (key.indexOf('//') === 0 && Object.keys(value).length === 0) {
                    return createVisualItem(key, '', 'direct', level);
                }
                
                var $section = createVisualSection(key, level);
                var $items = $section.find('.leftmenu-section-items');
                
                // Process nested items
                for (var subKey in value) {
                    if (value.hasOwnProperty(subKey)) {
                        $items.append(parseMenuItem(subKey, value[subKey], level + 1));
                    }
                }
                
                return $section;
            }
            
            // Fallback
            return createVisualItem(key, String(value), 'item', level);
        }

        // Render visual menu
        function renderVisualMenu() {
            var $preview = LeftMenuEditor.$preview;
            var $empty = $('.leftmenu-empty-state');
            
            $preview.empty();
            
            // Check if menuData is null or empty
            if (!LeftMenuEditor.menuData || Object.keys(LeftMenuEditor.menuData).length === 0) {
                $preview.hide();
                $empty.show();
                console.log('Showing empty state - menuData is:', LeftMenuEditor.menuData);
            } else {
                $preview.show();
                $empty.hide();
                console.log('Rendering menu with data:', LeftMenuEditor.menuData);
                
                // Render each top-level item
                for (var key in LeftMenuEditor.menuData) {
                    if (LeftMenuEditor.menuData.hasOwnProperty(key)) {
                        var $element = parseMenuItem(key, LeftMenuEditor.menuData[key], 0);
                        if ($element) {
                            $preview.append($element);
                        }
                    }
                }
                
                makeSortable();
                updateSectionCounts();
            }
        }

        // Create visual item
        function createVisualItem(key, value, type, level) {
            var displayText = key;
            var targetPage = value || key;
            
            // Parse display text
            if (type === 'direct' && key.match(/^\/\/(.+?)\s*\|\s*(.+)$/)) {
                var match = key.match(/^\/\/(.+?)\s*\|\s*(.+)$/);
                displayText = match[2].trim();
                targetPage = match[1].trim();
            } else if (value && typeof value === 'string') {
                if (value.indexOf('|') > -1) {
                    var parts = value.split('|');
                    targetPage = parts[0].trim();
                    displayText = parts[1].trim();
                } else if (value.match(/^\[([^\]]+)\]\s*\|\s*(.+)$/)) {
                    var bracketMatch = value.match(/^\[([^\]]+)\]\s*\|\s*(.+)$/);
                    targetPage = bracketMatch[1];
                    displayText = bracketMatch[2];
                }
            }
            
            var isCurrentPage = (targetPage === LeftMenuEditor.currentPage || 
                               targetPage === LeftMenuEditor.pageName ||
                               key === LeftMenuEditor.currentPage ||
                               key === LeftMenuEditor.pageName);
            
            var icon = type === 'direct' ? '→' : '•';
            
            var $item = $('<div>', {
                'class': 'leftmenu-visual-item' + (type === 'direct' ? ' direct-link' : '') + 
                        (isCurrentPage ? ' is-current-page' : ''),
                'data-key': key,
                'data-value': value || '',
                'data-type': type,
                'data-level': level
            }).css('margin-left', (level * 20) + 'px').html(
                '<span><span class="leftmenu-icon">' + icon + '</span>' + escapeHtml(displayText) + '</span>' +
                '<div class="leftmenu-item-actions">' +
                    '<button class="leftmenu-item-duplicate" title="Duplicate">⊕</button>' +
                    '<button class="leftmenu-item-edit" title="Edit">✎</button>' +
                    '<button class="leftmenu-item-delete" title="Delete">×</button>' +
                '</div>'
            );
            
            // Event handlers
            $item.on('click', function(e) {
                if (!$(e.target).closest('.leftmenu-item-actions').length) {
                    selectItem($item);
                }
            });
            
            $item.find('.leftmenu-item-edit').on('click', function(e) {
                e.stopPropagation();
                editItemInline($item);
            });
            
            $item.find('.leftmenu-item-delete').on('click', function(e) {
                e.stopPropagation();
                deleteItem($item);
            });
            
            $item.find('.leftmenu-item-duplicate').on('click', function(e) {
                e.stopPropagation();
                duplicateItem($item);
            });
            
            return $item;
        }

        // Create visual section
        function createVisualSection(title, level) {
            var $section = $('<div>', {
                'class': 'leftmenu-visual-section',
                'data-section': title,
                'data-level': level
            }).css('margin-left', (level * 20) + 'px').html(
                '<div class="leftmenu-visual-section-header">' +
                    '<span class="leftmenu-section-toggle">▼</span>' +
                    '<span>' + escapeHtml(title) + '</span>' +
                    '<div class="leftmenu-item-actions" style="margin-left:auto">' +
                        '<button class="leftmenu-item-edit" title="Rename">✎</button>' +
                        '<button class="leftmenu-item-delete" title="Delete">×</button>' +
                    '</div>' +
                '</div>' +
                '<div class="leftmenu-section-items"></div>'
            );
            
            $section.find('.leftmenu-visual-section-header').on('click', function(e) {
                if (!$(e.target).closest('.leftmenu-item-actions').length) {
                    $section.toggleClass('collapsed');
                }
            });
            
            $section.find('.leftmenu-item-edit').on('click', function(e) {
                e.stopPropagation();
                editSectionInline($section);
            });
            
            $section.find('.leftmenu-item-delete').on('click', function(e) {
                e.stopPropagation();
                deleteSection($section);
            });
            
            return $section;
        }

        // Update section counts
        function updateSectionCounts() {
            $('.leftmenu-visual-section').each(function() {
                var $section = $(this);
                var count = $section.find('.leftmenu-section-items > *').length;
                var $header = $section.find('.leftmenu-visual-section-header');
                
                $header.find('.leftmenu-item-count').remove();
                if (count > 0) {
                    var $count = $('<span class="leftmenu-item-count">' + count + '</span>');
                    $header.find('.leftmenu-item-actions').before($count);
                }
            });
        }

        // Select item
        function selectItem($item) {
            $('.leftmenu-visual-item, .leftmenu-visual-section').removeClass('selected');
            $item.addClass('selected');
        }

        // Edit item inline
        function editItemInline($item) {
            var $span = $item.find('span').first();
            var currentText = $span.text().replace(/^[•→]\s*/, '');
            
            var $input = $('<input>', {
                'type': 'text',
                'class': 'leftmenu-form-input',
                'value': currentText,
                'style': 'width:calc(100% - 100px);margin:0'
            });
            
            $span.html($input);
            $input.focus().select();
            
            function saveEdit() {
                var newText = $input.val().trim();
                if (newText && newText !== currentText) {
                    updateItemDisplay($item, newText);
                    showStatus('Item updated', 'success');
                } else {
                    $span.html('<span class="leftmenu-icon">' + 
                        ($item.hasClass('direct-link') ? '→' : '•') + 
                        '</span>' + escapeHtml(currentText));
                }
            }
            
            $input.on('blur', saveEdit);
            $input.on('keypress', function(e) {
                if (e.which === 13) {
                    e.preventDefault();
                    saveEdit();
                }
            });
        }

        // Update item display
        function updateItemDisplay($item, newDisplay) {
            var key = $item.data('key');
            var currentValue = $item.data('value') || '';
            var basePage = key;
            
            if (currentValue && currentValue.indexOf('|') > -1) {
                basePage = currentValue.split('|')[0];
            } else if (currentValue.match(/^\[([^\]]+)\]/)) {
                basePage = currentValue.match(/^(\[[^\]]+\])/)[1];
            }
            
            var newValue = basePage + '|' + newDisplay;
            $item.data('value', newValue);
            $item.find('span').first().html(
                '<span class="leftmenu-icon">' + 
                ($item.hasClass('direct-link') ? '→' : '•') + 
                '</span>' + escapeHtml(newDisplay)
            );
            
            updateMenuFromVisual();
        }

        // Delete item
        function deleteItem($item) {
            var name = $item.find('span').first().text().replace(/^[•→]\s*/, '');
            if (confirm('Delete "' + name + '"?')) {
                $item.slideUp(200, function() {
                    $(this).remove();
                    updateMenuFromVisual();
                    updateSectionCounts();
                    showStatus('Item deleted', 'success');
                });
            }
        }

        // Duplicate item
        function duplicateItem($item) {
            var key = $item.data('key');
            var value = $item.data('value');
            var level = $item.data('level') || 0;
            var newKey = key + '_copy';
            var counter = 1;
            
            // Find unique key
            while (isKeyExists(newKey)) {
                counter++;
                newKey = key + '_copy' + counter;
            }
            
            // Clone and insert
            var $clone = $item.clone();
            $clone.data('key', newKey);
            $clone.data('level', level); // Preserve the level
            $clone.css('margin-left', (level * 20) + 'px'); // Apply correct margin
            $clone.insertAfter($item);
            
            // Re-bind events
            bindItemEvents($clone);
            
            // Update and highlight
            updateMenuFromVisual();
            $clone.hide().slideDown(200);
            showStatus('Item duplicated', 'success');
        }

        // Edit section inline
        function editSectionInline($section) {
            var $header = $section.find('.leftmenu-visual-section-header');
            var $span = $header.find('span').eq(1);
            var currentName = $section.data('section');
            
            var $input = $('<input>', {
                'type': 'text',
                'class': 'leftmenu-form-input',
                'value': currentName,
                'style': 'width:200px;margin:0'
            });
            
            $span.html($input);
            $input.focus().select();
            
            function saveEdit() {
                var newName = $input.val().trim();
                if (newName && newName !== currentName) {
                    $section.data('section', newName);
                    $span.text(newName);
                    updateMenuFromVisual();
                    showStatus('Section renamed', 'success');
                } else {
                    $span.text(currentName);
                }
            }
            
            $input.on('blur', saveEdit);
            $input.on('keypress', function(e) {
                if (e.which === 13) {
                    e.preventDefault();
                    saveEdit();
                }
            });
        }

        // Delete section
        function deleteSection($section) {
            var name = $section.data('section');
            var itemCount = $section.find('.leftmenu-section-items > *').length;
            
            var message = 'Delete section "' + name + '"?';
            if (itemCount > 0) {
                message += '\n\nThis will also delete ' + itemCount + ' item' + (itemCount > 1 ? 's' : '') + '.';
            }
            
            if (confirm(message)) {
                $section.slideUp(200, function() {
                    $(this).remove();
                    updateMenuFromVisual();
                    showStatus('Section deleted', 'success');
                });
            }
        }

        // Make sortable
        function makeSortable() {
            $('.leftmenu-preview-tree, .leftmenu-section-items').sortable({
                items: '> .leftmenu-visual-item, > .leftmenu-visual-section',
                connectWith: '.leftmenu-preview-tree, .leftmenu-section-items',
                placeholder: 'leftmenu-drag-placeholder',
                tolerance: 'pointer',
                cursor: 'move',
                start: function(event, ui) {
                    ui.item.addClass('leftmenu-dragging');
                },
                stop: function(event, ui) {
                    ui.item.removeClass('leftmenu-dragging');
                    
                    // Get the new parent container
                    var $newParent = ui.item.parent();
                    var newLevel = 0;
                    
                    // Calculate new level based on parent
                    if ($newParent.hasClass('leftmenu-section-items')) {
                        // Find the parent section
                        var $parentSection = $newParent.closest('.leftmenu-visual-section');
                        newLevel = parseInt($parentSection.data('level') || 0) + 1;
                    }
                    
                    // Update the item's level
                    ui.item.data('level', newLevel);
                    ui.item.css('margin-left', (newLevel * 20) + 'px');
                    
                    // If this is a section, update all children's levels recursively
                    if (ui.item.hasClass('leftmenu-visual-section')) {
                        updateChildLevels(ui.item, newLevel);
                    }
                    
                    updateMenuFromVisual();
                    updateSectionCounts();
                }
            });
        }
        
        // Update child levels recursively
        function updateChildLevels($section, parentLevel) {
            var childLevel = parentLevel + 1;
            $section.find('> .leftmenu-section-items > *').each(function() {
                var $child = $(this);
                $child.data('level', childLevel);
                $child.css('margin-left', (childLevel * 20) + 'px');
                
                if ($child.hasClass('leftmenu-visual-section')) {
                    updateChildLevels($child, childLevel);
                }
            });
        }

        // Update menu from visual
        function updateMenuFromVisual() {
            var newData = {};
            
            function processLevel($container, targetObj) {
                $container.children().each(function() {
                    var $elem = $(this);
                    
                    if ($elem.hasClass('leftmenu-visual-section')) {
                        var sectionTitle = $elem.data('section');
                        var sectionData = {};
                        
                        processLevel($elem.find('.leftmenu-section-items').first(), sectionData);
                        
                        targetObj[sectionTitle] = sectionData;
                    } else if ($elem.hasClass('leftmenu-visual-item')) {
                        var key = $elem.data('key');
                        var value = $elem.data('value');
                        
                        if (!value || value === key) {
                            targetObj[key] = key;
                        } else {
                            targetObj[key] = value;
                        }
                    }
                });
            }
            
            processLevel(LeftMenuEditor.$preview, newData);
            LeftMenuEditor.menuData = newData;
        }

        // Show add form
        function showAddForm(type) {
            var $panel = $('.leftmenu-action-panel');
            var $form = $panel.find('.leftmenu-form');
            
            $panel.slideDown();
            
            if (type === 'section') {
                $form.html(
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Section Name</label>' +
                        '<input type="text" class="leftmenu-form-input" id="leftmenu-section-name" placeholder="e.g., Documentation">' +
                    '</div>' +
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Parent Section (optional)</label>' +
                        '<select class="leftmenu-form-select" id="leftmenu-parent-section">' +
                            '<option value="">[Root Level]</option>' +
                        '</select>' +
                    '</div>' +
                    '<div style="display:flex;gap:10px">' +
                        '<button class="leftmenu-button primary" id="leftmenu-confirm-add">Add Section</button>' +
                        '<button class="leftmenu-button secondary" id="leftmenu-cancel-add">Cancel</button>' +
                    '</div>'
                );
                
                // Populate sections
                populateSections('#leftmenu-parent-section');
                
                $('#leftmenu-confirm-add').on('click', function() {
                    confirmAddSection();
                });
                
            } else if (type === 'page') {
                $form.html(
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Page Name</label>' +
                        '<input type="text" class="leftmenu-form-input" id="leftmenu-page-name" placeholder="e.g., Help:Contents">' +
                    '</div>' +
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Display Name (optional)</label>' +
                        '<input type="text" class="leftmenu-form-input" id="leftmenu-display-name" placeholder="e.g., Help & Support">' +
                    '</div>' +
                    '<div class="leftmenu-form-group">' +
                        '<label class="leftmenu-form-label">Add to Section</label>' +
                        '<select class="leftmenu-form-select" id="leftmenu-target-section">' +
                            '<option value="">[Root Level]</option>' +
                        '</select>' +
                    '</div>' +
                    '<div style="display:flex;gap:10px">' +
                        '<button class="leftmenu-button primary" id="leftmenu-confirm-add">Add Page</button>' +
                        '<button class="leftmenu-button secondary" id="leftmenu-cancel-add">Cancel</button>' +
                    '</div>'
                );
                
                populateSections('#leftmenu-target-section');
                
                $('#leftmenu-confirm-add').on('click', function() {
                    confirmAddPage();
                });
            }
            
            $('#leftmenu-cancel-add').on('click', function() {
                $panel.slideUp();
            });
            
            setTimeout(function() {
                $form.find('input:first').focus();
            }, 300);
        }

        // Populate sections dropdown
        function populateSections(selector) {
            var $select = $(selector);
            
            function addOptions(obj, prefix, level) {
                for (var key in obj) {
                    if (obj.hasOwnProperty(key) && typeof obj[key] === 'object' && 
                        !Array.isArray(obj[key]) && key.indexOf('//') !== 0) {
                        var indent = '';
                        for (var i = 0; i < level; i++) indent += ' ';
                        $select.append('<option value="' + prefix + key + '">' + indent + key + '</option>');
                        addOptions(obj[key], prefix + key + ' > ', level + 1);
                    }
                }
            }
            
            addOptions(LeftMenuEditor.menuData, '', 0);
        }

        // Confirm add section
        function confirmAddSection() {
            var name = $('#leftmenu-section-name').val().trim();
            var parent = $('#leftmenu-parent-section').val();
            
            if (!name) {
                showStatus('Please enter a section name', 'error');
                return;
            }
            
            var target = LeftMenuEditor.menuData;
            if (parent) {
                var parts = parent.split(' > ');
                for (var i = 0; i < parts.length; i++) {
                    if (!target[parts[i]]) target[parts[i]] = {};
                    target = target[parts[i]];
                }
            }
            
            if (target[name]) {
                showStatus('Section already exists', 'error');
                return;
            }
            
            target[name] = {};
            
            renderVisualMenu();
            showStatus('Section added', 'success');
            $('.leftmenu-action-panel').slideUp();
        }

        // Confirm add page
        function confirmAddPage() {
            var pageName = $('#leftmenu-page-name').val().trim();
            var displayName = $('#leftmenu-display-name').val().trim() || pageName;
            var section = $('#leftmenu-target-section').val();
            
            if (!pageName) {
                showStatus('Please enter a page name', 'error');
                return;
            }
            
            var target = LeftMenuEditor.menuData;
            if (section) {
                var parts = section.split(' > ');
                for (var i = 0; i < parts.length; i++) {
                    if (!target[parts[i]]) target[parts[i]] = {};
                    target = target[parts[i]];
                }
            }
            
            var value = displayName !== pageName ? pageName + '|' + displayName : pageName;
            target[pageName] = value;
            
            renderVisualMenu();
            showStatus('Page added', 'success');
            $('.leftmenu-action-panel').slideUp();
        }

        // Add current page
        function addCurrentPage() {
            if (isPageInMenu()) {
                showStatus('This page is already in the menu', 'error');
                return;
            }
            
            // Create a temporary draggable item
            var $item = createVisualItem(
                LeftMenuEditor.pageName,
                LeftMenuEditor.currentPage,
                'item',
                0
            );
            
            $item.css('background', '#e8f4fd').css('border-color', '#4a90e2');
            
            // Create a placeholder message
            var $placeholder = $('<div class="leftmenu-drag-message" style="text-align:center;padding:20px;background:#f0f8ff;border:2px dashed #4a90e2;margin:10px 0;border-radius:4px;">' +
                '<strong>Drag the item below to any section or position</strong>' +
                '</div>');
            
            LeftMenuEditor.$preview.prepend($placeholder);
            LeftMenuEditor.$preview.prepend($item);
            
            showStatus('Drag the current page to position it in the menu', 'info');
            
            // Make it draggable but still connected to sortable
            makeSortable(); // Re-initialize sortable to include the new item
            
            // Remove placeholder when drag starts
            $item.on('sortstart', function() {
                $placeholder.remove();
            });
            
            // The sortable stop event in makeSortable() will handle the level updates
        }

        // Re-bind events
        function bindItemEvents($item) {
            $item.off('click').on('click', function(e) {
                if (!$(e.target).closest('.leftmenu-item-actions').length) {
                    selectItem($item);
                }
            });
            
            $item.find('.leftmenu-item-edit').off('click').on('click', function(e) {
                e.stopPropagation();
                editItemInline($item);
            });
            
            $item.find('.leftmenu-item-delete').off('click').on('click', function(e) {
                e.stopPropagation();
                deleteItem($item);
            });
            
            $item.find('.leftmenu-item-duplicate').off('click').on('click', function(e) {
                e.stopPropagation();
                duplicateItem($item);
            });
        }

        // Check if key exists
        function isKeyExists(key) {
            function check(obj) {
                for (var k in obj) {
                    if (obj.hasOwnProperty(k)) {
                        if (k === key) return true;
                        if (typeof obj[k] === 'object' && check(obj[k])) return true;
                    }
                }
                return false;
            }
            return check(LeftMenuEditor.menuData);
        }

        // Check if page in menu
        function isPageInMenu() {
            var targets = [LeftMenuEditor.currentPage, LeftMenuEditor.pageName];
            
            function walk(obj) {
                for (var k in obj) {
                    if (obj.hasOwnProperty(k)) {
                        for (var i = 0; i < targets.length; i++) {
                            if (k === targets[i]) return true;
                        }
                        
                        var v = obj[k];
                        if (typeof v === 'string') {
                            var page = v.split('|')[0].replace(/\[|\]/g, '');
                            for (var j = 0; j < targets.length; j++) {
                                if (page === targets[j] || v === targets[j]) return true;
                            }
                        } else if (Array.isArray(v)) {
                            for (var a = 0; a < v.length; a++) {
                                if (typeof v[a] === 'string') {
                                    for (var t = 0; t < targets.length; t++) {
                                        if (v[a] === targets[t]) return true;
                                    }
                                }
                            }
                        } else if (typeof v === 'object' && v !== null) {
                            if (walk(v)) return true;
                        }
                    }
                }
                return false;
            }
            
            return walk(LeftMenuEditor.menuData);
        }

        // Load menu data
        function loadMenuData(callback) {
            var page = 'MediaWiki:Menu-' + LeftMenuEditor.namespace;
            
            showStatus('Loading menu from: ' + page, 'info');
            console.log('Loading from page:', page);
            
            LeftMenuEditor.api.get({
                action: 'query',
                prop: 'revisions',
                titles: page,
                rvprop: 'content',
                rvslots: 'main',
                formatversion: 2
            }).done(function (data) {
                console.log('API response:', data);
                
                var raw = '';
                // Check if page exists and has content
                if (data.query && data.query.pages && data.query.pages.length > 0) {
                    var page = data.query.pages[0];
                    console.log('Page data:', page);
                    
                    if (page.revisions && page.revisions.length > 0) {
                        var revision = page.revisions[0];
                        console.log('Revision data:', revision);
                        
                        if (revision.slots && revision.slots.main) {
                            raw = revision.slots.main.content || '';
                            console.log('Raw content:', raw);
                        }
                    } else if (page.missing) {
                        console.log('Page does not exist yet');
                        showStatus('Menu page does not exist yet. Add items to create it.', 'info');
                    }
                }
                
                // Parse JSON
                if (raw) {
                    try {
                        LeftMenuEditor.menuData = JSON.parse(raw);
                        console.log('Parsed menu data:', LeftMenuEditor.menuData);
                    } catch (e) {
                        console.error('Failed to parse menu JSON:', e);
                        console.error('Raw content that failed to parse:', raw);
                        LeftMenuEditor.menuData = {};
                        showStatus('Error parsing menu data: ' + e.message, 'error');
                    }
                } else {
                    LeftMenuEditor.menuData = {};
                    console.log('No content found, starting with empty menu');
                }
                
                renderVisualMenu();
                $('.leftmenu-status').fadeOut(3000);
                if (typeof callback === 'function') { callback(); }
            }).fail(function(error) {
                console.error('API request failed:', error);
                showStatus('Failed to load menu data: ' + (error.error ? error.error.info : 'Unknown error'), 'error');
                LeftMenuEditor.menuData = {};
                renderVisualMenu();
            });
        }

        // Save menu
        function saveMenu() {
            var page = 'MediaWiki:Menu-' + LeftMenuEditor.namespace;
            var json = JSON.stringify(LeftMenuEditor.menuData, null, 2);

            $('.leftmenu-save').prop('disabled', true).text('Saving...');

            LeftMenuEditor.api.postWithToken('csrf', {
                action: 'edit',
                title: page,
                text: json,
                summary: 'Updated menu structure',
                contentformat: 'text/x-wiki',
                contentmodel: 'wikitext'
            }).done(function () {
                showStatus('Menu saved successfully!', 'success');
                $('.leftmenu-save').text('Saved!');
                setTimeout(function () { 
                    location.reload(); 
                }, 1500);
            }).fail(function (err) {
                showStatus('Failed to save: ' + (err.error ? err.error.info : err), 'error');
                $('.leftmenu-save').prop('disabled', false).text('Save Changes');
            });
        }

        // Reset menu
        function resetMenu() {
            if (confirm('Discard all changes and reload?')) {
                loadMenuData(function() {
                    showStatus('Menu reset', 'info');
                });
            }
        }

        // Toggle JSON view
        function toggleJsonView() {
            var $jsonView = $('.leftmenu-json-view');
            if ($jsonView.is(':visible')) {
                $jsonView.slideUp();
                $('.leftmenu-view-json').text('View JSON');
            } else {
                $jsonView.text(JSON.stringify(LeftMenuEditor.menuData, null, 2)).slideDown();
                $('.leftmenu-view-json').text('Hide JSON');
            }
        }

        // Show status
        function showStatus(msg, type) {
            $('.leftmenu-status')
                .removeClass('success error info')
                .addClass(type)
                .text(msg)
                .slideDown()
                .delay(3000)
                .slideUp();
        }

        // HTML escape
        function escapeHtml(text) {
            var map = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#039;'
            };
            return String(text).replace(/[&<>"']/g, function(m) { return map[m]; });
        }

        // Event bindings
        function bindEvents() {
            // Header toggle - make the container collapsible
            $('.leftmenu-editor-header').on('click', function() {
                $('.leftmenu-editor-container').toggleClass('collapsed');
                // Load menu data if expanding and on menu tab
                if (!$('.leftmenu-editor-container').hasClass('collapsed')) {
                    if ($('#menu-editor-tab').hasClass('active') && !LeftMenuEditor.menuData) {
                        loadMenuData();
                    }
                }
            });
            
            // Quick actions
            $('.leftmenu-quick-action').on('click', function() {
                var action = $(this).data('action');
                
                switch(action) {
                    case 'add-section':
                        showAddForm('section');
                        break;
                    case 'add-page':
                        showAddForm('page');
                        break;
                    case 'add-current':
                        addCurrentPage();
                        break;
                    case 'import':
                        showStatus('Import feature coming soon', 'info');
                        break;
                }
            });
            
            // Search
            $('.leftmenu-search').on('input', function() {
                var query = $(this).val().toLowerCase();
                
                $('.leftmenu-visual-item, .leftmenu-visual-section').each(function() {
                    var $item = $(this);
                    var text = $item.text().toLowerCase();
                    
                    if (!query || text.indexOf(query) > -1) {
                        $item.show();
                        // Show parent sections
                        if (query) {
                            $item.parents('.leftmenu-visual-section').show().removeClass('collapsed');
                        }
                    } else {
                        $item.hide();
                    }
                });
            });
            
            // Empty state button
            $('.leftmenu-empty-add').on('click', function() {
                showAddForm('page');
            });
            
            // Control buttons
            $('.leftmenu-save').on('click', saveMenu);
            $('.leftmenu-reset').on('click', resetMenu);
            $('.leftmenu-view-json').on('click', toggleJsonView);
        }

        // Initialize
        addStyles();
        createInterface();
        bindEvents();

    });

})(mediaWiki, jQuery);
MDriven Chat

How would you like to chat today?

Setting up your conversation…

This may take a few moments