MediaWiki:Common.js

From Makerpedia

Revision as of 20:36, 21 February 2025 by GiseleN (talk | contribs) (changing insertImage parameters)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* Any JavaScript here will be loaded for all users on every page load. */

if (document) window.µ = function (id, elem) {
  var ret;
  var root = ((elem) ? elem : document);
  switch (id.charAt(0)) {
    case '|':
      ret = root;
      break;
    case '+':
      ret = document.createElement(id.substring(1));
      if (elem) elem.appendChild(ret);
      break;
    case '#':
      ret = root.querySelector(id);
      break;
    default:
      ret = Array.prototype.slice.call(root.querySelectorAll(id));
      break;
  }

  return ret;
};

/* add additional edit button -- styled in Medik.css */ 
/* Takes them to visual editor if available/logged in; if not, takes them to normal edit mode; if they are not logged in at all, takes them to login page */
let editLinkQuery = document.querySelector("#ca-ve-edit a") ? "#ca-ve-edit a" : (document.querySelector("#ca-edit a") ? "#ca-edit a" : "#pt-login a");
document.getElementById("content").innerHTML += '<a href='+document.querySelector(editLinkQuery).href+'><button class="big-edit-button"><p>EDIT</p></button></a>';

/* looks at current url parameters of the form '?param1=value1&param2=value2...' and returns a dictionary of the form {param1: value1, param2: value2, ...} */
function parseUrlParameters() {
    let queryStr = window.location.search.substring(1).replaceAll("%20", " "); // start string after the question mark and replace '%20' with spaces
    let queryDict = {};
    queryStr.split("&").forEach(function(query) {
        let pair = query.split("=");
        queryDict[pair[0]] = pair[1];
    })
    return queryDict;
}

// Gallery
mw.loader.using(['mediawiki.api', 'jquery'], function () {
    $(document).ready(function () {
        if (mw.config.get('wgPageName') !== 'GALLERY') return;  // Ensure script runs only on the Gallery page

        // get url parameters and automatically select appropriate filter
        let queryDict = parseUrlParameters();
        var category = queryDict['filter'] ? queryDict['filter'] : "Projects"; // If no filter query in url, use default category
        var galleryContainer = $('#project-gallery');  

        
        galleryContainer.before('<div id="category-filter">' +
        '<button class="filter-btn" data-filter="Projects">Show All</button>' +
        '<button class="filter-btn" data-filter="Textiles">Textiles</button>' +
        '<button class="filter-btn" data-filter="Crafting">Crafting</button>' +
        '<button class="filter-btn" data-filter="Airbrushing">Airbrushing</button>' +
        '<button class="filter-btn" data-filter="Button Pressing">Button Pressing</button>' +
        '<button class="filter-btn" data-filter="Cassette Making">Cassette Making</button>' +
        '<button class="filter-btn" data-filter="Graphic Design">Graphic Design</button>' +
        '<button class="filter-btn" data-filter="Hand Sewing">Hand Sewing</button>' +
        '<button class="filter-btn" data-filter="Laser Cutting">Laser Cutting</button>' +
        '<button class="filter-btn" data-filter="Machining">Machining</button>' +
        '<button class="filter-btn" data-filter="3D Modeling">3D Modeling</button>' +
        '<button class="filter-btn" data-filter="3D Printing">3D Printing</button>' +
        '<button class="filter-btn" data-filter="Programming">Programming</button>' +
        '<button class="filter-btn" data-filter="Soldering">Soldering</button>' +
        '<button class="filter-btn" data-filter="Technical Design">Technical Design</button>' +
        '<button class="filter-btn" data-filter="Welding">Welding</button>' +
        '<button class="filter-btn" data-filter="Woodworking">Woodworking</button>' +
        '</div>');

        // load gallery based on category
        function loadGallery(category) {
            galleryContainer.html('<div class="gallery-container">Loading gallery...</div>');  

            new mw.Api().get({
                action: 'query',
                list: 'categorymembers',
                cmtitle: 'Category:' + category,
                cmlimit: 50,  
                format: 'json'
            }).done(function (data) {
                var pages = data.query.categorymembers;
                var galleryHtml = '';

                var requests = pages.map(function (page) {
                    return new mw.Api().get({
                        action: 'query',
                        prop: 'revisions',
                        rvprop: 'content',
                        titles: page.title,
                        format: 'json'
                    }).then(function (pageData) {
                        var pageId = Object.keys(pageData.query.pages)[0];
                        var content = pageData.query.pages[pageId].revisions[0]['*'];
                        var pageUrl = mw.util.getUrl(page.title);
                        var imgUrl = '';

                        // Try to find a direct image URL (img1=https://...)
                        var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);
                        if (directMatch) {
                            imgUrl = directMatch[1];
                        }

                        // If no direct URL, try to find a [[File:...]] entry
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);
                        if (!imgUrl && fileMatch) {
                            var fileName = fileMatch[1].trim();

                            // Fetch full image URL from MediaWiki API
                            return new mw.Api().get({
                                action: 'query',
                                titles: 'File:' + fileName,
                                prop: 'imageinfo',
                                iiprop: 'url',
                                format: 'json'
                            }).then(function (imageData) {
                                var imagePageId = Object.keys(imageData.query.pages)[0];
                                if (imageData.query.pages[imagePageId].imageinfo) {
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;
                                }

                               
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);
                            });
                        } else {
                            // Add the gallery item if the image was found
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);
                        }
                    });
                });

                Promise.all(requests).then(function () {
                    
                    galleryContainer.html('<div class="gallery-container">' + galleryHtml + '</div>');
                });
            });
        }

        // generate a gallery
        function generateGalleryItem(pageUrl, title, imgUrl, category) {
            return `
                <div class="gallery-item ${category}">
                    <a href="${pageUrl}">
                        ${imgUrl ? `<img src="${imgUrl}" alt="${title}">` : `<img src="https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg" alt="No Image Available">`}

                    </a>
                    <div class="gallery-caption">
                        <a href="${pageUrl}">${title}</a>
                    </div>
                </div>
            `;
        }

        loadGallery(category);
        // find filter button corresponding to preselected category and add css class
        $(".filter-btn").each(function () { $(this).data("filter") === category ? $(this).addClass('selected-filter') : null});

        $(".filter-btn").click(function () {
            var selectedCategory = $(this).data("filter");
            loadGallery(selectedCategory);  
            $('.filter-btn.selected-filter').each((i, elem) => $(elem).removeClass('selected-filter'));
            $(this).addClass('selected-filter');
        });
    });
});

// TOOLS Gallery
mw.loader.using(['mediawiki.api', 'jquery'], function () {
    $(document).ready(function () {
        if (mw.config.get('wgPageName') !== 'TOOLS') return;  // Ensure script runs only on the TOOLS page

        // get url parameters and automatically select appropriate filter
        let queryDict = parseUrlParameters();
        var category = queryDict['filter'] ? queryDict['filter'] : "Tools"; // If no filter query in url, use default category
        var galleryContainer = $('#tools-gallery');  

        // Add filter buttons before the gallery
        galleryContainer.before('<div id="category-filter">' +
            '<button class="filter-btn" data-filter="Tools">Show All</button>' +  
            '<button class="filter-btn" data-filter="Makerspace Tools">Makerspace Tools</button>' +
            '<button class="filter-btn" data-filter="Wood Shop Tools">Wood Shop Tools</button>' +
            '<button class="filter-btn" data-filter="Machine Shop Tools">Machine Shop Tools</button>' +
        '</div>');

        function loadGallery(category) {
            galleryContainer.html('<div class="gallery-container">Loading gallery...</div>');  

            new mw.Api().get({
                action: 'query',
                list: 'categorymembers',
                cmtitle: 'Category:' + category,
                cmlimit: 50,  
                format: 'json'
            }).done(function (data) {
                var pages = data.query.categorymembers;
                var galleryHtml = '';

                var requests = pages.map(function (page) {
                    return new mw.Api().get({
                        action: 'query',
                        prop: 'revisions',
                        rvprop: 'content',
                        titles: page.title,
                        format: 'json'
                    }).then(function (pageData) {
                        var pageId = Object.keys(pageData.query.pages)[0];
                        var content = pageData.query.pages[pageId].revisions[0]['*'];
                        var pageUrl = mw.util.getUrl(page.title);
                        var imgUrl = '';

                        // Try to find a [[File:...]] entry
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);
                        if (fileMatch) {
                            var fileName = fileMatch[1].trim();

                            // Fetch full image URL from MediaWiki API
                            return new mw.Api().get({
                                action: 'query',
                                titles: 'File:' + fileName,
                                prop: 'imageinfo',
                                iiprop: 'url',
                                format: 'json'
                            }).then(function (imageData) {
                                var imagePageId = Object.keys(imageData.query.pages)[0];
                                if (imageData.query.pages[imagePageId].imageinfo) {
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;
                                }

                                // Add the gallery item
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);
                            });
                        } else {
                            // If no image is found, still display the title
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);
                        }
                    });
                });

                Promise.all(requests).then(function () {
                    // Append gallery items after loading them
                    galleryContainer.html('<div class="gallery-container">' + galleryHtml + '</div>');
                });
            });
        }

        function generateGalleryItem(pageUrl, title, imgUrl, category) {
            return `
                <div class="gallery-item ${category}">
                    <a href="${pageUrl}">
                        ${imgUrl ? `<img src="${imgUrl}" alt="${title}">` : `<img src="https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg" alt="No Image Available">`}

                    </a>
                    <div class="gallery-caption">
                        <a href="${pageUrl}">${title}</a>
                    </div>
                </div>
            `;
        }

        loadGallery(category);
        // find filter button corresponding to preselected category and add css class
        $(".filter-btn").each(function () { $(this).data("filter") === category ? $(this).addClass('selected-filter') : null});

        $(".filter-btn").click(function () {
            var selectedCategory = $(this).data("filter");
            loadGallery(selectedCategory);  
            $('.filter-btn.selected-filter').each((i, elem) => $(elem).removeClass('selected-filter'));
            $(this).addClass('selected-filter');
        });
    });
});



function Carousel() {
    let currentIndex = 0;
    let $carouselItems = $(".carousel-item");
    let totalItems = $carouselItems.length;
    
    $carouselItems.hide().eq(currentIndex).show();

    let $prevButton = $('<button class="carousel-prev"> ◀ </button>');
    let $nextButton = $('<button class="carousel-next"> ▶ </button>');
    $('.carousel-container').append($prevButton, $nextButton);

    $nextButton.click(function () {
        currentIndex = (currentIndex + 1) % totalItems;
        updateCarousel();
    });

    $prevButton.click(function () {
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;
        updateCarousel();
    });

    function updateCarousel() {
        $carouselItems.hide().eq(currentIndex).show();
    }
}


// if page is part of a category, insert any corresponding skill badges (individual project pages)
if(document.getElementById("catlinks") != null) {
    document.querySelectorAll("#catlinks li a").forEach((cat) => {
        let query = "#firstHeading";
        if(cat.title.includes("Category:Textiles")) {
            insertImage('File:Textile_badge_small.png', query, "padding-left:.3em;", "Textiles", true);
        } 
        if(cat.title.includes("Category:Crafting")) {
            insertImage('File:Crafting_badge_small.png', query, "padding-left:.3em;", "Crafting", true);
        }
        if(cat.title.includes("Category:Airbrushing")) {
            insertImage('File:Airbrushing_badge_small.png', query, "padding-left:.3em;", "Airbrushing", true);
        }
        if(cat.title.includes("Category:Button Pressing")) {
            insertImage('File:Button_badge_small.png', query, "padding-left:.3em;", "Button%20Pressing", true);
        } 
        if(cat.title.includes("Category:Cassette Making")) {
            insertImage('File:Cassette_badge_small.png', query, "padding-left:.3em;", "Cassette%20Making", true);
        } 
        if(cat.title.includes("Category:Graphic Design")) {
            insertImage('File:Graphic_badge_small.png', query, "padding-left:.3em;", "Graphic%20Design", true);
        } 
        if(cat.title.includes("Category:Hand Sewing")) {
            insertImage('File:Handsewing_badge_small.png', query, "padding-left:.3em;", "Hand%20Sewing", true);
        } 
        if(cat.title.includes("Category:Laser Cutting")) {
            insertImage('File:Laser_badge_small.png', query, "padding-left:.3em;", "Laser%20Cutting", true);
        } 
        if(cat.title.includes("Category:Machining")) {
            insertImage('File:Machining_badge_small.png', query, "padding-left:.3em;", "Machining", true);
        } 
        if(cat.title.includes("Category:3D Modeling")) {
            insertImage('File:Modeling_badge_small.png', query, "padding-left:.3em;", "3D%20Modeling", true);
        } 
        if(cat.title.includes("Category:3D Printing")) {
            insertImage('File:Printing_badge_small.png', query, "padding-left:.3em;", "3D%20Printing", true);
        } 
        if(cat.title.includes("Category:Programming")) {
            insertImage('File:Programming_badge_small.png', query, "padding-left:.3em;", "Programming", true);
        } 
        if(cat.title.includes("Category:Soldering")) {
            insertImage('File:Soldering_badge_small.png', query, "padding-left:.3em;", "Soldering", true);
        } 
        if(cat.title.includes("Category:Technical Design")) {
            insertImage('File:Technical_badge_small.png', query, "padding-left:.3em;", "Technical%20Design", true);
        } 
        if(cat.title.includes("Category:Welding")) {
            insertImage('File:Welding_badge_small.png', query, "padding-left:.3em;", "Welding", true);
        } 
        if(cat.title.includes("Category:Woodworking")) {
            insertImage('File:Woodworking_badge_small.png', query, "padding-left:.3em;", "Woodworking", true);
        } 
    })
}

// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])
// if asLinkedSkillBadge is true, styles as skill badge
function insertImage(image, selector, style="", linkFilter="", asLinkedSkillBadge=false) {
    $.getJSON(
        mw.util.wikiScript( 'api' ), {
            format: 'json',
            action: 'query',
            titles: image,
            prop: 'imageinfo',
            iiprop: 'url'
        },
        function( obj ) {
            let pages = obj.query.pages;
            let result1 = pages[Object.keys(pages)[0]];
            let url = result1.imageinfo[0].url;
            let alt = result1.title; // set alt text to image title
            let urlSub = url.substring(url.indexOf("/wiki"));
            if(asLinkedSkillBadge) {
                document.querySelector(selector).innerHTML += '<a href="./GALLERY?title=GALLERY&filter='+linkFilter+'"><img class="skill-badge-img" src="'+urlSub+'" alt="'+alt+'" style="'+style+'"></a>';
            }
            else {
                document.querySelector(selector).innerHTML += '<img src="'+urlSub+'" alt="'+alt+'" style="'+style+'">';
            }
        }
    );
}