<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://makerspace.cc/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=TCGmaker</id>
	<title>Makerpedia - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://makerspace.cc/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=TCGmaker"/>
	<link rel="alternate" type="text/html" href="https://makerspace.cc/Special:Contributions/TCGmaker"/>
	<updated>2026-05-06T16:32:41Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.7</generator>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9051</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9051"/>
		<updated>2025-03-10T18:06:29Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button in bottom right corner -- styled in Common.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Project Tutorials Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select filter to value of &#039;filter&#039; parameter in url (eg www.wikititle/pagetitle?filter=Textiles)&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category Projects&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        /* add buttons to filter by category on Project Tutorials page&lt;br /&gt;
           html text displayed can be anything, but value of data-filter should be the same format as value passed in url parameters and entry in categories &lt;br /&gt;
           dictionary in loadGallery() function */&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        // use insertImage function to query api and insert given image at given id, with given style (adds icons to Project Tutorials filter buttons)&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
&lt;br /&gt;
            // map larger umbrella categories to the skill badge categories they include&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            // insert projects corresponding to each skill under broader category filter selected&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
&lt;br /&gt;
        // find filter button corresponding to selected category and add css class &#039;selected-filter&#039;&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        // when filter button is clicked, load projects for that category, deselect current filtered button, and select newly clicked filter button&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class &#039;selected-filter&#039;&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        // when filter button is clicked, load tools for that category, deselect current filtered button, and select newly clicked filter button&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; &amp;amp;#128896; &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; &amp;amp;#128898; &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        autoSlide = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
}); &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Individual Project pages (and potentially tools): if page is part of a category, insert any corresponding skill badges at top of page&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// uses api to insert image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// optional style parameter gets applied&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge (image wrapped in &amp;lt;a&amp;gt; link)&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/&amp;quot;)); // get just later part of url as link to image (after first slash)&lt;br /&gt;
            if(asLinkedSkillBadge) { // insert as linked skill badge (image wrapped in &amp;lt;a&amp;gt; with link to prefiltered Project Tutorials page)&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else { // insert as regular image&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
/* Styled in common.css*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead. Direct to login if not logged in.&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;amp;returnto=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else if (document.querySelector(&amp;quot;#ca-unfavorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;amp;returnto=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    // occurs if the user is not logged in:&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(&amp;quot;#pt-login a&amp;quot;).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9048</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9048"/>
		<updated>2025-03-10T18:04:29Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: small comment additions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button in bottom right corner -- styled in Common.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Project Tutorials Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select filter to value of &#039;filter&#039; parameter in url (eg www.wikititle/pagetitle?filter=Textiles)&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category Projects&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        /* add buttons to filter by category on Project Tutorials page&lt;br /&gt;
           html text displayed can be anything, but value of data-filter should be the same format as value passed in url parameters and entry in categories &lt;br /&gt;
           dictionary in loadGallery() function */&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        // use insertImage function to query api and insert given image at given id, with given style (adds icons to Project Tutorials filter buttons)&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
&lt;br /&gt;
            // map larger umbrella categories to the skill badge categories they include&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            // insert projects corresponding to each skill under broader category filter selected&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
&lt;br /&gt;
        // find filter button corresponding to selected category and add css class &#039;selected-filter&#039;&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        // when filter button is clicked, load projects for that category, deselect current filtered button, and select newly clicked filter button&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class &#039;selected-filter&#039;&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        // when filter button is clicked, load tools for that category, deselect current filtered button, and select newly clicked filter button&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; &amp;amp;#128896; &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; &amp;amp;#128898; &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        autoSlide = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
}); &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Individual Project pages (and potentially tools): if page is part of a category, insert any corresponding skill badges at top of page&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// uses api to insert image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// optional style parameter gets applied&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge (image wrapped in &amp;lt;a&amp;gt; link)&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/&amp;quot;)); // get just later part of url as link to image (after first slash)&lt;br /&gt;
            if(asLinkedSkillBadge) { // insert as linked skill badge (image wrapped in &amp;lt;a&amp;gt; with link to prefiltered Project Tutorials page)&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else { // insert as regular image&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead. Direct to login if not logged in.&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;amp;returnto=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else if (document.querySelector(&amp;quot;#ca-unfavorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;amp;returnto=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    // occurs if the user is not logged in:&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(&amp;quot;#pt-login a&amp;quot;).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9024</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9024"/>
		<updated>2025-03-07T20:21:31Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead. Direct to login if not logged in.&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;amp;returnto=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else if (document.querySelector(&amp;quot;#ca-unfavorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;amp;returnto=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(&amp;quot;#pt-login a&amp;quot;).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9023</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=9023"/>
		<updated>2025-03-07T20:17:44Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead. Direct to login if not logged in.&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else if (document.querySelector(&amp;quot;#ca-unfavorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(&amp;quot;#pt-login a&amp;quot;).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;LOGIN&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Screenprinting&amp;diff=9022</id>
		<title>Screenprinting</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Screenprinting&amp;diff=9022"/>
		<updated>2025-03-07T19:49:11Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: Reverted edits by Ajhg (talk) to last revision by GiseleN&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Screen Printing Frame.jpg|thumb]]&lt;br /&gt;
This is an experimental design for reusable screenprinting screens. The basic idea is that a [https://a360.co/3UtvIYt scoop coater] is used to cover stainless steel screen with acrylic paint, which is used as a resist. A [[:Category:Laser Engravers|laser engraver]] is then used to remove the resist where necessary. After printing, the scoop coater is again used to fill the areas where resist was removed.&lt;br /&gt;
&lt;br /&gt;
{{#widget:FusionViewer|fusionLink=https://carleton40.autodesk360.com/shares/public/SH30dd5QT870c25f12fcb35e89e7e0040312}}&lt;br /&gt;
&lt;br /&gt;
==== Bill of Materials: ====&lt;br /&gt;
&lt;br /&gt;
* [https://www.amazon.com/dp/B09KRS5F7T Stainless Steel Mesh]&lt;br /&gt;
* [https://www.amazon.com/gp/product/B08KQCHTZL 2020 Aluminum Extrusion]&lt;br /&gt;
* [https://www.amazon.com/gp/product/B0B77YLLT5 Silicone Squeegee]&lt;br /&gt;
* Acrylic Paint (any)&lt;br /&gt;
* [https://www.amazon.com/gp/product/B001038NLY Screen Printing Ink]&lt;br /&gt;
&lt;br /&gt;
=== Safe Operating Procedure: ===&lt;br /&gt;
&lt;br /&gt;
==== Before using: ====&lt;br /&gt;
&lt;br /&gt;
* Ensure that the screen has been properly coated and dried. &lt;br /&gt;
* Check that there is no tearing of the screen near the edges. &lt;br /&gt;
* Engrave your image onto the screen using [100% speed, 100% power] with a [[Universal PLS6.75|PLS6.75 laser engraver]]. &lt;br /&gt;
* Images should be rasterized to 1/2 the density of the screen material; if using a 120 mesh screen, rasterize the image to 60dpi. If using the 300 mesh, rasterize to 150 dpi. Note: 120 mesh is recommended for fabric screen printing.&lt;br /&gt;
&lt;br /&gt;
==== While using: ====&lt;br /&gt;
&lt;br /&gt;
* Print quickly, to prevent ink from drying in the screen. &lt;br /&gt;
* Pre-coat the screen with ink, before laying it on the substrate material. &lt;br /&gt;
&lt;br /&gt;
==== After using: ====&lt;br /&gt;
&lt;br /&gt;
* Wipe excess ink from inside of screen.&lt;br /&gt;
* Wash remaining paint in appropriate sink. &lt;br /&gt;
* Hang to dry, and let managers know that the screen is ready to be recoated.&lt;br /&gt;
[[Category:Printmaking]]&lt;br /&gt;
[[Category:Tools]]&lt;br /&gt;
[[Category:Textiles]]&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Medik.css&amp;diff=9020</id>
		<title>MediaWiki:Medik.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Medik.css&amp;diff=9020"/>
		<updated>2025-03-07T19:48:48Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: Reverted edits by Ajhg (talk) to last revision by Chetitac&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the Medik skin */&lt;br /&gt;
&lt;br /&gt;
/* css from Aaron */&lt;br /&gt;
body {&lt;br /&gt;
  height: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
h2, h1, h3 {&lt;br /&gt;
    font-family: Arial, Helvetica, sans-serif;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*[show*=&#039;vid&#039;] img, [show*=&#039;none&#039;] img {&lt;br /&gt;
  display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
[show*=&#039;img&#039;] .videoBox, [show*=&#039;none&#039;] .videoBox {&lt;br /&gt;
  display: none;&lt;br /&gt;
}*/&lt;br /&gt;
&lt;br /&gt;
/* the following affects project tutorial pages: */&lt;br /&gt;
&lt;br /&gt;
.sxs img {&lt;br /&gt;
  image-orientation: from-image;&lt;br /&gt;
  float: left;&lt;br /&gt;
  margin-right: 2em;&lt;br /&gt;
  width: min(calc(95vmin - 6em), 40vmax);&lt;br /&gt;
  height: auto;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sxs {&lt;br /&gt;
  counter-reset: section;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sxs h3::before {&lt;br /&gt;
  counter-increment: section;&lt;br /&gt;
  content: &amp;quot;Step &amp;quot; counter(section) &amp;quot;: &amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sxs div {&lt;br /&gt;
  overflow: auto;&lt;br /&gt;
  margin-bottom: 1em;&lt;br /&gt;
  padding: 2em;&lt;br /&gt;
  padding-top: 0;&lt;br /&gt;
  border: 1px #ccc solid;&lt;br /&gt;
  box-shadow: 2px 2px 3px rgba(0,0,0,.25);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sxs div h3{&lt;br /&gt;
  margin-top: .5em;&lt;br /&gt;
  border-bottom: .5px solid #ccc;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sxs div:nth-child(odd) img {&lt;br /&gt;
  float: right;&lt;br /&gt;
  margin-left: 2em;&lt;br /&gt;
  margin-right: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sxs div:nth-child(odd) {&lt;br /&gt;
  border-radius: .5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.sxs div:nth-child(even) {&lt;br /&gt;
  background-color: #eee;&lt;br /&gt;
  border-radius: .5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.overview {&lt;br /&gt;
  background-color: rgba(0,70,200,.2);&lt;br /&gt;
  border-radius: 1em; &lt;br /&gt;
  padding-left: 1em; &lt;br /&gt;
  padding-right: 1em; &lt;br /&gt;
  padding-top: .01em;&lt;br /&gt;
  padding-bottom: .75em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* our new css */&lt;br /&gt;
&lt;br /&gt;
#mw-navbar {&lt;br /&gt;
  align-items: start;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-navigation {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  padding: 0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-navigation-label {&lt;br /&gt;
  visibility: hidden;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#mw-navigation a:not(.disabled), #mw-navigation a:not(.disabled):hover {&lt;br /&gt;
  color: white;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (min-width: 768px) {&lt;br /&gt;
  #p-banner {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  #p-banner .mw-wiki-logo {&lt;br /&gt;
    width: 3.5em;&lt;br /&gt;
    height: 3.5em;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  .mw-desktop-sitename {&lt;br /&gt;
    font-size: 2em;&lt;br /&gt;
    padding-left: .75em;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  #mw-navigation {&lt;br /&gt;
    max-width: 7em;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  #site-navigation {&lt;br /&gt;
    width: 100%;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  #mw-navigation a {&lt;br /&gt;
    padding: 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  #site-navigation li a::before {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    display: block;&lt;br /&gt;
    content: &#039;&#039;;&lt;br /&gt;
    background-size: 2em;&lt;br /&gt;
    height: 2em;&lt;br /&gt;
    width: 2em;&lt;br /&gt;
    margin: auto;&lt;br /&gt;
    margin-top: 1em;&lt;br /&gt;
    filter: invert(1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#site-navigation li a:hover {&lt;br /&gt;
  filter: invert(.25);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#site-navigation li {&lt;br /&gt;
  text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#n-HOME a::before, #n-HOME-1 a::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/home.svg&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#n-SPACES a::before, #n-SPACES-1 a::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/door.svg&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#n-TOOLS a::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/tools.svg&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#n-PROJECT-TUTORIALS a::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/gallery.svg&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#n-SUBMIT-PROJECT a::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/howTo.svg&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* cece added this, modified by sameer */&lt;br /&gt;
&lt;br /&gt;
.carousel-heading {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    font-size: 20px;&lt;br /&gt;
    margin-bottom: 5px;&lt;br /&gt;
    margin-top: 23px;&lt;br /&gt;
    color: #003366;&lt;br /&gt;
}&lt;br /&gt;
.carousel-container {&lt;br /&gt;
  position: relative;&lt;br /&gt;
  display: block;&lt;br /&gt;
  width: 75%; &lt;br /&gt;
  margin: 0 auto;&lt;br /&gt;
  overflow: hidden;&lt;br /&gt;
  background-color: #d3ddf0;&lt;br /&gt;
  margin-bottom: 20px;&lt;br /&gt;
  box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.5); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.carousel-item {&lt;br /&gt;
  display: flex;&lt;br /&gt;
  flex-direction: column;&lt;br /&gt;
  justify-content: center;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  width: 100%;&lt;br /&gt;
  height: 400px; &lt;br /&gt;
  box-sizing: border-box;&lt;br /&gt;
  text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.carousel-title {&lt;br /&gt;
  margin-top: 10px;&lt;br /&gt;
  font-size: 18px;&lt;br /&gt;
  color: #333;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.carousel-item img {&lt;br /&gt;
  width: 400px; /* Make the image take the full width of the carousel item */&lt;br /&gt;
  height: 300px; /* Control the height to fit within the container */&lt;br /&gt;
  max-width: 400px;&lt;br /&gt;
  max-height: 300px;&lt;br /&gt;
  object-fit: cover; /* Ensures the image covers the space without distortion */&lt;br /&gt;
  transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;&lt;br /&gt;
  box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.3); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.carousel-prev, .carousel-next {&lt;br /&gt;
  position: absolute;&lt;br /&gt;
  top: 50%;&lt;br /&gt;
  transform: translateY(-50%);&lt;br /&gt;
  background-color: #003366;&lt;br /&gt;
  color: white;&lt;br /&gt;
  border: none;&lt;br /&gt;
  padding: 10px 15px;&lt;br /&gt;
  font-size: 20px;&lt;br /&gt;
  cursor: pointer;&lt;br /&gt;
  border-radius: 50%;&lt;br /&gt;
  width: 50px;&lt;br /&gt;
  height: 50px;&lt;br /&gt;
  display: flex;&lt;br /&gt;
  align-items: center;&lt;br /&gt;
  justify-content: center;&lt;br /&gt;
  z-index: 20;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.carousel-next {&lt;br /&gt;
  right: 5px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.carousel-prev {&lt;br /&gt;
  left: 5px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.carousel-prev:hover, .carousel-next:hover {&lt;br /&gt;
  background-color: #002244;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
button.filter-btn {&lt;br /&gt;
    border-radius: .5em;&lt;br /&gt;
    margin: .2em;&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    height: 2.2em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
button.filter-btn:hover, button.filter-btn.selected-filter {&lt;br /&gt;
    background-color: var(--medik);&lt;br /&gt;
    color: white;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
button.filter-btn:hover img, button.filter-btn.selected-filter img {&lt;br /&gt;
    filter: brightness(0) invert(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#category-filter {&lt;br /&gt;
  margin-bottom: 2em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
img.skill-badge-img, .skill-badge-img img {&lt;br /&gt;
  width: 55px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.skill-badge-img:hover, .skill-badge-img:hover img {&lt;br /&gt;
  width: 50px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) {&lt;br /&gt;
    .pc-map { display: none !important; }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media (min-width: 769px) {&lt;br /&gt;
    .mobile-map { display: none !important; }&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Make_your_own_deodorant_and_toothpaste!_(Project_0010)&amp;diff=9004</id>
		<title>Make your own deodorant and toothpaste! (Project 0010)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Make_your_own_deodorant_and_toothpaste!_(Project_0010)&amp;diff=9004"/>
		<updated>2025-03-03T13:06:13Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Charlotte Nahley&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:Make your own deodorant and toothpaste!}}&lt;br /&gt;
[[Category:Projects|Make your own deodorant and toothpaste!]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;overview&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Overview ==&lt;br /&gt;
&lt;br /&gt;
The creation of a program at the makerspace for students to create their own deodorant and toothpaste to encourage sustainability and creativity as well as to help students cut costs.&lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=null|img2=null|img3=null|img4=null|img5=null|num=2}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tools and Materials ==&lt;br /&gt;
* I found this recipe in this video - https://youtu.be/0bXofKySG4A (Ashley&#039;s Conscious Life&lt;br /&gt;
* Published on Feb 24, 2013) but I have some other videos I found as well. &lt;br /&gt;
* &lt;br /&gt;
* Recipe: “Homemade Deodorant”&lt;br /&gt;
* Ingredients:&lt;br /&gt;
* ¼ cup baking soda&lt;br /&gt;
* ¼ coconut oil &lt;br /&gt;
* ¼ cup arrowroot starch/flour &lt;br /&gt;
* &lt;br /&gt;
* https://trashisfortossers.com/my-zero-waste-homemade-toothpaste-recipe/&lt;br /&gt;
* Zero Waste Toothpaste&lt;br /&gt;
* 2 tablespoons of organic coconut oil&lt;br /&gt;
* 1 tablespoon baking soda&lt;br /&gt;
* 15-20 essential oil&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;files&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Files==&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;sxs&#039;&amp;gt;&lt;br /&gt;
== Step-by-Step Instructions ==&lt;br /&gt;
&lt;br /&gt;
{{#widget:ProjectStep|inst=I found this recipe in this video - https://youtu.be/0bXofKySG4A (Ashley&#039;s Conscious Life&lt;br /&gt;
Published on Feb 24, 2013) but I have some other videos I found as well. &lt;br /&gt;
&lt;br /&gt;
Recipe: “Homemade Deodorant”&lt;br /&gt;
Ingredients:&lt;br /&gt;
¼ cup baking soda&lt;br /&gt;
¼ coconut oil &lt;br /&gt;
¼ cup arrowroot starch/flour &lt;br /&gt;
&lt;br /&gt;
**If you don&#039;t have arrowroot starch, you can use corn starch instead (Note: I have not tested this recipe with cornstarch but it is what the original recipe said.)&lt;br /&gt;
Combine ingredients and store in a sealed jar/container. Apply a small amount daily. Lasts 3-4 weeks. – You have to mix it for a while until it becomes a paste (depending on the temperature of the room)&lt;br /&gt;
Another note: You can add shea butter to make it softer for people with more sensitive skin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
https://trashisfortossers.com/my-zero-waste-homemade-toothpaste-recipe/&lt;br /&gt;
Zero Waste Toothpaste&lt;br /&gt;
2 tablespoons of organic coconut oil&lt;br /&gt;
1 tablespoon baking soda&lt;br /&gt;
15-20 essential oil&lt;br /&gt;
Mix&lt;br /&gt;
&lt;br /&gt;
And when you are done, just fill up a jar with the mixture (for both the toothpaste and deodorant)&lt;br /&gt;
|show=none|src=none}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=AM_radio_transmitter_(Project_0025)&amp;diff=9003</id>
		<title>AM radio transmitter (Project 0025)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=AM_radio_transmitter_(Project_0025)&amp;diff=9003"/>
		<updated>2025-03-03T13:04:45Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Lydia Fick&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:AM radio transmitter}}&lt;br /&gt;
[[Category:Projects|AM radio transmitter]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;overview&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Overview ==&lt;br /&gt;
&lt;br /&gt;
In the worlds of radio and electronics, AM stands for amplitude modulation. For AM transmission of a signal, a carrier wave at a known, constant frequency is modulated by signal wave (which itself is an analog electronic representation of a sound wave), changing the amplitude of the carrier wave. This modulated wave is then sent through an antenna, so the signal can get picked up by nearby AM radio receivers. This guide will allow you to construct your own low-power AM transmitter, following FCC guidelines for hobby radio transmission. &lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://drive.google.com/thumbnail?id=18Ve0kGdtwokullwMBuWOMcXTrktC_dyH&amp;amp;sz=w1000|img2=null|img3=null|img4=null|img5=null|num=2}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tools and Materials ==&lt;br /&gt;
* *TLE2142CP op-amp&lt;br /&gt;
* *Breadboard-pinned standard headphone jack port&lt;br /&gt;
* Audio cable with standard headphone jack plugs on both ends&lt;br /&gt;
* 1kΩ resistor&lt;br /&gt;
* 15kΩ resistor&lt;br /&gt;
* 3x 10kΩ resistors&lt;br /&gt;
* 2x 100 kΩ resistor&lt;br /&gt;
* 2x 680kΩ resistors&lt;br /&gt;
* 2x 100 pF capacitors&lt;br /&gt;
* 1 nF capacitor&lt;br /&gt;
* 1 µF capacitor&lt;br /&gt;
* 100kΩ trimpot&lt;br /&gt;
* 10kΩ trimpot&lt;br /&gt;
* 2-3m long piece of solid core insulated wire&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;files&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Files==&lt;br /&gt;
* [https://drive.google.com/thumbnail?id=18Ve0kGdtwokullwMBuWOMcXTrktC_dyH AMtransmitter-block-diagram - Lydia Fick.png]&lt;br /&gt;
* [https://drive.google.com/thumbnail?id=1mQjuYlSX1QGtmtutK8vkBI4xGwLMSBpJ AMtransmitter-circuit-diagram - Lydia Fick.png]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;sxs&#039;&amp;gt;&lt;br /&gt;
== Step-by-Step Instructions ==&lt;br /&gt;
&lt;br /&gt;
{{#widget:ProjectStep|inst=Begin by constructing the oscillator portion of the circuit, outlined in blue on the circuit diagram. Once it is built, you can monitor the output V_carrier on an oscilloscope. You will likely have to zoom in pretty far on the time-axis of the oscilloscope -- AM radios expect carrier waves with a frequency of approximately 600-1600 kHz. Confirm that as you turn your potentiometer, the oscillator outputs primarily frequencies within this range. If this is not the case, double check your resistor and capacitor values. &lt;br /&gt;
	&lt;br /&gt;
An op-amp is the perfect candidate for generating a carrier wave, and is commonly implemented for use as an oscillator. This circuit has both positive and negative feedback elements, so the op-amp will always be operating such that it hits the rails, meaning it will always be outputting either +12V or 0V. If the non-inverting input V+ is greater than the inverting input V-, it will output +12V. Otherwise, it will output 0V. Since the non-inverting input (V+) is biased at a fraction of +Vcc (where R1 and R2 form a voltage divider), Vout will begin positive, so current will flow from the output to ground, charging the capacitor. As the capacitor charges, the voltage drop over it will increase, meaning the voltage to the inverting input, which is in parallel with the capacitor, will also increase. Eventually, the capacitor’s voltage will exceed that of the biasing at the non-inverting input, causing the op-amp to switch to outputting at the lower rail, or 0V. The capacitor will then begin to discharge until the threshold voltage is hit again, creating an oscillating signal. C4 and R11 are included for robustness, specifically to help prevent back-current from signals picked up by the antenna.|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Next, construct the modulator portion of the circuit, outlined in purple on the circuit diagram. For now, use a function generator to create a signal to act as “V_audio” and send it to the inverting input. Generate a signal within the audible frequency range, 20Hz-20kHz. Monitor the output of the frequency generator and of the modulator on the oscilloscope. The oscilloscope should look something like the attached image, where the bottom is the output of the function generator, and the top is the modulated signal. Notice how the modulated signal is a high frequency wave whose amplitudes over time resemble the shape of the frequency generator wave. &lt;br /&gt;
&lt;br /&gt;
This circuit involves an op-amp with negative feedback, so we know that the op-amp will adjust to try to make the difference between its inputs be 0. For that to happen, V_modulated must have a form such that when it is combined with V_carrier at the inverting input, it recovers the audio signal. This occurs when V_modulated has the form of the inverse of V_carrier, modulated by V_audio. |src=1tLypL8jM6xu_9RSamgd0ONdQTLMTjjws|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Next, construct the signal processor portion of the circuit, outlined in red on the circuit diagram, and attach it to the non-inverting input of the modulator op-amp. The potentiometer allows the strength of the audio signal relative to the carrier signal to be adjusted. This in turn will allow the modulated signal to contain more or less of the audio signal which can lead to some interesting sounds. C2 and R8 are included for robustness, specifically to help prevent back-current from signals picked up by the antenna. Monitor the audio signal and the modulated signal to ensure that they continue to line up as expected. An example is attached where the top waveform is the audio, and the bottom is the modulated signal.|src=14KwyCiLGS6FgcWEF8lm5BYJtSugGxH19|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Next, a power amplifier can be attached to the output of the modulator before putting the signal through the antenna in order to increase the range of the transmitter. This requires a high-frequency NPN transistor, which was not available in the makerspace. If you want to attempt this, I recommend looking into Class A or Class AB power amplifiers since while those are not the most efficient, they have the least warping of the signal inherent to their design. However, the transmitter will function fine without this component, so it is alright to skip this step. |show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Connect the output of the modulator to your antenna through C3. The capacitor is there to help prevent back current from any signals picked up by the antenna. All together, your circuit should look something like the attached image, where the long yellow wire sticking out leads into the antenna. Bring a radio receiver close to the antenna and tune it to the carrier frequency (which you can measure using your oscilloscope). Plug the audio cable into your MP3 player of choice (I used my laptop) and play a sound through it. You may need to adjust your carrier wave frequency slightly using the oscillator potentiometer, but you should be able to hit a point where you hear the audio you are playing through the radio. Feel free to try playing around with the modulator potentiometer and see how that impacts the sound. Also note that high-frequency analog electronics can be very susceptible to environmental changes, so for a more robust design you may want to contain your circuit in a metal shielding box. Happy transmitting!|src=1rw8iZQcXc6G2yvBAZ7bFJbCkWyT41-_y|show=img}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=0017-Crescent_flower_earrings&amp;diff=9002</id>
		<title>0017-Crescent flower earrings</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=0017-Crescent_flower_earrings&amp;diff=9002"/>
		<updated>2025-03-03T13:03:03Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Lydia&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:Crescent flower earrings}}&lt;br /&gt;
[[Category:Projects|Crescent flower earrings]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;overview&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Overview ==&lt;br /&gt;
&lt;br /&gt;
I lined a resin mold with wire then set pressed flowers and metal leaf within that same mold with resin. After it cured, I attached earring fittings. &lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://drive.google.com/thumbnail?id=1AGwwx6FinGVskWb8s1r5DeYNaWHJolQu&amp;amp;sz=w1000|img2=null|img3=null|img4=null|img5=null|num=2}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tools and Materials ==&lt;br /&gt;
* &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;files&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Files==&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;sxs&#039;&amp;gt;&lt;br /&gt;
== Step-by-Step Instructions ==&lt;br /&gt;
&lt;br /&gt;
{{#widget:ProjectStep|inst=Line the molds with craft wire |show=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Mix the resin using the instructions on the box|show=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Pour a layer of resin in to the mold and allow to sit for a few minutes |show=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Place the pressed flowers and copper leaf in to the molds |show=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Pour more resin on top to fill the mold. Allow to cure over the weekend. |show=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Take out of the molds, and use jump  rings to connect them to earring hooks|show=none}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:Crafting]]&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8930</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8930"/>
		<updated>2025-02-27T22:35:34Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8929</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8929"/>
		<updated>2025-02-27T22:34:03Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
/* if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) */&lt;br /&gt;
if ($(&amp;quot;[title=&#039;Category:Projects&#039;]&amp;quot;) !== null){&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8928</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8928"/>
		<updated>2025-02-27T22:31:59Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
/* if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) */&lt;br /&gt;
if ($(&amp;quot;[title=Category:Projects]&amp;quot;) !== null){&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8927</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8927"/>
		<updated>2025-02-27T22:18:23Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
/* if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) */&lt;br /&gt;
if (document.getElementById(&amp;quot;catlinks&amp;quot;).includes(&amp;quot;Category:Projects&amp;quot;)){&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8926</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8926"/>
		<updated>2025-02-27T22:13:30Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
/* if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) */&lt;br /&gt;
if (document.getElementById(&amp;quot;catlinks&amp;quot;) != null){&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8925</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8925"/>
		<updated>2025-02-27T22:10:53Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
/* if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) */&lt;br /&gt;
if (document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).title.includes(&amp;quot;Category:Projects&amp;quot;)){&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8924</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8924"/>
		<updated>2025-02-27T22:05:26Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8923</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8923"/>
		<updated>2025-02-27T22:03:38Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/likednt.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  float: right;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/liked.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  float: right;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8922</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8922"/>
		<updated>2025-02-27T21:58:53Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/likednt.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  justify-self: right;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/liked.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  justify-self: right;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8921</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8921"/>
		<updated>2025-02-27T21:54:08Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;firstHeading&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8920</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8920"/>
		<updated>2025-02-27T21:44:34Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8919</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8919"/>
		<updated>2025-02-27T21:42:59Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/likednt.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/liked.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8918</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8918"/>
		<updated>2025-02-27T21:40:35Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/likednt.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/liked.png&amp;quot;);&lt;br /&gt;
  background-size: contain;&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8917</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8917"/>
		<updated>2025-02-27T21:37:43Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/likednt.png&amp;quot;);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/liked.png&amp;quot;);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8916</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8916"/>
		<updated>2025-02-27T20:24:52Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;p&amp;gt;LIKE&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;p&amp;gt;UNLIKE&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8915</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8915"/>
		<updated>2025-02-27T20:15:38Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages that aren&#039;t sidebar pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0 &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Spaces_New&#039; &amp;amp;&amp;amp; mw.config.get(&#039;wgPageName&#039;) !== &#039;Home_New&#039;) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;p&amp;gt;LIKE&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;p&amp;gt;DELIKE&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8914</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8914"/>
		<updated>2025-02-27T20:07:21Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 10px;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8913</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8913"/>
		<updated>2025-02-27T20:03:40Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 0;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 100px;&lt;br /&gt;
  right: 0;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8912</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8912"/>
		<updated>2025-02-27T19:55:54Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 0;&lt;br /&gt;
  right: 0;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 0;&lt;br /&gt;
  right: 0;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8911</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8911"/>
		<updated>2025-02-27T19:52:54Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 0;&lt;br /&gt;
  right: 0;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  top: 0;&lt;br /&gt;
  right: 0;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8910</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8910"/>
		<updated>2025-02-27T19:46:10Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;p&amp;gt;LIKE&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;p&amp;gt;HATE&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Instrument Shop Tools&amp;quot;&amp;gt;Instrument Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Repair Lair Tools&amp;quot;&amp;gt;Repair Lair Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8909</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8909"/>
		<updated>2025-02-27T19:44:24Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  right: 1vw;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  right: 1vw;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8907</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8907"/>
		<updated>2025-02-27T19:39:32Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8906</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8906"/>
		<updated>2025-02-27T19:38:19Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 1vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 1vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8855</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8855"/>
		<updated>2025-02-27T03:54:58Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
&lt;br /&gt;
.cautionBox {&lt;br /&gt;
  border: 1px solid #ddcc55;&lt;br /&gt;
  background-color: #ffedaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.warningBox {&lt;br /&gt;
  border: 1px solid #dd5555;&lt;br /&gt;
  background-color: #ffaaaa;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.introBox {&lt;br /&gt;
  border: 2px solid #f505f5;&lt;br /&gt;
  background-color: #c2cbde;&lt;br /&gt;
  border-radius: .5vmin;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
  padding-top: .25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ytplayer {&lt;br /&gt;
  max-width: 90vw;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button {&lt;br /&gt;
  position: fixed;&lt;br /&gt;
  bottom: 2vh;&lt;br /&gt;
  right: 2vh;&lt;br /&gt;
  z-index: 100;&lt;br /&gt;
  background-color: var(--medik);&lt;br /&gt;
  color: white;&lt;br /&gt;
  border-radius: 5em;&lt;br /&gt;
  padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p {&lt;br /&gt;
  margin: 0em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.big-edit-button p::before {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  background-repeat: no-repeat;&lt;br /&gt;
  content: &#039;&#039;;&lt;br /&gt;
  display: inline;&lt;br /&gt;
  background-size: 1.75em;&lt;br /&gt;
  padding: .25em 1em;&lt;br /&gt;
  filter: invert(100%) sepia(100%) saturate(2%) hue-rotate(141deg) brightness(103%) contrast(101%);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.favorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  position: fixed;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.unfavorite {&lt;br /&gt;
  background-image: url(&amp;quot;images/icons/edit.svg&amp;quot;);&lt;br /&gt;
  position: fixed;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-container {&lt;br /&gt;
    column-count: 4; &lt;br /&gt;
    column-gap: 10px; &lt;br /&gt;
    width: 100%;&lt;br /&gt;
    max-width: 1200px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    margin-bottom: 10px; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%; &lt;br /&gt;
    border-radius: 8px;&lt;br /&gt;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media (max-width: 768px) { /* Adjust for mobile */&lt;br /&gt;
    .gallery-container {&lt;br /&gt;
        grid-template-columns: repeat(3, 1fr); &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8845</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8845"/>
		<updated>2025-02-27T03:32:33Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: finishing up like button. just need to style it&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;button class=&amp;quot;favorite&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;button class=&amp;quot;unfavorite&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8844</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8844"/>
		<updated>2025-02-27T03:25:29Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;p&amp;gt;Like&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=unfavorite&amp;gt;&amp;lt;p&amp;gt;UNLike&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8843</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8843"/>
		<updated>2025-02-27T03:24:41Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) {&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    if (document.querySelector(&amp;quot;#ca-favorite&amp;quot;)) {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;p&amp;gt;Like&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;p&amp;gt;UNLike&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8842</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8842"/>
		<updated>2025-02-27T03:18:37Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) {&lt;br /&gt;
    let action = &#039;favorite&#039;;&lt;br /&gt;
    // if page is favorited we should show unfavorite button instead&lt;br /&gt;
    document.querySelector(&amp;quot;#ca-unfavorite&amp;quot;) ? action = &#039;unfavorite&#039;;&lt;br /&gt;
    document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=&#039;+action+&#039;&amp;gt;&amp;lt;p&amp;gt;Like&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8841</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8841"/>
		<updated>2025-02-27T02:20:46Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) {&lt;br /&gt;
    let action = &#039;favorite&#039;;&lt;br /&gt;
    document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=&#039;+action+&#039;&amp;gt;&amp;lt;p&amp;gt;Like&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8835</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8835"/>
		<updated>2025-02-26T20:33:06Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. Only appears on &amp;quot;Main&amp;quot; Namespace pages (should be restricted to content pages like articles).*/&lt;br /&gt;
if (mw.config.get(&#039;wgNamespaceNumber&#039;) == 0) document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;p&amp;gt;Like&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8834</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8834"/>
		<updated>2025-02-26T20:26:02Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. */&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;&amp;lt;p&amp;gt;Like&amp;lt;/p&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8833</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8833"/>
		<updated>2025-02-26T20:07:47Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button -- styled in Medik.css */ &lt;br /&gt;
/* 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 */&lt;br /&gt;
let editLinkQuery = document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;) ? &amp;quot;#ca-ve-edit a&amp;quot; : (document.querySelector(&amp;quot;#ca-edit a&amp;quot;) ? &amp;quot;#ca-edit a&amp;quot; : &amp;quot;#pt-login a&amp;quot;);&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+document.querySelector(editLinkQuery).href+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* like button. */&lt;br /&gt;
document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=/wiki/index.php?title=&#039;+mw.config.get(&#039;wgPageName&#039;)+&#039;&amp;amp;action=favorite&amp;gt;Like&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
/* looks at current url parameters of the form &#039;?param1=value1&amp;amp;param2=value2...&#039; and returns a dictionary of the form {param1: value1, param2: value2, ...} */&lt;br /&gt;
function parseUrlParameters() {&lt;br /&gt;
    let queryStr = window.location.search.substring(1).replaceAll(&amp;quot;%20&amp;quot;, &amp;quot; &amp;quot;); // start string after the question mark and replace &#039;%20&#039; with spaces&lt;br /&gt;
    let queryDict = {};&lt;br /&gt;
    queryStr.split(&amp;quot;&amp;amp;&amp;quot;).forEach(function(query) {&lt;br /&gt;
        let pair = query.split(&amp;quot;=&amp;quot;);&lt;br /&gt;
        queryDict[pair[0]] = pair[1];&lt;br /&gt;
    })&lt;br /&gt;
    return queryDict;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Projects&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;all-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;crafts-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafts&amp;quot;&amp;gt;Crafts&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;design-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Design&amp;quot;&amp;gt;Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;fabrication-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Fabrication&amp;quot;&amp;gt;Fabrication&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;cnc-laser-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;CNC-Laser&amp;quot;&amp;gt;Laser &amp;amp; CNC&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;metalworking-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Metalworking&amp;quot;&amp;gt;Metalworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;button id=&amp;quot;textiles-filter-btn&amp;quot; class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        insertImage(&amp;quot;File:Airbrushing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Button_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Cassette_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Crafting_icon_color.png&amp;quot;, &amp;quot;#crafts-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Graphic_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Handsewing_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Laser_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Machining_icon_color.png&amp;quot;, &amp;quot;#cnc-laser-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Modeling_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Printing_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Programming_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Soldering_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Technical_icon_color.png&amp;quot;, &amp;quot;#design-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Textile_icon_color.png&amp;quot;, &amp;quot;#textiles-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Welding_icon_color.png&amp;quot;, &amp;quot;#metalworking-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
        insertImage(&amp;quot;File:Woodworking_icon_color.png&amp;quot;, &amp;quot;#fabrication-filter-btn&amp;quot;, style=&amp;quot;height:1.5em;padding-left:.4em&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            let pageTitles = [];&lt;br /&gt;
            let categories = {&lt;br /&gt;
                &amp;quot;Projects&amp;quot; : [&amp;quot;Projects&amp;quot;],&lt;br /&gt;
                &amp;quot;Design&amp;quot; : [&amp;quot;Graphic Design&amp;quot;, &amp;quot;3D Modeling&amp;quot;, &amp;quot;Technical Design&amp;quot;, &amp;quot;Programming&amp;quot;],&lt;br /&gt;
                &amp;quot;Textiles&amp;quot; : [&amp;quot;Textiles&amp;quot;, &amp;quot;Hand Sewing&amp;quot;],&lt;br /&gt;
                &amp;quot;Crafts&amp;quot; : [&amp;quot;Crafting&amp;quot;, &amp;quot;Button Pressing&amp;quot;, &amp;quot;Cassette Making&amp;quot;],&lt;br /&gt;
                &amp;quot;Fabrication&amp;quot; : [&amp;quot;Airbrushing&amp;quot;, &amp;quot;3D Printing&amp;quot;, &amp;quot;Woodworking&amp;quot;],&lt;br /&gt;
                &amp;quot;CNC-Laser&amp;quot; : [&amp;quot;Laser Cutting&amp;quot;, &amp;quot;Machining&amp;quot;],&lt;br /&gt;
                &amp;quot;Metalworking&amp;quot; : [&amp;quot;Soldering&amp;quot;, &amp;quot;Welding&amp;quot;]&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
            categories[category].forEach(function(cat) {&lt;br /&gt;
                new mw.Api().get({&lt;br /&gt;
                    action: &#039;query&#039;,&lt;br /&gt;
                    list: &#039;categorymembers&#039;,&lt;br /&gt;
                    cmtitle: &#039;Category:&#039; + cat,&lt;br /&gt;
                    cmlimit: 50,  &lt;br /&gt;
                    format: &#039;json&#039;&lt;br /&gt;
                }).done(function (data) {&lt;br /&gt;
                    var pages = data.query.categorymembers;&lt;br /&gt;
                    var galleryHtml = &#039;&#039;;&lt;br /&gt;
                    var requests = pages.map(function (page) {&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;revisions&#039;,&lt;br /&gt;
                            rvprop: &#039;content&#039;,&lt;br /&gt;
                            titles: page.title,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (pageData) {&lt;br /&gt;
                            var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                            var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                            var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                            // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                            var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                            if (directMatch) {&lt;br /&gt;
                                imgUrl = directMatch[1];&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                            var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                            if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                                var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                                // Fetch full image URL from MediaWiki API&lt;br /&gt;
                                return new mw.Api().get({&lt;br /&gt;
                                    action: &#039;query&#039;,&lt;br /&gt;
                                    titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                    prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                    iiprop: &#039;url&#039;,&lt;br /&gt;
                                    format: &#039;json&#039;&lt;br /&gt;
                                }).then(function (imageData) {&lt;br /&gt;
                                    var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                    if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                        imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                    }&lt;br /&gt;
&lt;br /&gt;
                                &lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                });&lt;br /&gt;
                            } else {&lt;br /&gt;
                                // Add the gallery item if the image was found and is not already being shown&lt;br /&gt;
                                  if(!pageTitles.includes(page.title)) {&lt;br /&gt;
                                    galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                                    pageTitles.push(page.title);&lt;br /&gt;
                                  }&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    $(&#039;.gallery-container&#039;).append(galleryHtml);&lt;br /&gt;
                });&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory); &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        // get url parameters and automatically select appropriate filter&lt;br /&gt;
        let queryDict = parseUrlParameters();&lt;br /&gt;
        var category = queryDict[&#039;filter&#039;] ? queryDict[&#039;filter&#039;] : &amp;quot;Tools&amp;quot;; // If no filter query in url, use default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(category);&lt;br /&gt;
        // find filter button corresponding to preselected category and add css class&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () { $(this).data(&amp;quot;filter&amp;quot;) === category ? $(this).addClass(&#039;selected-filter&#039;) : null});&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
            $(&#039;.filter-btn.selected-filter&#039;).each((i, elem) =&amp;gt; $(elem).removeClass(&#039;selected-filter&#039;));&lt;br /&gt;
            $(this).addClass(&#039;selected-filter&#039;);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;SimpleProjects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\s|}%]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
    &lt;br /&gt;
    function nextSlide() {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function resetInterval() {&lt;br /&gt;
        clearInterval(autoSlide);&lt;br /&gt;
        interval = setInterval(nextSlide, 10000);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let autoSlide = setInterval(nextSlide, 10000); //auto slide every 10 seconds&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        nextSlide();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
        resetInterval();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel () {&lt;br /&gt;
       $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Airbrushing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Airbrushing&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Button Pressing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Cassette_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Cassette Making&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Crafting_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Crafts&amp;quot;, true, &amp;quot;Crafting&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Graphic_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Graphic Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Handsewing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Hand Sewing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Laser_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Laser Cutting&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Machining_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;CNC-Laser&amp;quot;, true, &amp;quot;Machining&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;3D Modeling&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Printing_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;3D Printing&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Programming_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Programming&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Soldering_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Soldering&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical Design&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Design&amp;quot;, true, &amp;quot;Technical Design&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Textile_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Textiles&amp;quot;, true, &amp;quot;Textiles&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Welding_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Metalworking&amp;quot;, true, &amp;quot;Welding&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertImage(&#039;File:Woodworking_badge_small.png&#039;, query, &amp;quot;padding-left:.3em;&amp;quot;, &amp;quot;Fabrication&amp;quot;, true, &amp;quot;Woodworking&amp;quot;);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
// if asLinkedSkillBadge is true, styles as skill badge&lt;br /&gt;
function insertImage(image, selector, style=&amp;quot;&amp;quot;, linkFilter=&amp;quot;&amp;quot;, asLinkedSkillBadge=false, tooltip=image) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            if(asLinkedSkillBadge) {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#039;&amp;quot; title=&amp;quot;&#039;+tooltip+&#039;&amp;quot;&amp;gt;&amp;lt;img class=&amp;quot;skill-badge-img&amp;quot; src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
                document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; style=&amp;quot;&#039;+style+&#039;&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// open any &amp;lt;a&amp;gt; wrapped in &amp;lt;u class=&amp;quot;plainlinks&amp;quot;&amp;gt; in same tab (generally internal links that must be treated as external links in order to give url parameters)&lt;br /&gt;
$(&#039;u.plainlinks a&#039;).each(function() { $(this).attr(&#039;target&#039;, &amp;quot;_self&amp;quot;)});&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=User:TCGmaker&amp;diff=8550</id>
		<title>User:TCGmaker</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=User:TCGmaker&amp;diff=8550"/>
		<updated>2025-02-19T16:29:48Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: Created page with &amp;quot;&amp;lt;favorites/&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;favorites/&amp;gt;&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Building_a_Transistor_Theremin_(Project_0043)&amp;diff=8485</id>
		<title>Building a Transistor Theremin (Project 0043)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Building_a_Transistor_Theremin_(Project_0043)&amp;diff=8485"/>
		<updated>2025-02-17T18:56:05Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: /* Project Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Mia David &amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:Building a Transistor Theremin}}&lt;br /&gt;
[[Category:Projects|Building a Transistor Theremin]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;overview&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Overview ==&lt;br /&gt;
&lt;br /&gt;
This project includes instructions for the construction of a transistor based theremin, a simple electronic musical instrument. The theremin takes a constant DC signal as input and returns a clean sine wave (amplified and sent through a speaker to create a tone) as output; the frequency of the output audio signal is adjusted via a variable capacitor consisting of a control antenna and the performer’s hand. This particular design uses the Colpitts oscillator configuration to generate the oscillating output signal, which makes use of simple components including a bipolar junction transistor, a few capacitors, and an off-the-shelf inductor.&lt;br /&gt;
&lt;br /&gt;
The basic functioning blocks of the theremin include a reference oscillator (which outputs a constant frequency), a pitch oscillator (the frequency of this output signal is controlled by the variable capacitor formed by the player’s hand and the wire), a mixer to combine the two signals, filtering to eliminate unwanted frequencies, amplification of the signal, and finally the loudspeaker.&lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://drive.google.com/thumbnail?id=1r7h1214gnzyWdB_TSr6vYhMRLfE7i75n&amp;amp;sz=w1000|img2=null|img3=null|img4=null|img5=null|num=2}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tools and Materials ==&lt;br /&gt;
* - 4.7 nF capacitors (5)&lt;br /&gt;
* - 0.01 μF capacitors (2)&lt;br /&gt;
* - 680 pF capacitors (2)&lt;br /&gt;
* - 220 pF capacitor (1)&lt;br /&gt;
* - 260 pF capacitor (1)&lt;br /&gt;
* - 15 pF capacitors (2) — these replace the trimmer capacitors C15 and C25 in the schematic&lt;br /&gt;
* - 39 pF capacitors (2)&lt;br /&gt;
* - 100 pF capacitors (2)&lt;br /&gt;
* - 8.2 pF capacitor (1)&lt;br /&gt;
* - 0.22 μF capacitor (1)&lt;br /&gt;
* - 1000 μF capacitor (1)&lt;br /&gt;
* - 100 Ω resistors (2)&lt;br /&gt;
* - 9.2 kΩ resistors (2)&lt;br /&gt;
* - 3.3 kΩ resistors (2)&lt;br /&gt;
* - 390 Ω resistors (2)&lt;br /&gt;
* - 4.7 kΩ resistors (2)&lt;br /&gt;
* - 20 kΩ resistors (6)&lt;br /&gt;
* - 470 kΩ resistors (2)&lt;br /&gt;
* - 2.2 MΩ resistor (1)&lt;br /&gt;
* - 10 kΩ resistor (1)&lt;br /&gt;
* - 2N2222 npn transistors (2)&lt;br /&gt;
* - 1N5711 schottky diodes (1)&lt;br /&gt;
* - LM741 op amp (1)&lt;br /&gt;
* - LM386 low voltage audio power amplifier (1)&lt;br /&gt;
* - 8 Ω speaker&lt;br /&gt;
* - 530 μH inductors (2)&lt;br /&gt;
* - tinned copper wire, 16 AWG (~ 15cm) for pitch antenna&lt;br /&gt;
* - prototype board or breadboard (1)&lt;br /&gt;
* - DC power supply (or built-in power supply if using prototype board)&lt;br /&gt;
* - Oscilloscope&lt;br /&gt;
* - Multimeter for testing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;files&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Files==&lt;br /&gt;
* [https://drive.google.com/open?id=1NJoxoj1AFTFkFcVyzx0dQPT_L9oI4aZ- oscillator-osc14 - Mia David.gif]&lt;br /&gt;
* [https://drive.google.com/open?id=1JF0Lt7IGCvpWuMtZre63kqMT0rv-DQrp oscillator-osc15 - Mia David.gif]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;sxs&#039;&amp;gt;&lt;br /&gt;
== Step-by-Step Instructions ==&lt;br /&gt;
&lt;br /&gt;
{{#widget:ProjectStep|inst=Begin by constructing the circuit for the reference oscillator. Trimmer capacitor C15 can be replaced by a standard capacitor in the specified range (15-60 pF). Once the circuit is constructed and connected to power, use the multimeter to check the voltage at the base of the transistor; this should be at around 1.9 V, which puts the 2N2222 transistor into saturation mode (any voltages between 1.2V-2.0V will work, if the resistors in the voltage divider need to be adjusted). Check the output using the oscilloscope probe at the point specified on the schematic; frequency of the oscillating signal can be calculated using the included formulas, which only require the values of the components in the “tank circuit” (highlighted on the schematic). The values for the components in the tank circuit in the schematic should yield an output signal with a frequency around 536 kHz.|src=17fyZd5EtYffCYVLM-0Aah0Ws7S0e4YHg|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Build the pitch oscillator. For initial testing purposes, I would recommend adding a regular capacitor in place of the pitch antenna to make sure that the circuit behaves as expected; after the rest of the circuit is finished, replace that capacitor with the tinned copper wire which acts as the pitch antenna. The construction of the pitch oscillator should be very similar to the reference oscillator other than the additional capacitor; depending on the capacitor you choose, the output frequency will differ. As with the reference oscillator, I would check the voltage at the base of the transistor to make sure it is in saturation mode.|src=1RtGmIbb2wmPDk7KAwCegRgE2vJquol9O|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Build the mixer. This consists of the schottky diode, a very large resistor, and a capacitor. Note that between the oscillators and the mixer are a couple of resistors and capacitors, which are intended to decouple the oscillators from the mixer. Measure output before C2 using the oscilloscope to confirm you are getting a new frequency.|src=1K3ypZGGYhfCLrb-tNfMrlwIp7B9MDwm7|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Construct the remainder of the circuit. Before adding the speaker, measure the signal at the output of the audio amplifier to confirm it is a clean sine wave. Add the speaker. Depending on the capacitance of the capacitor substituted for the pitch antenna, the frequency of the tone will be different. Assuming that an audio signal is being produced, now replace the substitute capacitor for the wire used for the antenna. Move your hand closer and further from the antenna to observe how the pitch changes. At this point, you can try switching out the capacitors or inductor in the tank circuit for both oscillators to see how the audio output signal changes.|src=1NUwWlgCbj3zP-XraEeV-51uhJVgpVV8o|show=img}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:Programming]]&lt;br /&gt;
[[Category:Technical design]]&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=DIY_Chipmunk_(Project_0004)&amp;diff=8480</id>
		<title>DIY Chipmunk (Project 0004)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=DIY_Chipmunk_(Project_0004)&amp;diff=8480"/>
		<updated>2025-02-17T15:07:13Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Turn a Glove Into A Chipmunk!&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:DIY Chipmunk}}&lt;br /&gt;
[[Category:Projects|DIY Chipmunk]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;overview&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Overview ==&lt;br /&gt;
&lt;br /&gt;
Have you ever wanted to make a little stuffed animal, but never knew how? Well today is your lucky day because this project will show you how to turn any normal glove into a fun little chipmunk (no machine sewing required)!! Created By:(https://www.boredpanda.com/diy-glove-into-chipmunk/?utm_source=google&amp;amp;utm_medium=organic&amp;amp;utm_campaign=organic)&lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://drive.google.com/thumbnail?id=1RnA476qswLwlYP8-IKNdC5f-7fTIy8N2&amp;amp;sz=w1000|img2=https://drive.google.com/thumbnail?id=1kjiY2KKYpR30swaU5s3Rv7dFJmBlh6QP&amp;amp;sz=w1000|img3=null|img4=null|img5=null|num=3}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tools and Materials ==&lt;br /&gt;
* Thread (Yarn optional)&lt;br /&gt;
* Stuffing&lt;br /&gt;
* Buttons&lt;br /&gt;
* Glove&lt;br /&gt;
* Scissors&lt;br /&gt;
* Pen&lt;br /&gt;
* Pipe Cleaners (optional) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;files&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Files==&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;sxs&#039;&amp;gt;&lt;br /&gt;
== Step-by-Step Instructions ==&lt;br /&gt;
&lt;br /&gt;
{{#widget:ProjectStep|inst=Flip the glove inside out and using a pen, draw the diagram. Then pin along the lines and cut, making sure the fabric does not fray. Sew along the white lines, leaving just enough room around the edges to ensure the fabric doesn&#039;t unravel and leave large holes in the seams.   |src=1hmQfDPIU4sHq3H0PrBJtXF8u9PLJt3WU|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Once you&#039;ve sewn all the pieces together, turn them all right-side out. Stuff each piece with stuffing, except for the ears, and make sure you leave a little room at the top of each piece to allow for stitching. (Optional: before stuffing, place pipe cleaner pieces in the legs and tail to allow for a custom shape.)|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Stitch the open side of the arms and tail. Then at the open side of the head piece, fold the two sides together and while holding the that in, bring the bottom to the center and then the top (like gift wrapping) . Sew the top flap down and make sure the folds are solidly in place. This should create two little pockets in the top right and left corners. fold the ears in half only at the bottom and sew the bottom half of an ear and a pocket at the back of the head together. repeat with other ear.|src=1B33hCo4ZGYn2DyWgSwjqalp9Cx00KtkM|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Sew the head, arms, and tail onto the body|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=To complete, use thread or buttons to create eyes at the side of the head and a little nose at the tip. Then your little friend is complete.|show=none|src=none}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:Crafting]]&lt;br /&gt;
[[Category:Hand Sewing]]&lt;br /&gt;
[[Category:Textiles]]&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=DIY_Chipmunk_(Project_0004)&amp;diff=8479</id>
		<title>DIY Chipmunk (Project 0004)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=DIY_Chipmunk_(Project_0004)&amp;diff=8479"/>
		<updated>2025-02-17T15:06:21Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Turn a Glove Into A Chipmunk!&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:DIY Chipmunk}}&lt;br /&gt;
[[Category:Projects|DIY Chipmunk]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;overview&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Overview ==&lt;br /&gt;
&lt;br /&gt;
Have you ever wanted to make a little stuffed animal, but never knew how? Well today is your lucky day because this project will show you how to turn any normal glove into a fun little chipmunk (no machine sewing required)!! Created By:(https://www.boredpanda.com/diy-glove-into-chipmunk/?utm_source=google&amp;amp;utm_medium=organic&amp;amp;utm_campaign=organic)&lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://drive.google.com/thumbnail?id=1RnA476qswLwlYP8-IKNdC5f-7fTIy8N2&amp;amp;sz=w1000|img2=https://drive.google.com/thumbnail?id=1kjiY2KKYpR30swaU5s3Rv7dFJmBlh6QP&amp;amp;sz=w1000|img3=null|img4=null|img5=null|num=2}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tools and Materials ==&lt;br /&gt;
* Thread (Yarn optional)&lt;br /&gt;
* Stuffing&lt;br /&gt;
* Buttons&lt;br /&gt;
* Glove&lt;br /&gt;
* Scissors&lt;br /&gt;
* Pen&lt;br /&gt;
* Pipe Cleaners (optional) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;files&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Project Files==&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&#039;sxs&#039;&amp;gt;&lt;br /&gt;
== Step-by-Step Instructions ==&lt;br /&gt;
&lt;br /&gt;
{{#widget:ProjectStep|inst=Flip the glove inside out and using a pen, draw the diagram. Then pin along the lines and cut, making sure the fabric does not fray. Sew along the white lines, leaving just enough room around the edges to ensure the fabric doesn&#039;t unravel and leave large holes in the seams.   |src=1hmQfDPIU4sHq3H0PrBJtXF8u9PLJt3WU|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Once you&#039;ve sewn all the pieces together, turn them all right-side out. Stuff each piece with stuffing, except for the ears, and make sure you leave a little room at the top of each piece to allow for stitching. (Optional: before stuffing, place pipe cleaner pieces in the legs and tail to allow for a custom shape.)|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Stitch the open side of the arms and tail. Then at the open side of the head piece, fold the two sides together and while holding the that in, bring the bottom to the center and then the top (like gift wrapping) . Sew the top flap down and make sure the folds are solidly in place. This should create two little pockets in the top right and left corners. fold the ears in half only at the bottom and sew the bottom half of an ear and a pocket at the back of the head together. repeat with other ear.|src=1B33hCo4ZGYn2DyWgSwjqalp9Cx00KtkM|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Sew the head, arms, and tail onto the body|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=To complete, use thread or buttons to create eyes at the side of the head and a little nose at the tip. Then your little friend is complete.|show=none|src=none}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:Crafting]]&lt;br /&gt;
[[Category:Hand Sewing]]&lt;br /&gt;
[[Category:Textiles]]&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8478</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8478"/>
		<updated>2025-02-17T14:45:47Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button (prioritize &#039;Edit&#039; over &#039;Edit Source&#039; when available) -- styled in Medik.css */ &lt;br /&gt;
if(document.getElementById(&amp;quot;ca-edit&amp;quot;) != null || document.getElementById(&amp;quot;ca-ve-edit&amp;quot;) != null) {&lt;br /&gt;
    let link = document.getElementById(&amp;quot;ca-ve-edit&amp;quot;) != null ? document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;).href : document.querySelector(&amp;quot;#ca-edit a&amp;quot;).href;&lt;br /&gt;
    document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+link+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        var category = &amp;quot;Projects&amp;quot;;  // Default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafting&amp;quot;&amp;gt;Crafting&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Airbrushing&amp;quot;&amp;gt;Airbrushing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Button Pressing&amp;quot;&amp;gt;Button Pressing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Cassette Making&amp;quot;&amp;gt;Cassette Making&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Graphic Design&amp;quot;&amp;gt;Graphic Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Hand Sewing&amp;quot;&amp;gt;Hand Sewing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Laser Cutting&amp;quot;&amp;gt;Laser Cutting&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machining&amp;quot;&amp;gt;Machining&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;3D Modeling&amp;quot;&amp;gt;3D Modeling&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;3D Printing&amp;quot;&amp;gt;3D Printing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Programming&amp;quot;&amp;gt;Programming&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Soldering&amp;quot;&amp;gt;Soldering&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Technical Design&amp;quot;&amp;gt;Technical Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Welding&amp;quot;&amp;gt;Welding&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Woodworking&amp;quot;&amp;gt;Woodworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                        var directMatch = content.match(/img1=(https:\/\/[^\n|}%s]+)/);&lt;br /&gt;
                        if (directMatch) {&lt;br /&gt;
                            imgUrl = directMatch[1];&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // Add the gallery item if the image was found&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    &lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        var category = &amp;quot;Tools&amp;quot;;  // Default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg&amp;quot; alt=&amp;quot;No Image Available&amp;quot;&amp;gt;`}&lt;br /&gt;
&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(&amp;quot;Tools&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;Projects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\n|}%s]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Textile_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Crafting_badge_small.png&#039;, query);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Airbrushing_badge_small.png&#039;, query);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Button_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Cassette_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Graphic_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Handsewing_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Laser_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Machining_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Modeling_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Printing_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Programming_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Soldering_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical design&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Technical_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Welding_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Woodworking_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
function insertSkillBadgeLink(image, selector) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; width=&amp;quot;50px&amp;quot; style=&amp;quot;padding-left:.3em&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8449</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8449"/>
		<updated>2025-02-14T20:13:07Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
// browser.opaqueResponseBlocking.javascriptValidator = false;&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button (prioritize &#039;Edit&#039; over &#039;Edit Source&#039; when available) -- styled in Medik.css */ &lt;br /&gt;
if(document.getElementById(&amp;quot;ca-edit&amp;quot;) != null || document.getElementById(&amp;quot;ca-ve-edit&amp;quot;) != null) {&lt;br /&gt;
    let link = document.getElementById(&amp;quot;ca-ve-edit&amp;quot;) != null ? document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;).href : document.querySelector(&amp;quot;#ca-edit a&amp;quot;).href;&lt;br /&gt;
    document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+link+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        var category = &amp;quot;Projects&amp;quot;;  // Default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafting&amp;quot;&amp;gt;Crafting&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Airbrushing&amp;quot;&amp;gt;Airbrushing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Button Pressing&amp;quot;&amp;gt;Button Pressing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Cassette Making&amp;quot;&amp;gt;Cassette Making&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Graphic Design&amp;quot;&amp;gt;Graphic Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Hand Sewing&amp;quot;&amp;gt;Hand Sewing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Laser Cutting&amp;quot;&amp;gt;Laser Cutting&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machining&amp;quot;&amp;gt;Machining&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;3D Modeling&amp;quot;&amp;gt;3D Modeling&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;3D Printing&amp;quot;&amp;gt;3D Printing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Programming&amp;quot;&amp;gt;Programming&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Soldering&amp;quot;&amp;gt;Soldering&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Technical Design&amp;quot;&amp;gt;Technical Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Welding&amp;quot;&amp;gt;Welding&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Woodworking&amp;quot;&amp;gt;Woodworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                        var directMatch = content.match(/img1=(https:\/\/[^\n|}%s]+)/);&lt;br /&gt;
                        if (directMatch) {&lt;br /&gt;
                            imgUrl = directMatch[1];&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // Add the gallery item if the image was found&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    &lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : &#039;&amp;lt;div class=&amp;quot;no-image&amp;quot;&amp;gt;No Image Available&amp;lt;/div&amp;gt;&#039;}&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        var category = &amp;quot;Tools&amp;quot;;  // Default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : &#039;&amp;lt;div class=&amp;quot;no-image&amp;quot;&amp;gt;No Image Available&amp;lt;/div&amp;gt;&#039;}&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(&amp;quot;Tools&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;Projects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\n|}%s]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Textile_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Crafting_badge_small.png&#039;, query);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Airbrushing_badge_small.png&#039;, query);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Button_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Cassette_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Graphic_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Handsewing_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Laser_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Machining_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Modeling_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Printing_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Programming_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Soldering_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical design&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Technical_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Welding_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Woodworking_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
function insertSkillBadgeLink(image, selector) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; width=&amp;quot;50px&amp;quot; style=&amp;quot;padding-left:.3em&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8448</id>
		<title>MediaWiki:Common.js</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8448"/>
		<updated>2025-02-14T20:10:16Z</updated>

		<summary type="html">&lt;p&gt;TCGmaker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Any JavaScript here will be loaded for all users on every page load. */&lt;br /&gt;
browser.opaqueResponseBlocking.javascriptValidator = false;&lt;br /&gt;
if (document) window.µ = function (id, elem) {&lt;br /&gt;
  var ret;&lt;br /&gt;
  var root = ((elem) ? elem : document);&lt;br /&gt;
  switch (id.charAt(0)) {&lt;br /&gt;
    case &#039;|&#039;:&lt;br /&gt;
      ret = root;&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;+&#039;:&lt;br /&gt;
      ret = document.createElement(id.substring(1));&lt;br /&gt;
      if (elem) elem.appendChild(ret);&lt;br /&gt;
      break;&lt;br /&gt;
    case &#039;#&#039;:&lt;br /&gt;
      ret = root.querySelector(id);&lt;br /&gt;
      break;&lt;br /&gt;
    default:&lt;br /&gt;
      ret = Array.prototype.slice.call(root.querySelectorAll(id));&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ret;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* add additional edit button (prioritize &#039;Edit&#039; over &#039;Edit Source&#039; when available) -- styled in Medik.css */ &lt;br /&gt;
if(document.getElementById(&amp;quot;ca-edit&amp;quot;) != null || document.getElementById(&amp;quot;ca-ve-edit&amp;quot;) != null) {&lt;br /&gt;
    let link = document.getElementById(&amp;quot;ca-ve-edit&amp;quot;) != null ? document.querySelector(&amp;quot;#ca-ve-edit a&amp;quot;).href : document.querySelector(&amp;quot;#ca-edit a&amp;quot;).href;&lt;br /&gt;
    document.getElementById(&amp;quot;content&amp;quot;).innerHTML += &#039;&amp;lt;a href=&#039;+link+&#039;&amp;gt;&amp;lt;button class=&amp;quot;big-edit-button&amp;quot;&amp;gt;&amp;lt;p&amp;gt;EDIT&amp;lt;/p&amp;gt;&amp;lt;/button&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;GALLERY&#039;) return;  // Ensure script runs only on the Gallery page&lt;br /&gt;
&lt;br /&gt;
        var category = &amp;quot;Projects&amp;quot;;  // Default category&lt;br /&gt;
        var galleryContainer = $(&#039;#project-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Projects&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Textiles&amp;quot;&amp;gt;Textiles&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Crafting&amp;quot;&amp;gt;Crafting&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Airbrushing&amp;quot;&amp;gt;Airbrushing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Button Pressing&amp;quot;&amp;gt;Button Pressing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Cassette Making&amp;quot;&amp;gt;Cassette Making&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Graphic Design&amp;quot;&amp;gt;Graphic Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Hand Sewing&amp;quot;&amp;gt;Hand Sewing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Laser Cutting&amp;quot;&amp;gt;Laser Cutting&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machining&amp;quot;&amp;gt;Machining&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;3D Modeling&amp;quot;&amp;gt;3D Modeling&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;3D Printing&amp;quot;&amp;gt;3D Printing&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Programming&amp;quot;&amp;gt;Programming&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Soldering&amp;quot;&amp;gt;Soldering&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Technical Design&amp;quot;&amp;gt;Technical Design&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Welding&amp;quot;&amp;gt;Welding&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Woodworking&amp;quot;&amp;gt;Woodworking&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        // load gallery based on category&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                        var directMatch = content.match(/img1=(https:\/\/[^\n|}%s]+)/);&lt;br /&gt;
                        if (directMatch) {&lt;br /&gt;
                            imgUrl = directMatch[1];&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                               &lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // Add the gallery item if the image was found&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    &lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generate a gallery&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : &#039;&amp;lt;div class=&amp;quot;no-image&amp;quot;&amp;gt;No Image Available&amp;lt;/div&amp;gt;&#039;}&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// TOOLS Gallery&lt;br /&gt;
mw.loader.using([&#039;mediawiki.api&#039;, &#039;jquery&#039;], function () {&lt;br /&gt;
    $(document).ready(function () {&lt;br /&gt;
        if (mw.config.get(&#039;wgPageName&#039;) !== &#039;TOOLS&#039;) return;  // Ensure script runs only on the TOOLS page&lt;br /&gt;
&lt;br /&gt;
        var category = &amp;quot;Tools&amp;quot;;  // Default category&lt;br /&gt;
        var galleryContainer = $(&#039;#tools-gallery&#039;);  &lt;br /&gt;
&lt;br /&gt;
        // Add filter buttons before the gallery&lt;br /&gt;
        galleryContainer.before(&#039;&amp;lt;div id=&amp;quot;category-filter&amp;quot;&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Tools&amp;quot;&amp;gt;Show All&amp;lt;/button&amp;gt;&#039; +  &lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Makerspace Tools&amp;quot;&amp;gt;Makerspace Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Wood Shop Tools&amp;quot;&amp;gt;Wood Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
            &#039;&amp;lt;button class=&amp;quot;filter-btn&amp;quot; data-filter=&amp;quot;Machine Shop Tools&amp;quot;&amp;gt;Machine Shop Tools&amp;lt;/button&amp;gt;&#039; +&lt;br /&gt;
        &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
&lt;br /&gt;
        function loadGallery(category) {&lt;br /&gt;
            galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;Loading gallery...&amp;lt;/div&amp;gt;&#039;);  &lt;br /&gt;
&lt;br /&gt;
            new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                list: &#039;categorymembers&#039;,&lt;br /&gt;
                cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
                cmlimit: 50,  &lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).done(function (data) {&lt;br /&gt;
                var pages = data.query.categorymembers;&lt;br /&gt;
                var galleryHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                var requests = pages.map(function (page) {&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        prop: &#039;revisions&#039;,&lt;br /&gt;
                        rvprop: &#039;content&#039;,&lt;br /&gt;
                        titles: page.title,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (pageData) {&lt;br /&gt;
                        var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                        var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                        var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                        var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                        // Try to find a [[File:...]] entry&lt;br /&gt;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                            // Fetch full image URL from MediaWiki API&lt;br /&gt;
                            return new mw.Api().get({&lt;br /&gt;
                                action: &#039;query&#039;,&lt;br /&gt;
                                titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                                prop: &#039;imageinfo&#039;,&lt;br /&gt;
                                iiprop: &#039;url&#039;,&lt;br /&gt;
                                format: &#039;json&#039;&lt;br /&gt;
                            }).then(function (imageData) {&lt;br /&gt;
                                var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                                if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                                    imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                                }&lt;br /&gt;
&lt;br /&gt;
                                // Add the gallery item&lt;br /&gt;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&lt;br /&gt;
                            // If no image is found, still display the title&lt;br /&gt;
                            galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                });&lt;br /&gt;
&lt;br /&gt;
                Promise.all(requests).then(function () {&lt;br /&gt;
                    // Append gallery items after loading them&lt;br /&gt;
                    galleryContainer.html(&#039;&amp;lt;div class=&amp;quot;gallery-container&amp;quot;&amp;gt;&#039; + galleryHtml + &#039;&amp;lt;/div&amp;gt;&#039;);&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        function generateGalleryItem(pageUrl, title, imgUrl, category) {&lt;br /&gt;
            return `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;gallery-item ${category}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                        ${imgUrl ? `&amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${title}&amp;quot;&amp;gt;` : &#039;&amp;lt;div class=&amp;quot;no-image&amp;quot;&amp;gt;No Image Available&amp;lt;/div&amp;gt;&#039;}&lt;br /&gt;
                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;div class=&amp;quot;gallery-caption&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot;&amp;gt;${title}&amp;lt;/a&amp;gt;&lt;br /&gt;
                    &amp;lt;/div&amp;gt;&lt;br /&gt;
                &amp;lt;/div&amp;gt;&lt;br /&gt;
            `;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        loadGallery(&amp;quot;Tools&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var selectedCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(selectedCategory);  &lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//CAROUSEL&lt;br /&gt;
function loadCarouselData() {&lt;br /&gt;
    // Make the API query to fetch pages for carousel&lt;br /&gt;
    var category = &amp;quot;Projects&amp;quot;; &lt;br /&gt;
    var carouselData = [];&lt;br /&gt;
&lt;br /&gt;
    new mw.Api().get({&lt;br /&gt;
        action: &#039;query&#039;,&lt;br /&gt;
        list: &#039;categorymembers&#039;,&lt;br /&gt;
        cmtitle: &#039;Category:&#039; + category,&lt;br /&gt;
        cmlimit: 50, &lt;br /&gt;
        format: &#039;json&#039;&lt;br /&gt;
    }).done(function (data) {&lt;br /&gt;
        var pages = data.query.categorymembers;&lt;br /&gt;
&lt;br /&gt;
        var requests = pages.map(function (page) {&lt;br /&gt;
            return new mw.Api().get({&lt;br /&gt;
                action: &#039;query&#039;,&lt;br /&gt;
                prop: &#039;revisions&#039;,&lt;br /&gt;
                rvprop: &#039;content&#039;,&lt;br /&gt;
                titles: page.title,&lt;br /&gt;
                format: &#039;json&#039;&lt;br /&gt;
            }).then(function (pageData) {&lt;br /&gt;
                var pageId = Object.keys(pageData.query.pages)[0];&lt;br /&gt;
                var content = pageData.query.pages[pageId].revisions[0][&#039;*&#039;];&lt;br /&gt;
                var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
                var imgUrl = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
                // Try to find a direct image URL (img1=https://...)&lt;br /&gt;
                var directMatch = content.match(/img1=(https:\/\/[^\n|}%s]+)/);&lt;br /&gt;
                if (directMatch) {&lt;br /&gt;
                    imgUrl = directMatch[1];&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // If no direct URL, try to find a [[File:...]] entry&lt;br /&gt;
                var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                if (!imgUrl &amp;amp;&amp;amp; fileMatch) {&lt;br /&gt;
                    var fileName = fileMatch[1].trim();&lt;br /&gt;
&lt;br /&gt;
                    // Fetch full image URL from MediaWiki API&lt;br /&gt;
                    return new mw.Api().get({&lt;br /&gt;
                        action: &#039;query&#039;,&lt;br /&gt;
                        titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                        prop: &#039;imageinfo&#039;,&lt;br /&gt;
                        iiprop: &#039;url&#039;,&lt;br /&gt;
                        format: &#039;json&#039;&lt;br /&gt;
                    }).then(function (imageData) {&lt;br /&gt;
                        var imagePageId = Object.keys(imageData.query.pages)[0];&lt;br /&gt;
                        if (imageData.query.pages[imagePageId].imageinfo) {&lt;br /&gt;
                            imgUrl = imageData.query.pages[imagePageId].imageinfo[0].url;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        // Store carousel item data&lt;br /&gt;
                        if (imgUrl) {&lt;br /&gt;
                            carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                        }&lt;br /&gt;
                    });&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Store carousel item data&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        carouselData.push({ pageUrl: pageUrl, imgUrl: imgUrl, title: page.title });&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        Promise.all(requests).then(function () {&lt;br /&gt;
            // Call the function to display carousel&lt;br /&gt;
            displayCarousel(carouselData);&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function displayCarousel(carouselData) {&lt;br /&gt;
    var carouselHtml = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    carouselData.forEach(function (item) {&lt;br /&gt;
        carouselHtml += `&lt;br /&gt;
            &amp;lt;div class=&amp;quot;carousel-item&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;a href=&amp;quot;${item.pageUrl}&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;img src=&amp;quot;${item.imgUrl}&amp;quot; alt=&amp;quot;Carousel Image&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;/a&amp;gt;&lt;br /&gt;
               &amp;lt;div class=&amp;quot;carousel-title&amp;quot;&amp;gt;${item.title}&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
        `;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Inject the HTML into the carousel container&lt;br /&gt;
    var carouselContainer = $(&#039;.carousel-container&#039;);&lt;br /&gt;
    carouselContainer.html(carouselHtml);&lt;br /&gt;
&lt;br /&gt;
    // Initialize the carousel behavior&lt;br /&gt;
    initializeCarousel();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initializeCarousel() {&lt;br /&gt;
    let currentIndex = 0;&lt;br /&gt;
    let $carouselItems = $(&amp;quot;.carousel-item&amp;quot;);&lt;br /&gt;
    let totalItems = $carouselItems.length;&lt;br /&gt;
    &lt;br /&gt;
    $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    let $prevButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-prev&amp;quot;&amp;gt; ◀ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    let $nextButton = $(&#039;&amp;lt;button class=&amp;quot;carousel-next&amp;quot;&amp;gt; ▶ &amp;lt;/button&amp;gt;&#039;);&lt;br /&gt;
    $(&#039;.carousel-container&#039;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex + 1) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        currentIndex = (currentIndex - 1 + totalItems) % totalItems;&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide().eq(currentIndex).show();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&lt;br /&gt;
    loadCarouselData(); // Load the carousel data on page load&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// if page is part of a category, insert any corresponding skill badges (individual project pages)&lt;br /&gt;
if(document.getElementById(&amp;quot;catlinks&amp;quot;) != null) {&lt;br /&gt;
    document.querySelectorAll(&amp;quot;#catlinks li a&amp;quot;).forEach((cat) =&amp;gt; {&lt;br /&gt;
        let query = &amp;quot;#firstHeading&amp;quot;;&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Textiles&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Textile_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Crafting&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Crafting_badge_small.png&#039;, query);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Airbrushing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Airbrushing_badge_small.png&#039;, query);&lt;br /&gt;
        }&lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Button Pressing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Button_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Cassette Making&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Cassette_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Graphic Design&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Graphic_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Hand Sewing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Handsewing_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Laser Cutting&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Laser_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Machining&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Machining_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Modeling&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Modeling_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:3D Printing&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Printing_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Programming&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Programming_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Soldering&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Soldering_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Technical design&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Technical_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Welding&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Welding_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
        if(cat.title.includes(&amp;quot;Category:Woodworking&amp;quot;)) {&lt;br /&gt;
            insertSkillBadgeLink(&#039;File:Woodworking_badge_small.png&#039;, query);&lt;br /&gt;
        } &lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// inserts image at given selector element in html, using image in mediawiki format (eg [[File:filename...]])&lt;br /&gt;
function insertSkillBadgeLink(image, selector) {&lt;br /&gt;
    $.getJSON(&lt;br /&gt;
        mw.util.wikiScript( &#039;api&#039; ), {&lt;br /&gt;
            format: &#039;json&#039;,&lt;br /&gt;
            action: &#039;query&#039;,&lt;br /&gt;
            titles: image,&lt;br /&gt;
            prop: &#039;imageinfo&#039;,&lt;br /&gt;
            iiprop: &#039;url&#039;&lt;br /&gt;
        },&lt;br /&gt;
        function( obj ) {&lt;br /&gt;
            let pages = obj.query.pages;&lt;br /&gt;
            let result1 = pages[Object.keys(pages)[0]];&lt;br /&gt;
            let url = result1.imageinfo[0].url;&lt;br /&gt;
            let alt = result1.title; // set alt text to image title&lt;br /&gt;
            let urlSub = url.substring(url.indexOf(&amp;quot;/wiki&amp;quot;));&lt;br /&gt;
            document.querySelector(selector).innerHTML += &#039;&amp;lt;img src=&amp;quot;&#039;+urlSub+&#039;&amp;quot; alt=&amp;quot;&#039;+alt+&#039;&amp;quot; width=&amp;quot;50px&amp;quot; style=&amp;quot;padding-left:.3em&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>TCGmaker</name></author>
	</entry>
</feed>