<?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=EvaC</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=EvaC"/>
	<link rel="alternate" type="text/html" href="https://makerspace.cc/Special:Contributions/EvaC"/>
	<updated>2026-05-06T15:23:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.7</generator>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=9038</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=9038"/>
		<updated>2025-03-09T16:20:08Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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 that appears in bottom-right corner */&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); /* theme color; set in LocalSettings.php */&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;
/* insert pencil icon before text of big edit button */&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(1); /* change pencil icon from black to white */&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;
        column-count: 2; &lt;br /&gt;
        padding-top: 20px;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    .gallery-caption {&lt;br /&gt;
        font-size: 12px; &lt;br /&gt;
    }&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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=9021</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=9021"/>
		<updated>2025-03-07T19:49:10Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
    &amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Conditionally render the image only if &#039;show&#039; and &#039;src&#039; are not &#039;none&#039; --&amp;gt;&lt;br /&gt;
    &amp;lt;!--{if $show != &#039;none&#039; &amp;amp;&amp;amp; $src != &#039;none&#039;}--&amp;gt;&lt;br /&gt;
        &amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;!--{/if}--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=9014</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=9014"/>
		<updated>2025-03-07T19:20:16Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8901</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=8901"/>
		<updated>2025-02-27T15:18:42Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;br /&gt;
&lt;br /&gt;
.videoBox {&lt;br /&gt;
    display: none;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8854</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8854"/>
		<updated>2025-02-27T03:53:16Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/uc?export=view&amp;amp;id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8853</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8853"/>
		<updated>2025-02-27T03:51:27Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/uc?export=view&amp;amp;id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8852</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8852"/>
		<updated>2025-02-27T03:50:41Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Undo revision 8851 by EvaC (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!--&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8851</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8851"/>
		<updated>2025-02-27T03:47:23Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8848</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8848"/>
		<updated>2025-02-27T03:42:47Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!--&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8840</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8840"/>
		<updated>2025-02-27T00:43:01Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;!--&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8839</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8839"/>
		<updated>2025-02-27T00:35:55Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8838</id>
		<title>Widget:ProjectStep</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Widget:ProjectStep&amp;diff=8838"/>
		<updated>2025-02-27T00:11:09Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&#039;step&#039; show=&#039;&amp;lt;!--{$show|escape:&#039;html&#039;}--&amp;gt;&#039;&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;!--&amp;lt;img src=&#039;https://drive.google.com/thumbnail?id=&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;&amp;amp;sz=w1000&#039;&amp;gt;&amp;lt;/img&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;videoBox&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;iframe src=&amp;quot;https://drive.google.com/file/d/&amp;lt;!--{$src|escape:&#039;html&#039;}--&amp;gt;/preview&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!--{$inst|escape:&#039;html&#039;}--&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8837</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=8837"/>
		<updated>2025-02-26T23:28:34Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Undo revision 8836 by EvaC (talk)&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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8836</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=8836"/>
		<updated>2025-02-26T23:18:20Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
                    console.log(&amp;quot;Extracted Page Content:&amp;quot;, content); // Debugging step&lt;br /&gt;
&lt;br /&gt;
                    // Ignore images inside {{#widget:ProjectStep|...}}&lt;br /&gt;
                    content = content.replace(/\{\{#widget:ProjectStep\|.*?src=.*?\}\}/g, &#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 the full image URL using MediaWiki API&lt;br /&gt;
                        return new mw.Api().get({&lt;br /&gt;
                            action: &#039;query&#039;,&lt;br /&gt;
                            prop: &#039;imageinfo&#039;,&lt;br /&gt;
                            titles: &#039;File:&#039; + fileName,&lt;br /&gt;
                            iiprop: &#039;url&#039;,&lt;br /&gt;
                            format: &#039;json&#039;&lt;br /&gt;
                        }).then(function (fileData) {&lt;br /&gt;
                            var filePageId = Object.keys(fileData.query.pages)[0];&lt;br /&gt;
                            if (fileData.query.pages[filePageId].imageinfo) {&lt;br /&gt;
                                imgUrl = fileData.query.pages[filePageId].imageinfo[0].url;&lt;br /&gt;
                            }&lt;br /&gt;
&lt;br /&gt;
                            // Append only one image&lt;br /&gt;
                            if (imgUrl) {&lt;br /&gt;
                                galleryHtml += `&amp;lt;div class=&amp;quot;gallery-item&amp;quot;&amp;gt;&lt;br /&gt;
                                    &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;&lt;br /&gt;
                                        &amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${page.title}&amp;quot;&amp;gt;&lt;br /&gt;
                                        &amp;lt;p&amp;gt;${page.title}&amp;lt;/p&amp;gt;&lt;br /&gt;
                                    &amp;lt;/a&amp;gt;&lt;br /&gt;
                                &amp;lt;/div&amp;gt;`;&lt;br /&gt;
                            }&lt;br /&gt;
                        });&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // Append only one image&lt;br /&gt;
                    if (imgUrl) {&lt;br /&gt;
                        galleryHtml += `&amp;lt;div class=&amp;quot;gallery-item&amp;quot;&amp;gt;&lt;br /&gt;
                            &amp;lt;a href=&amp;quot;${pageUrl}&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;&lt;br /&gt;
                                &amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${page.title}&amp;quot;&amp;gt;&lt;br /&gt;
                                &amp;lt;p&amp;gt;${page.title}&amp;lt;/p&amp;gt;&lt;br /&gt;
                            &amp;lt;/a&amp;gt;&lt;br /&gt;
                        &amp;lt;/div&amp;gt;`;&lt;br /&gt;
                    }&lt;br /&gt;
                });&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
            Promise.all(requests).then(function () {&lt;br /&gt;
                galleryContainer.find(&#039;.gallery-container&#039;).html(galleryHtml);&lt;br /&gt;
            });&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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8589</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=8589"/>
		<updated>2025-02-20T15:58:27Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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 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:\/\/[^\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(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;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, &amp;quot;Textiles&amp;quot;);&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, &amp;quot;Crafting&amp;quot;);&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, &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;
            insertSkillBadgeLink(&#039;File:Button_badge_small.png&#039;, query, &amp;quot;Button%20Pressing&amp;quot;);&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, &amp;quot;Cassette%20Making&amp;quot;);&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, &amp;quot;Graphic%20Design&amp;quot;);&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, &amp;quot;Hand%20Sewing&amp;quot;);&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, &amp;quot;Laser%20Cutting&amp;quot;);&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, &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;
            insertSkillBadgeLink(&#039;File:Modeling_badge_small.png&#039;, query, &amp;quot;3D%20Modeling&amp;quot;);&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, &amp;quot;3D%20Printing&amp;quot;);&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, &amp;quot;Programming&amp;quot;);&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, &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;
            insertSkillBadgeLink(&#039;File:Technical_badge_small.png&#039;, query, &amp;quot;Technical%20Design&amp;quot;);&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, &amp;quot;Welding&amp;quot;);&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, &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;
function insertSkillBadgeLink(image, selector, linkFilter) {&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;a href=&amp;quot;./GALLERY?title=GALLERY&amp;amp;filter=&#039;+linkFilter+&#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;padding-left:.3em&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
        }&lt;br /&gt;
    );&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8557</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=8557"/>
		<updated>2025-02-19T19:10:24Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
.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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8556</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=8556"/>
		<updated>2025-02-19T19:02:46Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Undo revision 8553 by EvaC (talk)&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;
.gallery-container {&lt;br /&gt;
    display: grid;&lt;br /&gt;
    grid-template-columns: repeat(4, 1fr); &lt;br /&gt;
    gap: 10px; &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;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%;  /* Adjust width to be responsive */&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;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8555</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=8555"/>
		<updated>2025-02-19T19:01:38Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Undo revision 8554 by EvaC (talk)&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;
.gallery-container {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column; /* Stack images vertically */&lt;br /&gt;
    align-items: center; &lt;br /&gt;
    gap: 10px; &lt;br /&gt;
    max-width: 300px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 80%;  &lt;br /&gt;
    max-width: 200px; &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;
.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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8554</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=8554"/>
		<updated>2025-02-19T19:00:26Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
.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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8553</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=8553"/>
		<updated>2025-02-19T18:48:07Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
.gallery-container {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    flex-direction: column; /* Stack images vertically */&lt;br /&gt;
    align-items: center; &lt;br /&gt;
    gap: 10px; &lt;br /&gt;
    max-width: 300px; &lt;br /&gt;
    margin: auto; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    width: 100%; &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 80%;  &lt;br /&gt;
    max-width: 200px; &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;
.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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8552</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=8552"/>
		<updated>2025-02-19T18:05:16Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
&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 id=&amp;quot;filter-all&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;filter-textiles&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;button id=&amp;quot;filter-crafting&amp;quot; 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 id=&amp;quot;filter-airbrushing&amp;quot; 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 id=&amp;quot;filter-button-pressing&amp;quot; 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 id=&amp;quot;filter-cassette-making&amp;quot; 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 id=&amp;quot;filter-graphic-design&amp;quot; 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 id=&amp;quot;filter-hand-sewing&amp;quot; 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 id=&amp;quot;filter-laser-cutting&amp;quot; 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 id=&amp;quot;filter-machining&amp;quot; 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 id=&amp;quot;filter-3d-modeling&amp;quot; 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 id=&amp;quot;filter-3d-printing&amp;quot; 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 id=&amp;quot;filter-programming&amp;quot; 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 id=&amp;quot;filter-soldering&amp;quot; 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 id=&amp;quot;filter-technical-design&amp;quot; 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 id=&amp;quot;filter-welding&amp;quot; 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 id=&amp;quot;filter-woodworking&amp;quot; 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;
&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;
//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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Wood_Shop_Tools&amp;diff=8507</id>
		<title>Wood Shop Tools</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Wood_Shop_Tools&amp;diff=8507"/>
		<updated>2025-02-17T19:27:33Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Machine_Shop_Tools&amp;diff=8506</id>
		<title>Machine Shop Tools</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Machine_Shop_Tools&amp;diff=8506"/>
		<updated>2025-02-17T19:26:49Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Makerspace_Tools&amp;diff=8504</id>
		<title>Makerspace Tools</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Makerspace_Tools&amp;diff=8504"/>
		<updated>2025-02-17T19:26:13Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8490</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=8490"/>
		<updated>2025-02-17T19:02:26Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
//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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8489</id>
		<title>Spaces</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8489"/>
		<updated>2025-02-17T19:01:10Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Makerspace Spaces}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;Are you hoping to make something on campus? Here&#039;s a listing of all the places on campus that can help you out! All Makerspace locations are in the basement of Anderson Hall.&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;imagemap&amp;gt;Image:updated_makerspace_map.png|Subtitle of Image Map updated_makerspace_map.png&lt;br /&gt;
rect 134 298 406 410 [[Spaces_New#Class_Of_1969_Makerspace|Central hub for your making needs on Carleton Campus]]&lt;br /&gt;
rect 750 700 924 872 [[Spaces_New#Wood_Shop|Wood Shop]]&lt;br /&gt;
rect 604 874 924 1040 [[Spaces_New#Instrument_Shop|This space contains all of the higher precision tools used for STEM department research]]&lt;br /&gt;
poly 918 702 754 542 760 420 802 418 806 224 864 238 864 238 [[Spaces_New#Machine_Shop|General purpose machine shop for student use]]&lt;br /&gt;
poly 312 824 338 710 198 466 134 758 [[Spaces_New#Repair_Lair|Contains bike repair cart, sewing machines, and many reusable treasures]]&lt;br /&gt;
&amp;lt;/imagemap&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Class Of 1969 Makerspace&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
Central hub for all making on the Carleton College campus. This is the central hub for your making needs on campus. Have an idea and don&#039;t know where to start? Stop in and we&#039;ll help get you started! Want to learn a skill, but don&#039;t have a project in mind? We can help you with a variety of kits and brainstorming tools!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 028 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|MAKERSPACE TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Button badge small.png|link=GALLERY|alt=Blue &amp;quot;button pressing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Cassette badge small.png|link=GALLERY|alt=Yellow &amp;quot;cassette making icon&amp;quot;|frameless]]&lt;br /&gt;
[[File:Crafting badge_small.png|link=GALLERY|alt=Brown &amp;quot;crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Graphic badge small.png|link=GALLERY|alt=Indigo &amp;quot;graphic design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Printing badge small.png|link=GALLERY|alt=Purple &amp;quot;3d printing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Programming badge small.png|link=GALLERY|alt=Green &amp;quot;programming&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Repair Lair&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
The Makerspace Repair Lair is located in the hallway across from the Makerspace. It is open after hours. It contains the Bike Repair cart, a sewing machine, scrap fabric, and many reusable treasures sourced from around campus.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 029 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Anytime!&lt;br /&gt;
&lt;br /&gt;
[[File:Crafting_badge_small.png|link=GALLERY|alt=Brown &amp;quot;Crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Wood Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms woodshop.jpg|alt=A view of the inside of the Woodshop|thumb]]&lt;br /&gt;
The Makerspace Woodshop is a general purpose carpentry shop available for general student use. We have a limited supply of materials available to for use, after filing out a project proposal. The space contains a variety of saws (table, panel, band, battery, miller), drill presses, jointers, nail guns, and sanders.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 037 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|WOODSHOP TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Woodworking badge small.png|link=GALLERY|alt=Blue &amp;quot;woodworking&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Instrument Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms instrumentshop.jpg|alt=A view of the inside of the Instrument Shop|thumb]]&lt;br /&gt;
This is the Scientific Instrument production shop for Carleton College. This shop contains all of the higher precision tools used to make apparatus for the STEM department research labs. This space also contains a student-accessible welding studio, CNC plasma cutter, sheet metal sheer, and press brake, as well as a dermestid beetle colony.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 049 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|INSTRUMENT SHOP TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Machine Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 133016630.jpg|alt=A view of the inside of the Machine Shop|thumb]]&lt;br /&gt;
General purpose machine shop for student use. The Build Spot Student Machine Shop has a full complement of precision machining equipment suitable for working with a variety of metals and plastics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 039 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|MACHINE SHOP TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8487</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=8487"/>
		<updated>2025-02-17T18:58:37Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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 to get URL parameters&lt;br /&gt;
        function getUrlParameter(name) {&lt;br /&gt;
            var results = new RegExp(&#039;[\?&amp;amp;]&#039; + name + &#039;=([^&amp;amp;#]*)&#039;).exec(window.location.href);&lt;br /&gt;
            return results ? decodeURIComponent(results[1].replace(/\+/g, &#039; &#039;)) : null;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check if a filter is passed in the URL&lt;br /&gt;
        var selectedCategory = getUrlParameter(&#039;filter&#039;);&lt;br /&gt;
        if (!selectedCategory) selectedCategory = &amp;quot;Tools&amp;quot;; // Default to Tools if no parameter&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;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&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;
                                galleryHtml += generateGalleryItem(pageUrl, page.title, imgUrl, category);&lt;br /&gt;
                            });&lt;br /&gt;
                        } else {&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;
                    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;
                    &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;
        // Load gallery with the selected category&lt;br /&gt;
        loadGallery(selectedCategory);&lt;br /&gt;
&lt;br /&gt;
        // Highlight the correct filter button and load the selected category on click&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).click(function () {&lt;br /&gt;
            var newCategory = $(this).data(&amp;quot;filter&amp;quot;);&lt;br /&gt;
            loadGallery(newCategory);&lt;br /&gt;
            history.replaceState(null, &amp;quot;&amp;quot;, &amp;quot;?filter=&amp;quot; + encodeURIComponent(newCategory)); // Update URL without reloading&lt;br /&gt;
        });&lt;br /&gt;
&lt;br /&gt;
        // Auto-select the correct filter button based on URL parameter&lt;br /&gt;
        $(&amp;quot;.filter-btn&amp;quot;).each(function () {&lt;br /&gt;
            if ($(this).data(&amp;quot;filter&amp;quot;) === selectedCategory) {&lt;br /&gt;
                $(this).addClass(&amp;quot;active&amp;quot;);&lt;br /&gt;
            }&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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8486</id>
		<title>Spaces</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8486"/>
		<updated>2025-02-17T18:57:19Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Makerspace Spaces}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;Are you hoping to make something on campus? Here&#039;s a listing of all the places on campus that can help you out! All Makerspace locations are in the basement of Anderson Hall.&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;imagemap&amp;gt;Image:updated_makerspace_map.png|Subtitle of Image Map updated_makerspace_map.png&lt;br /&gt;
rect 134 298 406 410 [[Spaces_New#Class_Of_1969_Makerspace|Central hub for your making needs on Carleton Campus]]&lt;br /&gt;
rect 750 700 924 872 [[Spaces_New#Wood_Shop|Wood Shop]]&lt;br /&gt;
rect 604 874 924 1040 [[Spaces_New#Instrument_Shop|This space contains all of the higher precision tools used for STEM department research]]&lt;br /&gt;
poly 918 702 754 542 760 420 802 418 806 224 864 238 864 238 [[Spaces_New#Machine_Shop|General purpose machine shop for student use]]&lt;br /&gt;
poly 312 824 338 710 198 466 134 758 [[Spaces_New#Repair_Lair|Contains bike repair cart, sewing machines, and many reusable treasures]]&lt;br /&gt;
&amp;lt;/imagemap&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Class Of 1969 Makerspace&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
Central hub for all making on the Carleton College campus. This is the central hub for your making needs on campus. Have an idea and don&#039;t know where to start? Stop in and we&#039;ll help get you started! Want to learn a skill, but don&#039;t have a project in mind? We can help you with a variety of kits and brainstorming tools!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 028 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS?filter=Makerspace%20Tools|MAKERSPACE TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Button badge small.png|link=GALLERY|alt=Blue &amp;quot;button pressing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Cassette badge small.png|link=GALLERY|alt=Yellow &amp;quot;cassette making icon&amp;quot;|frameless]]&lt;br /&gt;
[[File:Crafting badge_small.png|link=GALLERY|alt=Brown &amp;quot;crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Graphic badge small.png|link=GALLERY|alt=Indigo &amp;quot;graphic design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Printing badge small.png|link=GALLERY|alt=Purple &amp;quot;3d printing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Programming badge small.png|link=GALLERY|alt=Green &amp;quot;programming&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Repair Lair&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
The Makerspace Repair Lair is located in the hallway across from the Makerspace. It is open after hours. It contains the Bike Repair cart, a sewing machine, scrap fabric, and many reusable treasures sourced from around campus.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 029 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Anytime!&lt;br /&gt;
&lt;br /&gt;
[[File:Crafting_badge_small.png|link=GALLERY|alt=Brown &amp;quot;Crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Wood Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms woodshop.jpg|alt=A view of the inside of the Woodshop|thumb]]&lt;br /&gt;
The Makerspace Woodshop is a general purpose carpentry shop available for general student use. We have a limited supply of materials available to for use, after filing out a project proposal. The space contains a variety of saws (table, panel, band, battery, miller), drill presses, jointers, nail guns, and sanders.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 037 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|WOODSHOP TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Woodworking badge small.png|link=GALLERY|alt=Blue &amp;quot;woodworking&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Instrument Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms instrumentshop.jpg|alt=A view of the inside of the Instrument Shop|thumb]]&lt;br /&gt;
This is the Scientific Instrument production shop for Carleton College. This shop contains all of the higher precision tools used to make apparatus for the STEM department research labs. This space also contains a student-accessible welding studio, CNC plasma cutter, sheet metal sheer, and press brake, as well as a dermestid beetle colony.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 049 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|INSTRUMENT SHOP TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Machine Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 133016630.jpg|alt=A view of the inside of the Machine Shop|thumb]]&lt;br /&gt;
General purpose machine shop for student use. The Build Spot Student Machine Shop has a full complement of precision machining equipment suitable for working with a variety of metals and plastics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 039 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|MACHINE SHOP TOOLS]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Cassette_Player_Circuit_(Project_0042)&amp;diff=8483</id>
		<title>Cassette Player Circuit (Project 0042)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Cassette_Player_Circuit_(Project_0042)&amp;diff=8483"/>
		<updated>2025-02-17T18:41:45Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Oliver Licht&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:Cassette Player Circuit}}&lt;br /&gt;
[[Category:Projects|Cassette Player Circuit]]&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;
Cassette Players work by amplifying a small voltage generated from a cassette tape playback head from about 0.1mV up to enough to drive a speaker. Some key considerations in these circuits are equalization, minimization of noise, and clean amplification. In this project, we build a circuit that will output a clean audio signal from a cassette tape head using basic electronics components. &lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://lh3.googleusercontent.com/d/1RA2W8xoomFUsPZp3U6XuTxZHfEWhMpmG=w1000?authuser=1|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;
* Breadboard&lt;br /&gt;
* Cassette mechanism with motor and tapehead (taking apart the ByronStatics player works well)&lt;br /&gt;
* 4 crocodile clip cables to make connections to the tape head and tape motor&lt;br /&gt;
* Additional alligator clips if necessary to splice wires&lt;br /&gt;
* Resistors: 100Ω (x4), 10kΩ (x3),  22kΩ, 105kΩ, 160 kΩ&lt;br /&gt;
* Unpolarized Capacitors: 1nF, 10nF, 47nF (x3)&lt;br /&gt;
* Polarized Capacitors: 4.7uF, 1uF, 10uF, 68uF&lt;br /&gt;
* LM4562 audio op-amp&lt;br /&gt;
* 2SC1815 audio transistor&lt;br /&gt;
* DC voltage supply capable of supplying +15V,  -15V, +3.3V, and +1.6V (may vary depending on motor)&lt;br /&gt;
* Function generator for diagnostic purposes with BNC splitter &amp;amp; cable&lt;br /&gt;
* Oscilloscope with probe&lt;br /&gt;
* A collection of wires&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=1oknIsrX-gGvHeeHfbGLSw5kr5TBqaAEb transistor_characterization - Oliver Licht.png]&lt;br /&gt;
* [https://drive.google.com/open?id=18HZ-GOd_GGsYu8sidNzmSp5152HHWC84 frequency_response - Oliver Licht.png]&lt;br /&gt;
* [https://drive.google.com/open?id=1bsJ_zhNUfImg0eh99g1N8EvBLta4RUir LM4562_pinout - Oliver Licht.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=Test cassette motor power requirements.&lt;br /&gt;
Open the case of the cassette player you will be using, and measure the voltage across the two pins labeled MO+ &amp;amp; MO- while it is operating. For the ByronStatics cassette player, this should be about 1.6V. This is the voltage you will use to drive the motor.|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Harvest the necessary physical components.&lt;br /&gt;
Taking off the back of the cassette player, desolder the connectors for the tape head, the motor, and the switch. You also might have to desolder some of the other connections to remove the PCB from the case. Our goal is to remove the cassette mechanism, which should include the tape head, tape motor, and a switch connected to the play button.|src=15MmB001g8dXzqvUs_mCFNwBm_c19Pq-6|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Wire up the motor. &lt;br /&gt;
With alligator clips, connect the negative end of the +1.6V power supply to the motor, and connect the positive end to one of the wires on the cassette chassis switch. Connect the other end of the switch to the positive end of the motor. Now, when the play button is pushed down, the motor should get power and begin to turn. I chose to use a separate external switch for the motor power, but the choice is up to you.|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Testing the preamplification common emitter amplifier circuit (recommended but not required).&lt;br /&gt;
The first circuit we will build for our project will pre-amplify the signal from the tape head. To ensure that our signal doesn’t get cut off, we will first verify that our transistor is at a linear operating point. To begin, construct the circuit depicted in the diagram for this step using a 2SC1815 NPN audio transistor and the relevant resistors. First, measure the voltage between R1 and R2. It should be approximately 0.57V. To verify that our transistor is at a linear operating point, we will output a 1V peak-to-peak sine wave from the function generator at 1kHz. Connect this function generator output to the circuit, with the positive connection between R_1 &amp;amp; R_2, and the negative connection to ground. Using a splitter, connect the same signal from the function generator output to CH1 on the oscilloscope. Connect the CH2 input to the oscilloscope between the transistor &amp;amp; R_C using an oscilloscope probe. From here, navigate to the acquire menu on the oscilloscope, and choose XY timebase mode. You should see an output similar to the transistor_characterization.png in the supporting files. If your curve doesn’t show the same horizontal range, you can adjust the amplitude of the sine wave, but it should not exceed 4V. Using the cursors, verify that the voltage you measured between R_1 &amp;amp; R_2 is in the sloped range of the plot. If this is the case, the circuit should amplify audio signals properly!|src=17CuuCunReHVjI7VODLJqMBR2nZ6q6PHb|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Construct the remainder of the common emitter amplifier circuit. &lt;br /&gt;
Building on the circuit from the previous step, add the capacitors &amp;amp; connect the input to the tape head to create the full common-emitter amplifier circuit. At this point, you can test a cassette tape, measuring the output with an oscilloscope probe. The signal may look noisy, but as long as it’s in a detectable range on the order of about 10 mV peak-to-peak, the circuit should be working properly.|src=1Us7LvXYF3Ggp2QeRbJFU4caTbcN1M76e|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Build an inverting amplifier. &lt;br /&gt;
Here, we construct the next stage of our circuit, the inverting amplifier. Construct the circuit below with the relevant resistors &amp;amp; capacitors and an LM4562 op-amp. Ensure that pins 8 and 4 (V+ &amp;amp; V- rails) of the op-amp are at +15V and -15V respectively. I used pin 1 for the output and pins 2 &amp;amp; 3 for the inverting &amp;amp; non-inverting inputs respectively. These pins come from the op-amp datasheet, with the pinout attached in supporting files. If using a different op-amp, ensure that you consult the datasheet for the right pins. After constructing this circuit, you can connect the output from the first common-emitter amplifier stage to the input, and test the output with an amplified speaker. It’s a good idea to start with the speaker at a minimum volume, then progressively increase until you hear sound.|src=1Xs-Zr-JklNGW66YozOdskTRfoRkIRJry|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Create and Characterize an RC equalization circuit. &lt;br /&gt;
Using the 160kΩ resistor and the 1 nF capacitor, build the following high-pass filter circuit. The audio output will be connected to the resistor, but to test the filter, you can connect a function generator to the input, and an oscilloscope across the capacitor (this part is also optional). With a 5V peak-to-peak sine wave, start at a 20 Hz signal and gradually increase the frequency. The 20 Hz signal should be close to the full 5V peak-to-peak, which should drop to about 1V by 500 Hz. Up to 20000 Hz, the output should decrease further to about 0.1V. Attached in the supporting files is a frequency response curve for this circuit, which you could replicate by plotting 1-(Vout/Vin) against the frequency. We characterize the corresponding low-pass filter instead of the high-pass filter to avoid creating a ground loop by measuring the voltage across the resistor. Keeping the capacitor between the resistor and ground also helps to reduce noise from the ground connection.|src=1-IOoXGpSU1f-1zzcLDgF-TyBQrkQdZWz|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Connect the different functional blocks. &lt;br /&gt;
At this point, we’re almost done! Following the functional diagram below, connect the tape head to the common emitter amplifier, connect the common emitter amplifier output to the inverting amplifier, connect the common emitter amplifier to the RC high pass filter, and connect your amplified speaker across the final 160 kΩ resistor! One final step we will take to reduce circuit noise is to connect 47nF capacitors between the voltage rails (+15V, -15V, and +3.3V) and ground. The +1.6V rail only powers the motor, so noise from this rail does not affect sound quality. |src=1By7ZcAC9ibNPZtFLdoIid-9dIYUd-5o1|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Test the Output! &lt;br /&gt;
With our circuit fully constructed, pick your favorite cassette, push the play button on the cassette chassis to bring the playback head into contact with the tape, turn on the power supplies, and switch on the speaker and the cassette motor. |show=none|src=none}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:Soldering]]&lt;br /&gt;
[[Category:Cassette Making]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Cassette_Player_Circuit_(Project_0042)&amp;diff=8482</id>
		<title>Cassette Player Circuit (Project 0042)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Cassette_Player_Circuit_(Project_0042)&amp;diff=8482"/>
		<updated>2025-02-17T18:41:02Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Oliver Licht&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:Cassette Player Circuit}}&lt;br /&gt;
[[Category:Projects|Cassette Player Circuit]]&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;
Cassette Players work by amplifying a small voltage generated from a cassette tape playback head from about 0.1mV up to enough to drive a speaker. Some key considerations in these circuits are equalization, minimization of noise, and clean amplification. In this project, we build a circuit that will output a clean audio signal from a cassette tape head using basic electronics components. &lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://drive.google.com/thumbnail&lt;br /&gt;
id=1RA2W8xoomFUsPZp3U6XuTxZHfEWhMpmG&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;
* Breadboard&lt;br /&gt;
* Cassette mechanism with motor and tapehead (taking apart the ByronStatics player works well)&lt;br /&gt;
* 4 crocodile clip cables to make connections to the tape head and tape motor&lt;br /&gt;
* Additional alligator clips if necessary to splice wires&lt;br /&gt;
* Resistors: 100Ω (x4), 10kΩ (x3),  22kΩ, 105kΩ, 160 kΩ&lt;br /&gt;
* Unpolarized Capacitors: 1nF, 10nF, 47nF (x3)&lt;br /&gt;
* Polarized Capacitors: 4.7uF, 1uF, 10uF, 68uF&lt;br /&gt;
* LM4562 audio op-amp&lt;br /&gt;
* 2SC1815 audio transistor&lt;br /&gt;
* DC voltage supply capable of supplying +15V,  -15V, +3.3V, and +1.6V (may vary depending on motor)&lt;br /&gt;
* Function generator for diagnostic purposes with BNC splitter &amp;amp; cable&lt;br /&gt;
* Oscilloscope with probe&lt;br /&gt;
* A collection of wires&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=1oknIsrX-gGvHeeHfbGLSw5kr5TBqaAEb transistor_characterization - Oliver Licht.png]&lt;br /&gt;
* [https://drive.google.com/open?id=18HZ-GOd_GGsYu8sidNzmSp5152HHWC84 frequency_response - Oliver Licht.png]&lt;br /&gt;
* [https://drive.google.com/open?id=1bsJ_zhNUfImg0eh99g1N8EvBLta4RUir LM4562_pinout - Oliver Licht.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=Test cassette motor power requirements.&lt;br /&gt;
Open the case of the cassette player you will be using, and measure the voltage across the two pins labeled MO+ &amp;amp; MO- while it is operating. For the ByronStatics cassette player, this should be about 1.6V. This is the voltage you will use to drive the motor.|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Harvest the necessary physical components.&lt;br /&gt;
Taking off the back of the cassette player, desolder the connectors for the tape head, the motor, and the switch. You also might have to desolder some of the other connections to remove the PCB from the case. Our goal is to remove the cassette mechanism, which should include the tape head, tape motor, and a switch connected to the play button.|src=15MmB001g8dXzqvUs_mCFNwBm_c19Pq-6|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Wire up the motor. &lt;br /&gt;
With alligator clips, connect the negative end of the +1.6V power supply to the motor, and connect the positive end to one of the wires on the cassette chassis switch. Connect the other end of the switch to the positive end of the motor. Now, when the play button is pushed down, the motor should get power and begin to turn. I chose to use a separate external switch for the motor power, but the choice is up to you.|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Testing the preamplification common emitter amplifier circuit (recommended but not required).&lt;br /&gt;
The first circuit we will build for our project will pre-amplify the signal from the tape head. To ensure that our signal doesn’t get cut off, we will first verify that our transistor is at a linear operating point. To begin, construct the circuit depicted in the diagram for this step using a 2SC1815 NPN audio transistor and the relevant resistors. First, measure the voltage between R1 and R2. It should be approximately 0.57V. To verify that our transistor is at a linear operating point, we will output a 1V peak-to-peak sine wave from the function generator at 1kHz. Connect this function generator output to the circuit, with the positive connection between R_1 &amp;amp; R_2, and the negative connection to ground. Using a splitter, connect the same signal from the function generator output to CH1 on the oscilloscope. Connect the CH2 input to the oscilloscope between the transistor &amp;amp; R_C using an oscilloscope probe. From here, navigate to the acquire menu on the oscilloscope, and choose XY timebase mode. You should see an output similar to the transistor_characterization.png in the supporting files. If your curve doesn’t show the same horizontal range, you can adjust the amplitude of the sine wave, but it should not exceed 4V. Using the cursors, verify that the voltage you measured between R_1 &amp;amp; R_2 is in the sloped range of the plot. If this is the case, the circuit should amplify audio signals properly!|src=17CuuCunReHVjI7VODLJqMBR2nZ6q6PHb|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Construct the remainder of the common emitter amplifier circuit. &lt;br /&gt;
Building on the circuit from the previous step, add the capacitors &amp;amp; connect the input to the tape head to create the full common-emitter amplifier circuit. At this point, you can test a cassette tape, measuring the output with an oscilloscope probe. The signal may look noisy, but as long as it’s in a detectable range on the order of about 10 mV peak-to-peak, the circuit should be working properly.|src=1Us7LvXYF3Ggp2QeRbJFU4caTbcN1M76e|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Build an inverting amplifier. &lt;br /&gt;
Here, we construct the next stage of our circuit, the inverting amplifier. Construct the circuit below with the relevant resistors &amp;amp; capacitors and an LM4562 op-amp. Ensure that pins 8 and 4 (V+ &amp;amp; V- rails) of the op-amp are at +15V and -15V respectively. I used pin 1 for the output and pins 2 &amp;amp; 3 for the inverting &amp;amp; non-inverting inputs respectively. These pins come from the op-amp datasheet, with the pinout attached in supporting files. If using a different op-amp, ensure that you consult the datasheet for the right pins. After constructing this circuit, you can connect the output from the first common-emitter amplifier stage to the input, and test the output with an amplified speaker. It’s a good idea to start with the speaker at a minimum volume, then progressively increase until you hear sound.|src=1Xs-Zr-JklNGW66YozOdskTRfoRkIRJry|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Create and Characterize an RC equalization circuit. &lt;br /&gt;
Using the 160kΩ resistor and the 1 nF capacitor, build the following high-pass filter circuit. The audio output will be connected to the resistor, but to test the filter, you can connect a function generator to the input, and an oscilloscope across the capacitor (this part is also optional). With a 5V peak-to-peak sine wave, start at a 20 Hz signal and gradually increase the frequency. The 20 Hz signal should be close to the full 5V peak-to-peak, which should drop to about 1V by 500 Hz. Up to 20000 Hz, the output should decrease further to about 0.1V. Attached in the supporting files is a frequency response curve for this circuit, which you could replicate by plotting 1-(Vout/Vin) against the frequency. We characterize the corresponding low-pass filter instead of the high-pass filter to avoid creating a ground loop by measuring the voltage across the resistor. Keeping the capacitor between the resistor and ground also helps to reduce noise from the ground connection.|src=1-IOoXGpSU1f-1zzcLDgF-TyBQrkQdZWz|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Connect the different functional blocks. &lt;br /&gt;
At this point, we’re almost done! Following the functional diagram below, connect the tape head to the common emitter amplifier, connect the common emitter amplifier output to the inverting amplifier, connect the common emitter amplifier to the RC high pass filter, and connect your amplified speaker across the final 160 kΩ resistor! One final step we will take to reduce circuit noise is to connect 47nF capacitors between the voltage rails (+15V, -15V, and +3.3V) and ground. The +1.6V rail only powers the motor, so noise from this rail does not affect sound quality. |src=1By7ZcAC9ibNPZtFLdoIid-9dIYUd-5o1|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Test the Output! &lt;br /&gt;
With our circuit fully constructed, pick your favorite cassette, push the play button on the cassette chassis to bring the playback head into contact with the tape, turn on the power supplies, and switch on the speaker and the cassette motor. |show=none|src=none}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:Soldering]]&lt;br /&gt;
[[Category:Cassette Making]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Cassette_Player_Circuit_(Project_0042)&amp;diff=8481</id>
		<title>Cassette Player Circuit (Project 0042)</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Cassette_Player_Circuit_(Project_0042)&amp;diff=8481"/>
		<updated>2025-02-17T18:39:23Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;by Oliver Licht&amp;lt;/small&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
__NOTOC__&lt;br /&gt;
{{DISPLAYTITLE:Cassette Player Circuit}}&lt;br /&gt;
[[Category:Projects|Cassette Player Circuit]]&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;
Cassette Players work by amplifying a small voltage generated from a cassette tape playback head from about 0.1mV up to enough to drive a speaker. Some key considerations in these circuits are equalization, minimization of noise, and clean amplification. In this project, we build a circuit that will output a clean audio signal from a cassette tape head using basic electronics components. &lt;br /&gt;
&lt;br /&gt;
{{#widget:gallery|img1=https://drive.google.com/thumbnailid=1RA2W8xoomFUsPZp3U6XuTxZHfEWhMpmG&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;
* Breadboard&lt;br /&gt;
* Cassette mechanism with motor and tapehead (taking apart the ByronStatics player works well)&lt;br /&gt;
* 4 crocodile clip cables to make connections to the tape head and tape motor&lt;br /&gt;
* Additional alligator clips if necessary to splice wires&lt;br /&gt;
* Resistors: 100Ω (x4), 10kΩ (x3),  22kΩ, 105kΩ, 160 kΩ&lt;br /&gt;
* Unpolarized Capacitors: 1nF, 10nF, 47nF (x3)&lt;br /&gt;
* Polarized Capacitors: 4.7uF, 1uF, 10uF, 68uF&lt;br /&gt;
* LM4562 audio op-amp&lt;br /&gt;
* 2SC1815 audio transistor&lt;br /&gt;
* DC voltage supply capable of supplying +15V,  -15V, +3.3V, and +1.6V (may vary depending on motor)&lt;br /&gt;
* Function generator for diagnostic purposes with BNC splitter &amp;amp; cable&lt;br /&gt;
* Oscilloscope with probe&lt;br /&gt;
* A collection of wires&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=1oknIsrX-gGvHeeHfbGLSw5kr5TBqaAEb transistor_characterization - Oliver Licht.png]&lt;br /&gt;
* [https://drive.google.com/open?id=18HZ-GOd_GGsYu8sidNzmSp5152HHWC84 frequency_response - Oliver Licht.png]&lt;br /&gt;
* [https://drive.google.com/open?id=1bsJ_zhNUfImg0eh99g1N8EvBLta4RUir LM4562_pinout - Oliver Licht.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=Test cassette motor power requirements.&lt;br /&gt;
Open the case of the cassette player you will be using, and measure the voltage across the two pins labeled MO+ &amp;amp; MO- while it is operating. For the ByronStatics cassette player, this should be about 1.6V. This is the voltage you will use to drive the motor.|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Harvest the necessary physical components.&lt;br /&gt;
Taking off the back of the cassette player, desolder the connectors for the tape head, the motor, and the switch. You also might have to desolder some of the other connections to remove the PCB from the case. Our goal is to remove the cassette mechanism, which should include the tape head, tape motor, and a switch connected to the play button.|src=15MmB001g8dXzqvUs_mCFNwBm_c19Pq-6|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Wire up the motor. &lt;br /&gt;
With alligator clips, connect the negative end of the +1.6V power supply to the motor, and connect the positive end to one of the wires on the cassette chassis switch. Connect the other end of the switch to the positive end of the motor. Now, when the play button is pushed down, the motor should get power and begin to turn. I chose to use a separate external switch for the motor power, but the choice is up to you.|show=none|src=none}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Testing the preamplification common emitter amplifier circuit (recommended but not required).&lt;br /&gt;
The first circuit we will build for our project will pre-amplify the signal from the tape head. To ensure that our signal doesn’t get cut off, we will first verify that our transistor is at a linear operating point. To begin, construct the circuit depicted in the diagram for this step using a 2SC1815 NPN audio transistor and the relevant resistors. First, measure the voltage between R1 and R2. It should be approximately 0.57V. To verify that our transistor is at a linear operating point, we will output a 1V peak-to-peak sine wave from the function generator at 1kHz. Connect this function generator output to the circuit, with the positive connection between R_1 &amp;amp; R_2, and the negative connection to ground. Using a splitter, connect the same signal from the function generator output to CH1 on the oscilloscope. Connect the CH2 input to the oscilloscope between the transistor &amp;amp; R_C using an oscilloscope probe. From here, navigate to the acquire menu on the oscilloscope, and choose XY timebase mode. You should see an output similar to the transistor_characterization.png in the supporting files. If your curve doesn’t show the same horizontal range, you can adjust the amplitude of the sine wave, but it should not exceed 4V. Using the cursors, verify that the voltage you measured between R_1 &amp;amp; R_2 is in the sloped range of the plot. If this is the case, the circuit should amplify audio signals properly!|src=17CuuCunReHVjI7VODLJqMBR2nZ6q6PHb|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Construct the remainder of the common emitter amplifier circuit. &lt;br /&gt;
Building on the circuit from the previous step, add the capacitors &amp;amp; connect the input to the tape head to create the full common-emitter amplifier circuit. At this point, you can test a cassette tape, measuring the output with an oscilloscope probe. The signal may look noisy, but as long as it’s in a detectable range on the order of about 10 mV peak-to-peak, the circuit should be working properly.|src=1Us7LvXYF3Ggp2QeRbJFU4caTbcN1M76e|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Build an inverting amplifier. &lt;br /&gt;
Here, we construct the next stage of our circuit, the inverting amplifier. Construct the circuit below with the relevant resistors &amp;amp; capacitors and an LM4562 op-amp. Ensure that pins 8 and 4 (V+ &amp;amp; V- rails) of the op-amp are at +15V and -15V respectively. I used pin 1 for the output and pins 2 &amp;amp; 3 for the inverting &amp;amp; non-inverting inputs respectively. These pins come from the op-amp datasheet, with the pinout attached in supporting files. If using a different op-amp, ensure that you consult the datasheet for the right pins. After constructing this circuit, you can connect the output from the first common-emitter amplifier stage to the input, and test the output with an amplified speaker. It’s a good idea to start with the speaker at a minimum volume, then progressively increase until you hear sound.|src=1Xs-Zr-JklNGW66YozOdskTRfoRkIRJry|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Create and Characterize an RC equalization circuit. &lt;br /&gt;
Using the 160kΩ resistor and the 1 nF capacitor, build the following high-pass filter circuit. The audio output will be connected to the resistor, but to test the filter, you can connect a function generator to the input, and an oscilloscope across the capacitor (this part is also optional). With a 5V peak-to-peak sine wave, start at a 20 Hz signal and gradually increase the frequency. The 20 Hz signal should be close to the full 5V peak-to-peak, which should drop to about 1V by 500 Hz. Up to 20000 Hz, the output should decrease further to about 0.1V. Attached in the supporting files is a frequency response curve for this circuit, which you could replicate by plotting 1-(Vout/Vin) against the frequency. We characterize the corresponding low-pass filter instead of the high-pass filter to avoid creating a ground loop by measuring the voltage across the resistor. Keeping the capacitor between the resistor and ground also helps to reduce noise from the ground connection.|src=1-IOoXGpSU1f-1zzcLDgF-TyBQrkQdZWz|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Connect the different functional blocks. &lt;br /&gt;
At this point, we’re almost done! Following the functional diagram below, connect the tape head to the common emitter amplifier, connect the common emitter amplifier output to the inverting amplifier, connect the common emitter amplifier to the RC high pass filter, and connect your amplified speaker across the final 160 kΩ resistor! One final step we will take to reduce circuit noise is to connect 47nF capacitors between the voltage rails (+15V, -15V, and +3.3V) and ground. The +1.6V rail only powers the motor, so noise from this rail does not affect sound quality. |src=1By7ZcAC9ibNPZtFLdoIid-9dIYUd-5o1|show=img}}&lt;br /&gt;
{{#widget:ProjectStep|inst=Test the Output! &lt;br /&gt;
With our circuit fully constructed, pick your favorite cassette, push the play button on the cassette chassis to bring the playback head into contact with the tape, turn on the power supplies, and switch on the speaker and the cassette motor. |show=none|src=none}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[[Category:Soldering]]&lt;br /&gt;
[[Category:Cassette Making]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8477</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=8477"/>
		<updated>2025-02-16T21:40:57Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;` : `&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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8476</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=8476"/>
		<updated>2025-02-16T21:37:25Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;` : `&amp;lt;img src=&amp;quot;https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.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;` : &#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>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Category:Machine_Shop_Tools&amp;diff=8440</id>
		<title>Category:Machine Shop Tools</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Category:Machine_Shop_Tools&amp;diff=8440"/>
		<updated>2025-02-14T19:31:11Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Machine Shop Tools}}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Category:Makerspace_Tools&amp;diff=8439</id>
		<title>Category:Makerspace Tools</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Category:Makerspace_Tools&amp;diff=8439"/>
		<updated>2025-02-14T19:30:00Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are some of the tools that can be found in the Class of 1969 Makerspace, but it is not comprehensive. Stop in to find out exactly what we have in stock.{{DISPLAYTITLE:Makerspace Tools}}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Category:Wood_Shop_Tools&amp;diff=8438</id>
		<title>Category:Wood Shop Tools</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Category:Wood_Shop_Tools&amp;diff=8438"/>
		<updated>2025-02-14T19:29:10Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Wood Shop Tools}}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8422</id>
		<title>Spaces</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8422"/>
		<updated>2025-02-13T23:57:23Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Makerspace Spaces}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;Are you hoping to make something on campus? Here&#039;s a listing of all the places on campus that can help you out! All Makerspace locations are in the basement of Anderson Hall.&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;imagemap&amp;gt; File:makerspace_map.png|Subtitle of Image Map makerspace_map.png&lt;br /&gt;
rect 34 26 338 132 [[Spaces_New#Class_Of_1969_Makerspace|Central hub for your making needs on Carleton Campus]]&lt;br /&gt;
rect 108 186 236 492 [[Spaces_New#Makerspace_Repair_Lair|Contains bike repair cart, sewing machines, and many reusable treasures]]&lt;br /&gt;
rect 554 554 894 706 [[Spaces_New#Makerspace_Instrument_Shop|This space contains all of the higher precision tools used for STEM department research]]&lt;br /&gt;
rect 714 388 902 544 [[Spaces_New#Makerspace_Woodshop|Wood Shop]]&lt;br /&gt;
rect 718 2 898 386 [[Spaces_New#Makerspace_Machine_Shop|General purpose machine shop for student use]]&lt;br /&gt;
&amp;lt;/imagemap&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0f0f0; padding: 10px; width: 295px; border-radius: 10px;box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.2);&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;strong&amp;gt;Key&amp;lt;/strong&amp;gt;&amp;lt;ul style=&amp;quot;list-style-type: none; padding: 0;&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: green;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; No prerequisites to visit/use&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: yellow;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; Training required before use&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: red;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; Supervision required during use&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Class Of 1969 Makerspace&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
Central hub for all making on the Carleton College campus. This is the central hub for your making needs on campus. Have an idea and don&#039;t know where to start? Stop in and we&#039;ll help get you started! Want to learn a skill, but don&#039;t have a project in mind? We can help you with a variety of kits and brainstorming tools!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 028 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Button badge small.png|link=GALLERY|alt=Blue &amp;quot;button pressing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Cassette badge small.png|link=GALLERY|alt=Yellow &amp;quot;cassette making icon&amp;quot;|frameless]]&lt;br /&gt;
[[File:Crafting badge_small.png|link=GALLERY|alt=Brown &amp;quot;crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Graphic badge small.png|link=GALLERY|alt=Indigo &amp;quot;graphic design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Printing badge small.png|link=GALLERY|alt=Purple &amp;quot;3d printing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Programming badge small.png|link=GALLERY|alt=Green &amp;quot;programming&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Repair Lair&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
The Makerspace Repair Lair is located in the hallway across from the Makerspace. It is open after hours. It contains the Bike Repair cart, a sewing machine, scrap fabric, and many reusable treasures sourced from around campus.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 029 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Anytime!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Crafting_badge_small.png|link=GALLERY|alt=Brown &amp;quot;Crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Woodshop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms woodshop.jpg|alt=A view of the inside of the Woodshop|thumb]]&lt;br /&gt;
The Makerspace Woodshop is a general purpose carpentry shop available for general student use. We have a limited supply of materials available to for use, after filing out a project proposal. The space contains a variety of saws (table, panel, band, battery, miller), drill presses, jointers, nail guns, and sanders.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 037 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Woodworking badge small.png|link=GALLERY|alt=Blue &amp;quot;woodworking&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Instrument Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms instrumentshop.jpg|alt=A view of the inside of the Instrument Shop|thumb]]&lt;br /&gt;
This is the Scientific Instrument production shop for Carleton College. This shop contains all of the higher precision tools used to make apparatus for the STEM department research labs. This space also contains a student-accessible welding studio, CNC plasma cutter, sheet metal sheer, and press brake, as well as a dermestid beetle colony.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 049 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Machine Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 133016630.jpg|alt=A view of the inside of the Machine Shop|thumb]]&lt;br /&gt;
General purpose machine shop for student use. The Build Spot Student Machine Shop has a full complement of precision machining equipment suitable for working with a variety of metals and plastics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 039 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8421</id>
		<title>Spaces</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8421"/>
		<updated>2025-02-13T23:56:23Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Makerspace Spaces}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;Are you hoping to make something on campus? Here&#039;s a listing of all the places on campus that can help you out! All Makerspace locations are in the basement of Anderson Hall.&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;imagemap&amp;gt; File:makerspace_map.png|Subtitle of Image Map makerspace_map.png&lt;br /&gt;
rect 34 26 338 132 [[Spaces_New#Class_Of_1969_Makerspace|Central hub for your making needs on Carleton Campus]]&lt;br /&gt;
rect 108 186 236 492 [[Spaces_New#Makerspace_Repair_Lair|Contains bike repair cart, sewing machines, and many reusable treasures]]&lt;br /&gt;
rect 554 554 894 706 [[Spaces_New#Makerspace_Instrument_Shop|This space contains all of the higher precision tools used for STEM department research]]&lt;br /&gt;
rect 714 388 902 544 [[Spaces_New#Makerspace_Woodshop|Wood Shop]]&lt;br /&gt;
rect 718 2 898 386 [[Spaces_New#Makerspace_Machine_Shop|General purpose machine shop for student use]]&lt;br /&gt;
&amp;lt;/imagemap&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0f0f0; padding: 10px; width: 295px; border-radius: 10px;box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.2);&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;strong&amp;gt;Key&amp;lt;/strong&amp;gt;&amp;lt;ul style=&amp;quot;list-style-type: none; padding: 0;&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: green;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; No prerequisites to visit/use&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: yellow;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; Training required before use&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: red;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; Supervision required during use&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Class Of 1969 Makerspace&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
Central hub for all making on the Carleton College campus. This is the central hub for your making needs on campus. Have an idea and don&#039;t know where to start? Stop in and we&#039;ll help get you started! Want to learn a skill, but don&#039;t have a project in mind? We can help you with a variety of kits and brainstorming tools!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 028 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Button badge small.png|link=GALLERY|alt=Blue &amp;quot;button pressing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Cassette badge small.png|link=GALLERY|alt=Yellow &amp;quot;cassette making icon&amp;quot;|frameless]]&lt;br /&gt;
[[File:Crafting badge_small.png|link=GALLERY|alt=Brown &amp;quot;crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Graphic badge small.png|link=GALLERY|alt=Indigo &amp;quot;graphic design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Printing badge small.png|link=GALLERY|alt=Purple &amp;quot;3d printing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Programming badge small.png|link=GALLERY|alt=Green &amp;quot;programming&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Repair Lair&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
The Makerspace Repair Lair is located in the hallway across from the Makerspace. It is open after hours. It contains the Bike Repair cart, a sewing machine, scrap fabric, and many reusable treasures sourced from around campus.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 029 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Anytime!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Crafting_badge_small.png|link=GALLERY|alt=Brown &amp;quot;Crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Woodshop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms woodshop.jpg|alt=A view of the inside of the Woodshop|thumb]]&lt;br /&gt;
The Makerspace Woodshop is a general purpose carpentry shop available for general student use. We have a limited supply of materials available to for use, after filing out a project proposal. The space contains a variety of saws (table, panel, band, battery, miller), drill presses, jointers, nail guns, and sanders.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 037 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[Tools New#Wood Shop Tools Gallery|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Woodworking badge small.png|link=GALLERY|alt=Blue &amp;quot;woodworking&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Instrument Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms instrumentshop.jpg|alt=A view of the inside of the Instrument Shop|thumb]]&lt;br /&gt;
This is the Scientific Instrument production shop for Carleton College. This shop contains all of the higher precision tools used to make apparatus for the STEM department research labs. This space also contains a student-accessible welding studio, CNC plasma cutter, sheet metal sheer, and press brake, as well as a dermestid beetle colony.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 049 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Machine Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 133016630.jpg|alt=A view of the inside of the Machine Shop|thumb]]&lt;br /&gt;
General purpose machine shop for student use. The Build Spot Student Machine Shop has a full complement of precision machining equipment suitable for working with a variety of metals and plastics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 039 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[TOOLS|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=GALLERY|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Laser badge small.png|link=GALLERY|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=GALLERY|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=GALLERY|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8420</id>
		<title>Spaces</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Spaces&amp;diff=8420"/>
		<updated>2025-02-13T23:51:42Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:Makerspace Spaces}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;Are you hoping to make something on campus? Here&#039;s a listing of all the places on campus that can help you out! All Makerspace locations are in the basement of Anderson Hall.&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;imagemap&amp;gt; File:makerspace_map.png|Subtitle of Image Map makerspace_map.png&lt;br /&gt;
rect 34 26 338 132 [[Spaces_New#Class_Of_1969_Makerspace|Central hub for your making needs on Carleton Campus]]&lt;br /&gt;
rect 108 186 236 492 [[Spaces_New#Makerspace_Repair_Lair|Contains bike repair cart, sewing machines, and many reusable treasures]]&lt;br /&gt;
rect 554 554 894 706 [[Spaces_New#Makerspace_Instrument_Shop|This space contains all of the higher precision tools used for STEM department research]]&lt;br /&gt;
rect 714 388 902 544 [[Spaces_New#Makerspace_Woodshop|Wood Shop]]&lt;br /&gt;
rect 718 2 898 386 [[Spaces_New#Makerspace_Machine_Shop|General purpose machine shop for student use]]&lt;br /&gt;
&amp;lt;/imagemap&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f0f0f0; padding: 10px; width: 295px; border-radius: 10px;box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.2);&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;strong&amp;gt;Key&amp;lt;/strong&amp;gt;&amp;lt;ul style=&amp;quot;list-style-type: none; padding: 0;&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: green;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; No prerequisites to visit/use&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: yellow;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; Training required before use&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;&amp;lt;span style=&amp;quot;display: inline-block; width: 20px; height: 20px; background-color: red;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt; Supervision required during use&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Class Of 1969 Makerspace&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
Central hub for all making on the Carleton College campus. This is the central hub for your making needs on campus. Have an idea and don&#039;t know where to start? Stop in and we&#039;ll help get you started! Want to learn a skill, but don&#039;t have a project in mind? We can help you with a variety of kits and brainstorming tools!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 028 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[Tools New#Makerspace Tools Gallery|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Button badge small.png|link=GALLERY|alt=Blue &amp;quot;button pressing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Cassette badge small.png|link=GALLERY|alt=Yellow &amp;quot;cassette making icon&amp;quot;|frameless]]&lt;br /&gt;
[[File:Crafting badge_small.png|link=GALLERY|alt=Brown &amp;quot;crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Graphic badge small.png|link=GALLERY|alt=Indigo &amp;quot;graphic design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=GALLERY|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=GALLERY|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Printing badge small.png|link=GALLERY|alt=Purple &amp;quot;3d printing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Programming badge small.png|link=GALLERY|alt=Green &amp;quot;programming&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=GALLERY|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=GALLERY|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=GALLERY|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Repair Lair&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 132906251.jpg|alt=A view of the inside of the  Class 1969 Makerspace|thumb]]&lt;br /&gt;
The Makerspace Repair Lair is located in the hallway across from the Makerspace. It is open after hours. It contains the Bike Repair cart, a sewing machine, scrap fabric, and many reusable treasures sourced from around campus.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 029 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Anytime!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[Tools New#Tools Gallery|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Crafting_badge_small.png|link=Category:Projects|alt=Brown &amp;quot;Crafting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Handsewing badge small.png|link=Category:Projects|alt=Purple &amp;quot;handsewing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Textile badge small.png|link=Category:Projects|alt=Green &amp;quot;textiles&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Woodshop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms woodshop.jpg|alt=A view of the inside of the Woodshop|thumb]]&lt;br /&gt;
The Makerspace Woodshop is a general purpose carpentry shop available for general student use. We have a limited supply of materials available to for use, after filing out a project proposal. The space contains a variety of saws (table, panel, band, battery, miller), drill presses, jointers, nail guns, and sanders.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 037 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[Tools New#Wood Shop Tools Gallery|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=Category:Projects|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=Category:Projects|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=Category:Projects|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=Category:Projects|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Woodworking badge small.png|link=Category:Projects|alt=Blue &amp;quot;woodworking&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Instrument Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:Ms instrumentshop.jpg|alt=A view of the inside of the Instrument Shop|thumb]]&lt;br /&gt;
This is the Scientific Instrument production shop for Carleton College. This shop contains all of the higher precision tools used to make apparatus for the STEM department research labs. This space also contains a student-accessible welding studio, CNC plasma cutter, sheet metal sheer, and press brake, as well as a dermestid beetle colony.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 049 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[Tools New#Tools Gallery|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Laser badge small.png|link=Category:Projects|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=Category:Projects|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Modeling badge small.png|link=Category:Projects|alt=Yellow &amp;quot;3d modeling&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=Category:Projects|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=Category:Projects|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=Category:Projects|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Makerspace Machine Shop&#039;&#039;&#039; ==&lt;br /&gt;
[[File:PXL 20230710 133016630.jpg|alt=A view of the inside of the Machine Shop|thumb]]&lt;br /&gt;
General purpose machine shop for student use. The Build Spot Student Machine Shop has a full complement of precision machining equipment suitable for working with a variety of metals and plastics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Location:&#039;&#039;&#039; Anderson Hall 039 (Basement)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hours:&#039;&#039;&#039; Daily, 1-6PM&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tools&#039;&#039;&#039;: &amp;lt;u&amp;gt;[[Tools New#Machine Shop Tools Gallery|Link to Tools Page]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Airbrushing badge small.png|link=Category:Projects|alt=Green &amp;quot;airbrushing&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Laser badge small.png|link=Category:Projects|alt=Gray &amp;quot;laser cutting&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Machining badge small.png|link=Category:Projects|alt=Pink &amp;quot;machining&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Soldering badge small.png|link=Category:Projects|alt=Orange &amp;quot;soldering&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Technical badge small.png|link=Category:Projects|alt=Green &amp;quot;technical design&amp;quot; icon|frameless]]&lt;br /&gt;
[[File:Welding badge small.png|link=Category:Projects|alt=Indigo &amp;quot;welding&amp;quot; icon|frameless]]&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8413</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=8413"/>
		<updated>2025-02-13T14:55:02Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
.gallery-container {&lt;br /&gt;
    display: grid;&lt;br /&gt;
    grid-template-columns: repeat(4, 1fr); &lt;br /&gt;
    gap: 10px; &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;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%;  /* Adjust width to be responsive */&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;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.css&amp;diff=8412</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=8412"/>
		<updated>2025-02-13T14:50:54Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
.gallery-container {&lt;br /&gt;
    display: grid;&lt;br /&gt;
    grid-template-columns: repeat(4, 1fr); &lt;br /&gt;
    gap: 10px; &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;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
.gallery-item {&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.gallery-item img {&lt;br /&gt;
    width: 100%;  /* Adjust width to be responsive */&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;
.gallery-caption {&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    font-size: 14px;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8317</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=8317"/>
		<updated>2025-02-10T16:36:49Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
$(document).ready(function () {&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;
    $(&amp;quot;.carousel-count&amp;quot;).text(`Total Images: ${totalItems}`);&lt;br /&gt;
    // Hide all items and show the first one by default&lt;br /&gt;
    $carouselItems.hide();&lt;br /&gt;
    $carouselItems.eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    // Create the Next and Previous buttons &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;
&lt;br /&gt;
    // add buttons to the carousel container&lt;br /&gt;
    $(&amp;quot;.carousel-container&amp;quot;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;lt; totalItems - 1) {&lt;br /&gt;
            currentIndex++;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = 0; // Loop back to the first item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Previous button click&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;gt; 0) {&lt;br /&gt;
            currentIndex--;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = totalItems - 1; // Loop back to the last item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to update the carousel view&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide(); // Hide all items&lt;br /&gt;
        $carouselItems.eq(currentIndex).show(); // Show the active one&lt;br /&gt;
    }&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;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8316</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=8316"/>
		<updated>2025-02-10T16:27:20Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
$(document).ready(function () {&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;
    $(&amp;quot;.carousel-count&amp;quot;).text(`Total Images: ${totalItems}`);&lt;br /&gt;
    // Hide all items and show the first one by default&lt;br /&gt;
    $carouselItems.hide();&lt;br /&gt;
    $carouselItems.eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    // Create the Next and Previous buttons &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;
&lt;br /&gt;
    // add buttons to the carousel container&lt;br /&gt;
    $(&amp;quot;.carousel-container&amp;quot;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;lt; totalItems - 1) {&lt;br /&gt;
            currentIndex++;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = 0; // Loop back to the first item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Previous button click&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;gt; 0) {&lt;br /&gt;
            currentIndex--;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = totalItems - 1; // Loop back to the last item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to update the carousel view&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide(); // Hide all items&lt;br /&gt;
        $carouselItems.eq(currentIndex).show(); // Show the active one&lt;br /&gt;
    }&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;);  // Get the gallery container&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;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;
        // Function to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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;
                                // Add the gallery item&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 or not needed&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 to generate a gallery item&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;
        // Initially, load all projects (Projects category)&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&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;);  // Get the gallery container&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 to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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 to generate a gallery item&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;
        // Initially, load all tools (Tools category)&lt;br /&gt;
        loadGallery(&amp;quot;Tools&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8311</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=8311"/>
		<updated>2025-02-10T15:48:03Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Undo revision 8310 by EvaC (talk)&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;
\\ Homepage Carousel&lt;br /&gt;
$(document).ready(function () {&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;
    $(&amp;quot;.carousel-count&amp;quot;).text(`Total Images: ${totalItems}`);&lt;br /&gt;
    // Hide all items and show the first one by default&lt;br /&gt;
    $carouselItems.hide();&lt;br /&gt;
    $carouselItems.eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    // Create the Next and Previous buttons &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;
&lt;br /&gt;
    // add buttons to the carousel container&lt;br /&gt;
    $(&amp;quot;.carousel-container&amp;quot;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;lt; totalItems - 1) {&lt;br /&gt;
            currentIndex++;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = 0; // Loop back to the first item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Previous button click&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;gt; 0) {&lt;br /&gt;
            currentIndex--;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = totalItems - 1; // Loop back to the last item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to update the carousel view&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide(); // Hide all items&lt;br /&gt;
        $carouselItems.eq(currentIndex).show(); // Show the active one&lt;br /&gt;
    }&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;);  // Get the gallery container&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;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;
        // Function to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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;
                                // Add the gallery item&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 or not needed&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 to generate a gallery item&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;
        // Initially, load all projects (Projects category)&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&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;);  // Get the gallery container&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 to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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 to generate a gallery item&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;
        // Initially, load all tools (Tools category)&lt;br /&gt;
        loadGallery(&amp;quot;Tools&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8310</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=8310"/>
		<updated>2025-02-10T15:42:31Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
\\ Homepage Carousel&lt;br /&gt;
$(document).ready(function () {&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;
    $(&amp;quot;.carousel-count&amp;quot;).text(`Total Images: ${totalItems}`);&lt;br /&gt;
    // Hide all items and show the first one by default&lt;br /&gt;
    $carouselItems.hide();&lt;br /&gt;
    $carouselItems.eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    // Create the Next and Previous buttons &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;
&lt;br /&gt;
    // add buttons to the carousel container&lt;br /&gt;
    $(&amp;quot;.carousel-container&amp;quot;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;lt; totalItems - 1) {&lt;br /&gt;
            currentIndex++;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = 0; // Loop back to the first item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Previous button click&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;gt; 0) {&lt;br /&gt;
            currentIndex--;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = totalItems - 1; // Loop back to the last item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to update the carousel view&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide(); // Hide all items&lt;br /&gt;
        $carouselItems.eq(currentIndex).show(); // Show the active one&lt;br /&gt;
    }&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; &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;
        // 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;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;
                            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;
                    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;
        // Load all projects by default&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);  // Load gallery based on selected category&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;  &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;);  // Show loading message&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;
                        var fileMatch = content.match(/\[\[File:([^|\]]+)/);&lt;br /&gt;
                        if (fileMatch) {&lt;br /&gt;
                            var fileName = fileMatch[1].trim();&lt;br /&gt;
&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;
                                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;
                    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);  // Load gallery based on selected category&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=Tools&amp;diff=8308</id>
		<title>Tools</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=Tools&amp;diff=8308"/>
		<updated>2025-02-10T15:09:30Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Created page with &amp;quot;&amp;lt;div id=&amp;quot;tools-gallery&amp;quot;&amp;gt;     &amp;lt;p&amp;gt;Loading gallery...&amp;lt;/p&amp;gt; &amp;lt;/div&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div id=&amp;quot;tools-gallery&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;Loading gallery...&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=8307</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://makerspace.cc/wiki/index.php?title=MediaWiki:Sidebar&amp;diff=8307"/>
		<updated>2025-02-10T15:09:12Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** Home_New|HOME&lt;br /&gt;
** Spaces_New|SPACES&lt;br /&gt;
** TOOLS|TOOLS&lt;br /&gt;
** Category:Tutorials|TUTORIALS&lt;br /&gt;
** Category:Projects|PROJECTS&lt;br /&gt;
** GALLERY|GALLERY&lt;br /&gt;
** https://forms.gle/nCtJcMaAw14R42PY8 | SUBMIT PROJECT&lt;br /&gt;
&amp;lt;!--** recentchanges-url|recentchanges--&amp;gt;&lt;br /&gt;
&amp;lt;!--** randompage-url|randompage--&amp;gt;&lt;br /&gt;
&amp;lt;!--** helppage|help-mediawiki--&amp;gt;&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8305</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=8305"/>
		<updated>2025-02-10T15:05:07Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
$(document).ready(function () {&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;
    $(&amp;quot;.carousel-count&amp;quot;).text(`Total Images: ${totalItems}`);&lt;br /&gt;
    // Hide all items and show the first one by default&lt;br /&gt;
    $carouselItems.hide();&lt;br /&gt;
    $carouselItems.eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    // Create the Next and Previous buttons &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;
&lt;br /&gt;
    // add buttons to the carousel container&lt;br /&gt;
    $(&amp;quot;.carousel-container&amp;quot;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;lt; totalItems - 1) {&lt;br /&gt;
            currentIndex++;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = 0; // Loop back to the first item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Previous button click&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;gt; 0) {&lt;br /&gt;
            currentIndex--;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = totalItems - 1; // Loop back to the last item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to update the carousel view&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide(); // Hide all items&lt;br /&gt;
        $carouselItems.eq(currentIndex).show(); // Show the active one&lt;br /&gt;
    }&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;);  // Get the gallery container&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;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;
        // Function to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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;
                                // Add the gallery item&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 or not needed&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 to generate a gallery item&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;
        // Initially, load all projects (Projects category)&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&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;);  // Get the gallery container&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 to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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 to generate a gallery item&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;
        // Initially, load all tools (Tools category)&lt;br /&gt;
        loadGallery(&amp;quot;Tools&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8274</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=8274"/>
		<updated>2025-02-10T01:10:32Z</updated>

		<summary type="html">&lt;p&gt;EvaC: &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;
$(document).ready(function () {&lt;br /&gt;
    // Add the category filter buttons before the gallery&lt;br /&gt;
    $(&amp;quot;#tool-gallery&amp;quot;).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;
    // Initially, show all galleries&lt;br /&gt;
    $(&amp;quot;#tool-gallery, #makerspace-gallery, #machineshop-gallery, #woodshop-gallery&amp;quot;).show();&lt;br /&gt;
&lt;br /&gt;
    // Filter logic when a button is clicked&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;
&lt;br /&gt;
        // Hide all galleries first&lt;br /&gt;
        $(&amp;quot;#tool-gallery, #makerspace-gallery, #machineshop-gallery, #woodshop-gallery&amp;quot;).hide();&lt;br /&gt;
&lt;br /&gt;
        // Show the appropriate gallery based on the selected category&lt;br /&gt;
        if (selectedCategory === &amp;quot;Tools&amp;quot;) {&lt;br /&gt;
            // Show all galleries when &amp;quot;Show All&amp;quot; is clicked&lt;br /&gt;
            $(&amp;quot;#tool-gallery, #makerspace-gallery, #machineshop-gallery, #woodshop-gallery&amp;quot;).show();&lt;br /&gt;
        } else if (selectedCategory === &amp;quot;Machine Shop Tools&amp;quot;) {&lt;br /&gt;
            // Show only Machine Shop Tools gallery&lt;br /&gt;
            $(&amp;quot;#machineshop-gallery&amp;quot;).show();&lt;br /&gt;
        } else if (selectedCategory === &amp;quot;Makerspace Tools&amp;quot;) {&lt;br /&gt;
            // Show only Makerspace Tools gallery&lt;br /&gt;
            $(&amp;quot;#makerspace-gallery&amp;quot;).show();&lt;br /&gt;
        } else if (selectedCategory === &amp;quot;Wood Shop Tools&amp;quot;) {&lt;br /&gt;
            // Show only Wood Shop Tools gallery&lt;br /&gt;
            $(&amp;quot;#woodshop-gallery&amp;quot;).show();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&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;
    $(&amp;quot;.carousel-count&amp;quot;).text(`Total Images: ${totalItems}`);&lt;br /&gt;
    // Hide all items and show the first one by default&lt;br /&gt;
    $carouselItems.hide();&lt;br /&gt;
    $carouselItems.eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    // Create the Next and Previous buttons &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;
&lt;br /&gt;
    // add buttons to the carousel container&lt;br /&gt;
    $(&amp;quot;.carousel-container&amp;quot;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;lt; totalItems - 1) {&lt;br /&gt;
            currentIndex++;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = 0; // Loop back to the first item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Previous button click&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;gt; 0) {&lt;br /&gt;
            currentIndex--;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = totalItems - 1; // Loop back to the last item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to update the carousel view&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide(); // Hide all items&lt;br /&gt;
        $carouselItems.eq(currentIndex).show(); // Show the active one&lt;br /&gt;
    }&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;);  // Get the gallery container&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;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;
        // Function to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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;
                                // Add the gallery item&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 or not needed&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 to generate a gallery item&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;
        // Initially, load all projects (Projects category)&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
	<entry>
		<id>https://makerspace.cc/wiki/index.php?title=MediaWiki:Common.js&amp;diff=8273</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=8273"/>
		<updated>2025-02-09T21:04:51Z</updated>

		<summary type="html">&lt;p&gt;EvaC: Undo revision 8272 by EvaC (talk)&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;
$(document).ready(function () {&lt;br /&gt;
    // Add the category filter buttons before the gallery&lt;br /&gt;
    $(&amp;quot;#tool-gallery&amp;quot;).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;
    // Initially, show all galleries&lt;br /&gt;
    $(&amp;quot;#tool-gallery, #makerspace-gallery, #machineshop-gallery, #woodshop-gallery&amp;quot;).show();&lt;br /&gt;
&lt;br /&gt;
    // Filter logic when a button is clicked&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;
&lt;br /&gt;
        // Hide all galleries first&lt;br /&gt;
        $(&amp;quot;#tool-gallery, #makerspace-gallery, #machineshop-gallery, #woodshop-gallery&amp;quot;).hide();&lt;br /&gt;
&lt;br /&gt;
        // Show the appropriate gallery based on the selected category&lt;br /&gt;
        if (selectedCategory === &amp;quot;Tools&amp;quot;) {&lt;br /&gt;
            // Show all galleries when &amp;quot;Show All&amp;quot; is clicked&lt;br /&gt;
            $(&amp;quot;#tool-gallery, #makerspace-gallery, #machineshop-gallery, #woodshop-gallery&amp;quot;).show();&lt;br /&gt;
        } else if (selectedCategory === &amp;quot;Machine Shop Tools&amp;quot;) {&lt;br /&gt;
            // Show only Machine Shop Tools gallery&lt;br /&gt;
            $(&amp;quot;#machineshop-gallery&amp;quot;).show();&lt;br /&gt;
        } else if (selectedCategory === &amp;quot;Makerspace Tools&amp;quot;) {&lt;br /&gt;
            // Show only Makerspace Tools gallery&lt;br /&gt;
            $(&amp;quot;#makerspace-gallery&amp;quot;).show();&lt;br /&gt;
        } else if (selectedCategory === &amp;quot;Wood Shop Tools&amp;quot;) {&lt;br /&gt;
            // Show only Wood Shop Tools gallery&lt;br /&gt;
            $(&amp;quot;#woodshop-gallery&amp;quot;).show();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function () {&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;
    $(&amp;quot;.carousel-count&amp;quot;).text(`Total Images: ${totalItems}`);&lt;br /&gt;
    // Hide all items and show the first one by default&lt;br /&gt;
    $carouselItems.hide();&lt;br /&gt;
    $carouselItems.eq(currentIndex).show();&lt;br /&gt;
&lt;br /&gt;
    // Create the Next and Previous buttons &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;
&lt;br /&gt;
    // add buttons to the carousel container&lt;br /&gt;
    $(&amp;quot;.carousel-container&amp;quot;).append($prevButton, $nextButton);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    $nextButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;lt; totalItems - 1) {&lt;br /&gt;
            currentIndex++;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = 0; // Loop back to the first item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Previous button click&lt;br /&gt;
    $prevButton.click(function () {&lt;br /&gt;
        if (currentIndex &amp;gt; 0) {&lt;br /&gt;
            currentIndex--;&lt;br /&gt;
        } else {&lt;br /&gt;
            currentIndex = totalItems - 1; // Loop back to the last item&lt;br /&gt;
        }&lt;br /&gt;
        updateCarousel();&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // Function to update the carousel view&lt;br /&gt;
    function updateCarousel() {&lt;br /&gt;
        $carouselItems.hide(); // Hide all items&lt;br /&gt;
        $carouselItems.eq(currentIndex).show(); // Show the active one&lt;br /&gt;
    }&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;);  // Get the gallery container&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;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;
        // Function to 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;);  // Show loading message&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,  // Limit the number of results (adjust as needed)&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 match = content.match(/img1=(https:\/\/[^\n|}%s]+)/);&lt;br /&gt;
                        &lt;br /&gt;
                        if (match) {&lt;br /&gt;
                            var imgUrl = match[1];&lt;br /&gt;
                            var pageUrl = mw.util.getUrl(page.title);&lt;br /&gt;
&lt;br /&gt;
                            galleryHtml += `&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;
                                        &amp;lt;img src=&amp;quot;${imgUrl}&amp;quot; alt=&amp;quot;${page.title}&amp;quot;&amp;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;${page.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;
                });&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;
        // Initially, load all projects (Projects category)&lt;br /&gt;
        loadGallery(&amp;quot;Projects&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Filter logic for buttons&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);  // Load gallery based on selected category&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
});&lt;/div&gt;</summary>
		<author><name>EvaC</name></author>
	</entry>
</feed>