Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MediaWiki:Common.js: Difference between revisions

MediaWiki interface page
No edit summary
mNo edit summary
 
(171 intermediate revisions by the same user not shown)
Line 1: Line 1:
/* Any JavaScript here will be loaded for all users on every page load. */
/* Any JavaScript here will be loaded for all users on every page load. */
$(function(){
$(document).ready(function () {
  $('.card').on('mousenter', function(event){
     setTimeout(() => {
     event.preventDefault();
        $('body').addClass('fade-in');
    $(this).toggleClass('hovered');
     }, 100); // 0.1s delay before showing content
  });
  $('.card').on('mouseleave', function(event){
    event.preventDefault();
     $(this).toggleClass('hovered');
  });
});
});
document.querySelectorAll('.sub-card').forEach(card => {
    card.addEventListener('click', function(event) {
        event.stopPropagation(); // Prevent event bubbling


         // Toggle the expanded state of the clicked card
$(document).ready(function () {
         const isExpanded = card.getAttribute('data-expanded') === 'true';
    // Immediately inject the loading screen before anything else
          
    var loadingScreen = document.createElement("div");
         // Flip the current sub-card
    loadingScreen.id = "loading-screen";
         card.setAttribute('data-expanded', isExpanded ? 'false' : 'true');
    loadingScreen.innerHTML =
         `<div class="loading-circle"></div>
        <p id="loading-message">Loading...</p>`;
    document.body.prepend(loadingScreen);
 
    // Create the <p> tag dynamically to display messages
    var messageTag = document.createElement("p");
    messageTag.id = "dynamic-message";
    loadingScreen.appendChild(messageTag); // Add the new message tag to the loading screen
 
    // Check if it's the user's first visit by using localStorage
    if (!localStorage.getItem("visitedBefore")) {
        localStorage.setItem("visitedBefore", "true");
 
        // Show the welcome and preload messages immediately
        document.getElementById("dynamic-message").innerHTML = "Welcome to the Chrome Engine Modding Wiki ❤️<br>Uh oh I have never seen you here before, let me preload some stuff";
 
        // After 3 seconds, switch to the random message
        setTimeout(() => {
            displayRandomMessage();
        }, 8000);  // Wait for 8 seconds before changing the message
    } else {
        // If not first visit, just show the loading message as normal
        setTimeout(() => {
            displayRandomMessage();
        }, 100);  // Wait for 0.1 second to show the random message
    }
 
    // Function to display a random message
    function displayRandomMessage() {
        var messages = [
            "Hold on, just a second while we get things ready for you!",
            "Almost done loading everything for you!",
            "Preloading the cool stuff... be right there!"
        ];
         var randomMessage = messages[Math.floor(Math.random() * messages.length)];
        document.getElementById("dynamic-message").innerHTML = randomMessage;
    }
 
    // Apply background styles based on categories
    var categories = mw.config.get("wgCategories");
    var categoryBackgrounds = {
        "Dead Island": ["https://cemodding.wiki/images/5/5b/Dead_islan_background.png"],
        "Dying Light": ["https://cemodding.wiki/images/f/fe/Dying_light.png"],
        "Call of Juarez: Gunslinger": ["https://cemodding.wiki/images/4/4b/Call_of_juaez_gunslinger.png"],
        "Dead Island: Riptide": ["https://cemodding.wiki/images/b/b6/Random_project_di_riptide_1.png"],
        "Dead Island: Riptide DE": ["https://cemodding.wiki/images/0/09/Dead_island_riptide_DE.png"],
        "Call of Juarez: BiB": ["https://cemodding.wiki/images/2/24/Project_juaez_no_title_1.png"],
        "Call of Juarez: The Cartel": ["https://cemodding.wiki/images/6/64/Callofjuarezcartel.png"],
        "Call of Juarez": [
            "https://cemodding.wiki/images/c/cf/Call_of_juarez_background_1.png",
            "https://cemodding.wiki/images/3/38/Call_of_juarez_background_2.png"
        ],
        "Dead Island DE": ["https://cemodding.wiki/images/4/45/Dead_island_DE.png"],
        "Dying Light: The Beast": [
            "https://cemodding.wiki/images/1/12/Dying_light_the_beast.png",
            "https://cemodding.wiki/images/c/c3/Dying_light_the_beast_2.png"
        ],
         "Dying Light 2": [
            "https://cemodding.wiki/images/0/04/Dying_light_2.png",
            "https://cemodding.wiki/images/0/02/Dying_light_2_.png",
            "https://cemodding.wiki/images/3/3f/Dying_light_2_some_layered_effects.png"
         ]
    };
 
    var defaultBackgrounds = ["https://cemodding.wiki/images/1/1f/Wiki_page.png"];
 
    function getRandomBackground(images) {
        return images[Math.floor(Math.random() * images.length)];
    }
 
    let selectedBackground = null;
 
    function applyBackground() {
        const htmlElement = document.documentElement;
        const isLightMode = htmlElement.classList.contains("skin-citizen-light");
        const isPureBlackMode = htmlElement.classList.contains("citizen-feature-pure-black-clientpref-0");
 
        if (isPureBlackMode) {
            $("body").css({
                "background": "var(--color-surface-1)",
                "background-repeat": "no-repeat",
                "background-position": "top center",
                "background-size": "cover",
                "background-attachment": "fixed"
            });
         } else {
            if (isLightMode) {
                $("body").css({
                    "background": 'var(--color-surface-1)',
                    "background-repeat": "no-repeat",
                    "background-position": "top center",
                    "background-size": "cover",
                    "background-attachment": "fixed"
                });
            } else {
                if (!selectedBackground) {
                    for (let category of categories) {
                        if (categoryBackgrounds[category]) {
                            selectedBackground = getRandomBackground(categoryBackgrounds[category]);
                            break;
                        }
                    }
                    if (!selectedBackground) {
                        selectedBackground = getRandomBackground(defaultBackgrounds);
                    }
                }
 
                $("body").css({
                    "background": `linear-gradient(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.15)), url("${selectedBackground}")`,
                    "background-repeat": "no-repeat",
                    "background-position": "top center",
                    "background-size": "cover",
                    "background-attachment": "fixed"
                });
            }
        }
    }
 
    applyBackground();
 
    const observer = new MutationObserver(() => {
        setTimeout(() => applyBackground(), 50);
    });
 
    observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
 
    // Show loading screen until everything is ready
    $("#loading-screen").fadeIn();
 
    var imagesToLoad = [...Object.values(categoryBackgrounds).flat(), ...defaultBackgrounds];
    var loadedImages = 0;


         // Hide all other sub-cards
    imagesToLoad.forEach(function (imageUrl) {
         document.querySelectorAll('.sub-card').forEach(otherCard => {
         var img = new Image();
             if (otherCard !== card) {
         img.onload = function () {
                 otherCard.setAttribute('data-expanded', 'false');
            loadedImages++;
             if (loadedImages === imagesToLoad.length) {
                 $("#loading-screen").fadeOut(1000, function () {
                    $(this).remove();
                });
             }
             }
         });
         };
        img.src = imageUrl;
     });
     });
});
});


document.querySelectorAll('.card').forEach(card => {
function preloadOnHover() {
     card.addEventListener('mouseleave', function() {
     $("a").on("mouseenter", function () {
         // Collapse all sub-cards when mouse leaves the main card
         var url = $(this).attr("href");
         document.querySelectorAll('.sub-card').forEach(subCard => {
 
             subCard.setAttribute('data-expanded', 'false');
         if (url && !$(this).data("preloaded")) {
         });
            var link = document.createElement("link");
            link.rel = "prefetch";
            link.href = url;
             document.head.appendChild(link);
 
            $(this).data("preloaded", true); // Mark it as preloaded
         }
     });
     });
}
// Run the function when the page loads
$(document).ready(function () {
    preloadOnHover();
});
});


$(document).ready(function() {
 
     // Click event for the header or the arrow
// Function to trigger file download when the image is clicked
     $('.mw-collapsible-header').click(function() {
function downloadFile(filePath) {
        var parentDiv = $(this).closest('.mw-collapsible');
    var a = document.createElement('a');
         var content = parentDiv.find('.mw-collapsible-content');
    a.href = filePath;
    a.download = '';  // This triggers the download
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);  // Clean up
}
 
 
$(function () {
    var categoryList = [];
 
     // Fetch categories from the API
    $.ajax({
        url: mw.util.wikiScript('api'),
        data: {
            action: 'query',
            list: 'allcategories',
            aclimit: '500',
            format: 'json'
        },
        dataType: 'json',
        success: function (data) {
            categoryList = data.query.allcategories.map(function (cat) {
                return cat['*'];
            });
        }
    });
 
     function createSuggestionBox(input, suggestions, cursorPosition) {
        $('.category-suggestions').remove(); // Clear old suggestions
 
        var suggestionBox = $('<ul class="category-suggestions"></ul>').css({
            position: 'absolute',
            zIndex: 1000,
            backgroundColor: 'rgba(0, 0, 0, 0.7)',
            color: 'white',
            border: '1px solid #ccc',
            padding: '0',
            listStyleType: 'none',
            margin: '0',
            maxHeight: '200px',
            overflowY: 'auto',
            cursor: 'pointer'
        });
 
        suggestions.forEach(function (suggestion) {
            var item = $('<li></li>').text(suggestion).css({ padding: '5px' });
            item.on('mousedown', function () {
                var text = input.val();
                var beforeCursor = text.substring(0, cursorPosition).replace(/\[\[Category:[^\]]*$/, '[[Category:' + suggestion);
                var afterCursor = text.substring(cursorPosition);
                input.val(beforeCursor + afterCursor);
                suggestionBox.remove();
            });
            suggestionBox.append(item);
        });
 
        $('body').append(suggestionBox);
        positionSuggestionBox(input, cursorPosition, suggestionBox);
    }
 
    function positionSuggestionBox(input, cursorPos, suggestionBox) {
         var text = input.val().substring(0, cursorPos);
        var textarea = input[0];
        var div = $('<div></div>').css({
            position: 'absolute',
            whiteSpace: 'pre-wrap',
            wordWrap: 'break-word',
            visibility: 'hidden',
            font: input.css('font'),
            padding: input.css('padding'),
            width: input.width(),
            lineHeight: input.css('line-height')
        }).appendTo('body');
          
          
         // Toggle the collapse/expand state
         // Simulate the text up to the cursor
         parentDiv.toggleClass('mw-collapsed');
        var beforeCursorText = text.replace(/ /g, '\u00a0');  // Non-breaking spaces for correct width
          
        div.text(beforeCursorText);
         // Toggle visibility of the content
        var span = $('<span>|</span>').appendTo(div);  // Add a cursor marker
         content.stop(true, true).slideToggle(); // Stop any ongoing animation before toggling visibility
        var cursorOffset = span.offset();
 
        // Adjust position to match textarea
        var inputOffset = input.offset();
         suggestionBox.css({
            top: inputOffset.top + (cursorOffset.top - div.offset().top) + parseInt(input.css('padding-top'), 10),
            left: inputOffset.left + (cursorOffset.left - div.offset().left) + parseInt(input.css('padding-left'), 10)
        });
 
        div.remove();
    }
 
    $('#wpTextbox1').on('input', function () {
        var input = $(this);
        var cursorPos = this.selectionStart;
         var text = input.val().substring(0, cursorPos);
         var match = text.match(/\[\[Category:([^\]]*)$/);
         if (match) {
            var partial = match[1].toLowerCase();
            var matches = categoryList.filter(function (category) {
                return category.toLowerCase().startsWith(partial);
            }).slice(0, 10); // Limit suggestions
            if (matches.length) {
                createSuggestionBox(input, matches, cursorPos);
            }
        } else {
            $('.category-suggestions').remove();
        }
     });
     });


    // Ensure that the arrow starts pointing up for expanded sections by default
     $(document).on('mousedown', function (e) {
     $('.mw-collapsible').each(function() {
         if (!$(e.target).closest('.category-suggestions').length) {
         var parentDiv = $(this);
            $('.category-suggestions').remove();
        var content = parentDiv.find('.mw-collapsible-content');
       
        if (!parentDiv.hasClass('mw-collapsed')) {
            content.show(); // Ensure content is visible
         }
         }
     });
     });
Line 63: Line 298:


$(document).ready(function() {
$(document).ready(function() {
  // Check if there are categories in the page
    $('.mw-collapsible-header').each(function() {
  var categories = mw.config.get('wgCategories');
        // Wrap indicator and spinner inside a container for positioning
        $(this).prepend('<span class="mw-collapsible-icon"><span class="mw-collapsible-indicator">•</span><span class="mw-collapsible-loading hidden"></span></span> ');
    });
 
    $('.mw-collapsible-header').click(function() {
        var parentDiv = $(this).closest('.mw-collapsible');
        var content = parentDiv.find('.mw-collapsible-content');
        var indicator = $(this).find('.mw-collapsible-indicator');
        var spinner = $(this).find('.mw-collapsible-loading');


  // Define a mapping of categories to background images
        // Fade out indicator and show spinner at the same position
  var categoryBackgrounds = {
        indicator.addClass('fade-out');
    'Dead Island': 'linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url("https://www.chromengine.com/images/c/c9/DIBackground.jpg")',
        setTimeout(() => {
    'Dying Light': 'linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url("https://www.chromengine.com/images/2/26/Background.png")',
            spinner.removeClass('hidden');
    'Call of Juarez: BiB': 'linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.5)), url("https://www.chromengine.com/images/3/36/Random_project_call_of_juaez_gunslingerupscaled.png")',
        }, 100);
    'Dead Island Riptide': 'linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.5)), url("https://www.chromengine.com/images/b/b6/Random_project_di_riptide_1.png")'
  };


  // Default background image if no category matches
        // Toggle content visibility
  var defaultBackground = 'linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url("https://www.chromengine.com/images/8/89/Newbackground.png")';
        parentDiv.toggleClass('mw-collapsed');
        content.stop(true, true).slideToggle();


  // Variable to check if a category matches
        // Restore indicator and hide spinner after animation
  var backgroundImageSet = false;
        setTimeout(function() {
            indicator.removeClass('fade-out');
            spinner.addClass('hidden');
        }, 300);
    });


  // Iterate through categories to find a matching background
    // Ensure correct initial state for collapsibles
  categories.forEach(function(category) {
     $('.mw-collapsible').each(function() {
     if (categoryBackgrounds[category]) {
         var parentDiv = $(this);
      $('body').css({
         var content = parentDiv.find('.mw-collapsible-content');
         'background':  categoryBackgrounds[category],
         'background-repeat': 'no-repeat',
        'background-position': 'top center',
        'background-size': 'cover',
        'opactiy': 30,
        'transition': 'opacity 0.5s ease',
        'background-attachment': 'fixed'
      });
      backgroundImageSet = true;
    }
  });


  // If no category matched, apply the default background
        if (parentDiv.hasClass('mw-collapsed')) {
  if (!backgroundImageSet) {
            content.hide();
    $('body').css({
         } else {
      'background-image': defaultBackground,
            content.show();
         'background-repeat': 'no-repeat',
         }
        'background-position': 'top center',
        'background-size': 'cover',
        'opactiy': 30,
        'transition': 'opacity 0.5s ease',
         'background-attachment': 'fixed'
     });
     });
  }
});
});

Latest revision as of 03:39, 9 March 2025

/* Any JavaScript here will be loaded for all users on every page load. */
$(document).ready(function () {
    setTimeout(() => {
        $('body').addClass('fade-in');
    }, 100); // 0.1s delay before showing content
});

$(document).ready(function () {
    // Immediately inject the loading screen before anything else
    var loadingScreen = document.createElement("div");
    loadingScreen.id = "loading-screen";
    loadingScreen.innerHTML = 
        `<div class="loading-circle"></div>
        <p id="loading-message">Loading...</p>`;
    document.body.prepend(loadingScreen);

    // Create the <p> tag dynamically to display messages
    var messageTag = document.createElement("p");
    messageTag.id = "dynamic-message";
    loadingScreen.appendChild(messageTag); // Add the new message tag to the loading screen

    // Check if it's the user's first visit by using localStorage
    if (!localStorage.getItem("visitedBefore")) {
        localStorage.setItem("visitedBefore", "true");

        // Show the welcome and preload messages immediately
        document.getElementById("dynamic-message").innerHTML = "Welcome to the Chrome Engine Modding Wiki ❤️<br>Uh oh I have never seen you here before, let me preload some stuff";

        // After 3 seconds, switch to the random message
        setTimeout(() => {
            displayRandomMessage();
        }, 8000);  // Wait for 8 seconds before changing the message
    } else {
        // If not first visit, just show the loading message as normal
        setTimeout(() => {
            displayRandomMessage();
        }, 100);  // Wait for 0.1 second to show the random message
    }

    // Function to display a random message
    function displayRandomMessage() {
        var messages = [
            "Hold on, just a second while we get things ready for you!",
            "Almost done loading everything for you!",
            "Preloading the cool stuff... be right there!"
        ];
        var randomMessage = messages[Math.floor(Math.random() * messages.length)];
        document.getElementById("dynamic-message").innerHTML = randomMessage;
    }

    // Apply background styles based on categories
    var categories = mw.config.get("wgCategories");
    var categoryBackgrounds = {
        "Dead Island": ["https://cemodding.wiki/images/5/5b/Dead_islan_background.png"],
        "Dying Light": ["https://cemodding.wiki/images/f/fe/Dying_light.png"],
        "Call of Juarez: Gunslinger": ["https://cemodding.wiki/images/4/4b/Call_of_juaez_gunslinger.png"],
        "Dead Island: Riptide": ["https://cemodding.wiki/images/b/b6/Random_project_di_riptide_1.png"],
        "Dead Island: Riptide DE": ["https://cemodding.wiki/images/0/09/Dead_island_riptide_DE.png"],
        "Call of Juarez: BiB": ["https://cemodding.wiki/images/2/24/Project_juaez_no_title_1.png"],
        "Call of Juarez: The Cartel": ["https://cemodding.wiki/images/6/64/Callofjuarezcartel.png"],
        "Call of Juarez": [
            "https://cemodding.wiki/images/c/cf/Call_of_juarez_background_1.png",
            "https://cemodding.wiki/images/3/38/Call_of_juarez_background_2.png"
        ],
        "Dead Island DE": ["https://cemodding.wiki/images/4/45/Dead_island_DE.png"],
        "Dying Light: The Beast": [
            "https://cemodding.wiki/images/1/12/Dying_light_the_beast.png",
            "https://cemodding.wiki/images/c/c3/Dying_light_the_beast_2.png"
        ],
        "Dying Light 2": [
            "https://cemodding.wiki/images/0/04/Dying_light_2.png",
            "https://cemodding.wiki/images/0/02/Dying_light_2_.png",
            "https://cemodding.wiki/images/3/3f/Dying_light_2_some_layered_effects.png"
        ]
    };

    var defaultBackgrounds = ["https://cemodding.wiki/images/1/1f/Wiki_page.png"];

    function getRandomBackground(images) {
        return images[Math.floor(Math.random() * images.length)];
    }

    let selectedBackground = null;

    function applyBackground() {
        const htmlElement = document.documentElement;
        const isLightMode = htmlElement.classList.contains("skin-citizen-light");
        const isPureBlackMode = htmlElement.classList.contains("citizen-feature-pure-black-clientpref-0");

        if (isPureBlackMode) {
            $("body").css({
                "background": "var(--color-surface-1)", 
                "background-repeat": "no-repeat",
                "background-position": "top center",
                "background-size": "cover",
                "background-attachment": "fixed"
            });
        } else {
            if (isLightMode) {
                $("body").css({
                    "background": 'var(--color-surface-1)',
                    "background-repeat": "no-repeat",
                    "background-position": "top center",
                    "background-size": "cover",
                    "background-attachment": "fixed"
                });
            } else {
                if (!selectedBackground) {
                    for (let category of categories) {
                        if (categoryBackgrounds[category]) {
                            selectedBackground = getRandomBackground(categoryBackgrounds[category]);
                            break;
                        }
                    }
                    if (!selectedBackground) {
                        selectedBackground = getRandomBackground(defaultBackgrounds);
                    }
                }

                $("body").css({
                    "background": `linear-gradient(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.15)), url("${selectedBackground}")`,
                    "background-repeat": "no-repeat",
                    "background-position": "top center",
                    "background-size": "cover",
                    "background-attachment": "fixed"
                });
            }
        }
    }

    applyBackground();

    const observer = new MutationObserver(() => {
        setTimeout(() => applyBackground(), 50);
    });

    observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });

    // Show loading screen until everything is ready
    $("#loading-screen").fadeIn();

    var imagesToLoad = [...Object.values(categoryBackgrounds).flat(), ...defaultBackgrounds];
    var loadedImages = 0;

    imagesToLoad.forEach(function (imageUrl) {
        var img = new Image();
        img.onload = function () {
            loadedImages++;
            if (loadedImages === imagesToLoad.length) {
                $("#loading-screen").fadeOut(1000, function () {
                    $(this).remove();
                });
            }
        };
        img.src = imageUrl;
    });
});

function preloadOnHover() {
    $("a").on("mouseenter", function () {
        var url = $(this).attr("href");

        if (url && !$(this).data("preloaded")) {
            var link = document.createElement("link");
            link.rel = "prefetch";
            link.href = url;
            document.head.appendChild(link);

            $(this).data("preloaded", true); // Mark it as preloaded
        }
    });
}

// Run the function when the page loads
$(document).ready(function () {
    preloadOnHover();
});


// Function to trigger file download when the image is clicked
function downloadFile(filePath) {
    var a = document.createElement('a');
    a.href = filePath;
    a.download = '';  // This triggers the download
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);  // Clean up
}


$(function () {
    var categoryList = [];

    // Fetch categories from the API
    $.ajax({
        url: mw.util.wikiScript('api'),
        data: {
            action: 'query',
            list: 'allcategories',
            aclimit: '500',
            format: 'json'
        },
        dataType: 'json',
        success: function (data) {
            categoryList = data.query.allcategories.map(function (cat) {
                return cat['*'];
            });
        }
    });

    function createSuggestionBox(input, suggestions, cursorPosition) {
        $('.category-suggestions').remove(); // Clear old suggestions

        var suggestionBox = $('<ul class="category-suggestions"></ul>').css({
            position: 'absolute',
            zIndex: 1000,
            backgroundColor: 'rgba(0, 0, 0, 0.7)',
            color: 'white',
            border: '1px solid #ccc',
            padding: '0',
            listStyleType: 'none',
            margin: '0',
            maxHeight: '200px',
            overflowY: 'auto',
            cursor: 'pointer'
        });

        suggestions.forEach(function (suggestion) {
            var item = $('<li></li>').text(suggestion).css({ padding: '5px' });
            item.on('mousedown', function () {
                var text = input.val();
                var beforeCursor = text.substring(0, cursorPosition).replace(/\[\[Category:[^\]]*$/, '[[Category:' + suggestion);
                var afterCursor = text.substring(cursorPosition);
                input.val(beforeCursor + afterCursor);
                suggestionBox.remove();
            });
            suggestionBox.append(item);
        });

        $('body').append(suggestionBox);
        positionSuggestionBox(input, cursorPosition, suggestionBox);
    }

    function positionSuggestionBox(input, cursorPos, suggestionBox) {
        var text = input.val().substring(0, cursorPos);
        var textarea = input[0];
        var div = $('<div></div>').css({
            position: 'absolute',
            whiteSpace: 'pre-wrap',
            wordWrap: 'break-word',
            visibility: 'hidden',
            font: input.css('font'),
            padding: input.css('padding'),
            width: input.width(),
            lineHeight: input.css('line-height')
        }).appendTo('body');
        
        // Simulate the text up to the cursor
        var beforeCursorText = text.replace(/ /g, '\u00a0');  // Non-breaking spaces for correct width
        div.text(beforeCursorText);
        var span = $('<span>|</span>').appendTo(div);  // Add a cursor marker
        var cursorOffset = span.offset();

        // Adjust position to match textarea
        var inputOffset = input.offset();
        suggestionBox.css({
            top: inputOffset.top + (cursorOffset.top - div.offset().top) + parseInt(input.css('padding-top'), 10),
            left: inputOffset.left + (cursorOffset.left - div.offset().left) + parseInt(input.css('padding-left'), 10)
        });

        div.remove();
    }

    $('#wpTextbox1').on('input', function () {
        var input = $(this);
        var cursorPos = this.selectionStart;
        var text = input.val().substring(0, cursorPos);
        var match = text.match(/\[\[Category:([^\]]*)$/);
        if (match) {
            var partial = match[1].toLowerCase();
            var matches = categoryList.filter(function (category) {
                return category.toLowerCase().startsWith(partial);
            }).slice(0, 10);  // Limit suggestions
            if (matches.length) {
                createSuggestionBox(input, matches, cursorPos);
            }
        } else {
            $('.category-suggestions').remove();
        }
    });

    $(document).on('mousedown', function (e) {
        if (!$(e.target).closest('.category-suggestions').length) {
            $('.category-suggestions').remove();
        }
    });
});

$(document).ready(function() {
    $('.mw-collapsible-header').each(function() {
        // Wrap indicator and spinner inside a container for positioning
        $(this).prepend('<span class="mw-collapsible-icon"><span class="mw-collapsible-indicator">•</span><span class="mw-collapsible-loading hidden"></span></span> ');
    });

    $('.mw-collapsible-header').click(function() {
        var parentDiv = $(this).closest('.mw-collapsible');
        var content = parentDiv.find('.mw-collapsible-content');
        var indicator = $(this).find('.mw-collapsible-indicator');
        var spinner = $(this).find('.mw-collapsible-loading');

        // Fade out indicator and show spinner at the same position
        indicator.addClass('fade-out');
        setTimeout(() => {
            spinner.removeClass('hidden');
        }, 100);

        // Toggle content visibility
        parentDiv.toggleClass('mw-collapsed');
        content.stop(true, true).slideToggle();

        // Restore indicator and hide spinner after animation
        setTimeout(function() {
            indicator.removeClass('fade-out');
            spinner.addClass('hidden');
        }, 300);
    });

    // Ensure correct initial state for collapsibles
    $('.mw-collapsible').each(function() {
        var parentDiv = $(this);
        var content = parentDiv.find('.mw-collapsible-content');

        if (parentDiv.hasClass('mw-collapsed')) {
            content.hide();
        } else {
            content.show();
        }
    });
});
Cookies help us deliver our services. By using our services, you agree to our use of cookies.