Image Archive (w/ tags!)
This is the code ripped out my art gallery. Had to rework it a bit so it would work purely with javascript. Tried leaving the styling as bare as possible so you can customize it to your hearts content!
Head Back »This is the code ripped out my art gallery. Had to rework it a bit so it would work purely with javascript. Tried leaving the styling as bare as possible so you can customize it to your hearts content!
Head Back »Showing 0 of
Just copy and past the codes below. Also, I don't really care what people do with my code. Feel free to modify and claim it to be yours.
<div id="container">
<main>
<article>
<h1>Image Archive (w/ tags!)</h1>
<!-- Add your content here -->
</article>
<article>
<!-- Archive Start -->
<!-- Actually none of the other content matters. You just need everything here -->
<div id="archive_content"></div><!-- REQUIRED » Do not delete this element -->
<div id="archive_buttons">
<button onclick="showEm(3)">[3] Load More</button>
<button onclick="showEm(32)">[32] Load More</button>
<button onclick="showEm()">Load Everything!</button>
</div>
<p>Showing <span id="archive_counter">0</span> of <span id="archive_max"></span></p><!-- REQUIRED » Do not delete this element. You can change the text though -->
<hr>
<div id="archive_tags"></div><!-- REQUIRED » Do not delete this element -->
<button onclick="getChecked()">Filter em!</button>
<a href="?">Clear Filters</a>
<hr>
<!-- Archive End -->
</article>
</main>
<footer>
<!-- Feel free to remove the credit -->
Template created by <a href="https://stupied.net" target="_blank">stupied</a>
</footer>
</div>body{ padding:0;margin:0; }
#container {
max-width: 500px;
width: 98%;
margin: auto;
box-sizing: border-box;
padding: 1rem;
}
.archive-item {
display: block;
margin-bottom: 1rem;
border: 2px solid;
background-color: white;
box-shadow: 0.2rem 0.2rem;
transition: 0.2s;
break-inside: avoid;
}
.archive-item img{width: 100%; display: block;}
.archive-item-title {
font-weight: bolder;
font-family: var(--display-font);
font-size: 1.2rem;
padding: 0.5rem;
border-top: 1px solid;
border-bottom: 1px solid;
margin: 0;
}
.archive-item-desc { padding: 0 0.5rem; }
.archive-item-tags { padding: 0.5rem; }
.archive-item-tags button {
background-color: lightgray;
margin-right: 0.5rem;
margin-bottom: 0.5rem;
border-radius: 5px;
border: 0;
}
.hidden { display: none; }
#archive_buttons { margin-top: 1rem; }
#archive_tags { margin-bottom: 1rem; }
.archive-tag { display: inline-block; }const IMG_FOLDER = 'img'; // this is the folder your images are stored in - relative to the page location
const START = 3; // the amount shown when first loaded in
const ARCHIVE_TAGS = [
"tag-1",
"tag-2",
"tag-3"
]
const ARCHIVE_LIST = [
// Topmost part is the most recent.
{ "img": "hello-world.png" }, // This is all you need to write. This is relative to IMG_FOLDER.
{ "img": "/folder/2025.jpg" }, // You can put them into folders.
{
"img": "custom-title.png",
"title": "ヽ(✿゚▽゚)ノ", // Custom Title. Will override default title.
"desc": "This is an awesome description!", // Description of image. Will get enclose in a <p> tag.
"tags": "tag-1 tag-2" // used to filter your images.
},
{
"img": "moving.gif",
// you can add additional images.
"extra": [
"not-moving-1.png",
"/folder/not-moving-2.png"
],
},
// This is what it looks like with all optional items filled in!
{
"img": "final.png",
"title": "This is the final image!",
"desc": "Thank you for using my dumb ass scripts. I hope they're helpful in some way :D",
"extra": ["final-for-realzies.png"],
"tags": "tag-2 tag-3"
}
];
// ATTENTION - don't touch unless you know what you're doing
const TARGET = document.getElementById("archive_content");
const COUNTER_TARGET = document.getElementById("archive_counter");
var MAX = ARCHIVE_LIST.length;
var counter = 0;
document.getElementById('archive_max').textContent = MAX;
ARCHIVE_LIST.forEach(item => {
let result = document.createElement('div');
result.classList.add('archive-item');
result.classList.add('hidden');
result.dataset.tags = item.tags;
result.append(writeImage(item.img));
if (item.extra !== undefined)
item.extra.forEach(extra => { result.append(writeImage(extra)); });
// Info
let info = document.createElement('div');
let title = document.createElement('h2');
title.classList.add('archive-item-title');
title.textContent = getTitle(item);
info.append(title);
if (item.desc !== undefined) {
let desc = document.createElement('p');
desc.classList.add('archive-item-desc');
desc.textContent = item.desc;
info.append(desc);
}
result.append(info);
// Tags
if (item.tags !== undefined) {
let tags = document.createElement('div');
tags.classList.add('archive-item-tags');
let tags_arr = item.tags.split(' ');
tags_arr.forEach(tag => {
let button = document.createElement('button');
button.setAttribute('onclick', `getChecked('${tag}')`);
button.textContent = tag;
tags.append(button);
});
result.append(tags);
}
TARGET.append(result);
});
function getTitle(e) {
if (e.title !== undefined) {
return e.title;
} else {
let title = e.img;
title = title.split("/");
title = title[title.length - 1];
title = title.slice(0, title.indexOf('.'))
title = title.replaceAll("-", " ");
return title;
}
}
function writeImage(item) {
// Link
let link = IMG_FOLDER + '/' + item;
let anchor = document.createElement('a');
anchor.href = link;
// Image
let img = document.createElement('img');
img.dataset.src = link;
img.src = '#';
img.alt = item;
anchor.append(img);
return anchor;
}
const TAGS_TARGET = document.getElementById('archive_tags');
ARCHIVE_TAGS.forEach(tag => {
let label = document.createElement('label');
label.classList.add('archive-tag')
label.for = tag;
let input = document.createElement('input');
input.type = 'checkbox';
input.name = 'tags';
input.value = tag;
input.name = tag;
input.id = tag;
label.append(input);
let span = document.createElement('span');
span.textContent = tag;
label.append(span);
TAGS_TARGET.append(label);
});
var items = TARGET.querySelectorAll('& > *');
var query = window.location.search.replace("?","");
var separator = '+';
if (query === "") showEm(START);
else sortEm();
function getChecked(value) {
let result = "?";
if (value === undefined) {
// if clicking the filter button
let checked = document.querySelectorAll('input:checked');
checked.forEach(check => {
result += check.value + separator;
});
result = result.slice(0, result.length - 1)
} else {
// if clicking the tag from item
if (query !== "") {
split = query.split(separator);
if (split.includes(value)) return;
split.forEach(tag => {
result += tag + separator;
});
}
result += value;
}
window.location.href = result;
}
function sortEm() {
let tags = new Set(query.split(separator));
tags = Array.from(tags)
let counter = 0;
tags.forEach(tag => {
if (e = document.getElementById(tag))
e.checked = true;
});
for (let i = 0; i < items.length; i++) {
if (items[i].dataset.tags === undefined) return;
let data = items[i].dataset.tags.split(" ");
let mixed = tags.concat(data);
let goal = mixed.length - tags.length;
let set = new Set(mixed).size;
if (set === goal) {
counter++;
items[i].classList.add("all-tags");
} else {
items[i].remove();
}
}
MAX = counter;
items = TARGET.querySelectorAll('& > *');
document.getElementById('archive_max').textContent = counter;
showEm(START);
}
function showEm (increment) {
if (increment === undefined )
increment = MAX;
let next = counter + increment;
let prev = counter;
if ( next < MAX ) {
counter = next;
} else {
counter = MAX;
document.getElementById("archive_buttons").remove()
}
for (let i = prev; i < counter; i++)
showItem(i);
COUNTER_TARGET.textContent = counter;
}
function showItem(i) {
items[i].classList.remove('hidden');
let thumb = items[i].querySelectorAll('img');
thumb.forEach(img => {
img.src = img.dataset.src;
});
}Just right click and download because I'm too lazy to code it properly right now lol