'use strict'; const _GALLERY = { path: '', masonry: 0, masonry_direction: 'vertical', images_per_page: 24, max_width: '50vw', max_height: '50vw', min_width: '180px', min_height: '180px', grid_gap: 24, max_pagination_links: 9, grid_card_layout: ['image','title','tags'], view_card_layout: ['image','title','tags','download','description'], // Language: Find_tags: 'Find tag(s): ', Search_mode: 'Search mode: ', Search_OR: 'OR', Search_AND: 'AND', Avoid_tags: 'Avoid tag(s): ', Showing_results: ['Showing results ',' of '], See_all_tags: 'See all tags', Prev_page: 'Prev', Page: 'Page: ', Next_page: 'Next', Next_result: 'Next →', Return_to_gallery: 'Gallery', Prev_result: '← Prev', Permalink: 'View', Download: 'Download', No_description: '

No description.

', // codestuffing, do not eat: archive_text: document.querySelector('[name=archive]') .innerHTML, gallery: document.querySelector('[name=gallery]'), archive: [], // Objects do_grid: true, // .grid or .view? curPage: 1, // current page find: [], // tags to find avoid: [], // tags to avoid s_mode: 'OR', // inclusive 'OR' / exclusive 'AND'? allTags: [], // for filtering } if (window.GALLERY) for (let key in GALLERY) { _GALLERY[key] = GALLERY[key]; } //=====================================// /* INIT */ //=====================================// getQueries(); parse(); //=====================================// /* GRID */ //=====================================// if (_GALLERY.do_grid) { sessionStorage['do_gallery-returnLink'] = location.search || ''; sessionStorage['do-gallery-find'] = _GALLERY.find.join(','); sessionStorage['do-gallery-avoid'] = _GALLERY.avoid.join(','); const grid = document.createElement('div'); grid.classList.add('grid',_GALLERY.masonry?_GALLERY.masonry_direction:'nomasonry'); const searchForm = makeSearchForm(); const res = document.createElement('p'); res.classList.add('results'); res.id='results'; function resizeGridItem(item) { const grid = _GALLERY.gallery; const rowGap = _GALLERY.grid_gap; if (_GALLERY.masonry_direction==='vertical'||_GALLERY.masonry_direction==='both') { const rowSpan = Math.ceil( (item.scrollHeight + rowGap) / (1 + rowGap) ); item.style.gridRowEnd = "span " + rowSpan; } if (_GALLERY.masonry_direction==='both') { const colSpan = Math.ceil( (item.scrollWidth + rowGap) / (1 + rowGap) ); item.style.gridColumnEnd = "span " + colSpan; } } function resizeAllGridItems(){ _GALLERY.results.forEach(card => { resizeGridItem(card); }); } if (_GALLERY.masonry) addEventListener("resize", resizeAllGridItems); _GALLERY.results = []; function createGrid(arr) { /* GRID CSS */ const style_el = document.createElement('style'); style_el.textContent = ` .grid { display: ${_GALLERY.masonry&&_GALLERY.masonry_direction!=='horizontal' ? 'grid':'flex'}; flex-wrap: wrap; grid-gap: ${_GALLERY.grid_gap}px; ${_GALLERY.masonry?'':'/*'} grid-auto-rows: ${_GALLERY.masonry_direction==='vertical'||_GALLERY.masonry_direction==='both'?'1px':'unset'}; grid-template-columns: ${_GALLERY.masonry_direction==='horizontal'||_GALLERY.masonry_direction==='both'?'repeat(auto-fill, 1px)':'repeat(auto-fill,'+_GALLERY.min_width+')'}; ${_GALLERY.masonry?'':'*/'} ${_GALLERY.masonry&&_GALLERY.masonry_direction!=='vertical' ? '/*':''} grid-template-columns: repeat(auto-fill, minmax(${_GALLERY.min_width},1fr)); ${_GALLERY.masonry&&_GALLERY.masonry_direction!=='vertical' ? '*/':''} } .grid img, .grid video, .grid iframe { box-sizing: border-box; max-width: 100%; ${!_GALLERY.masonry||_GALLERY.masonry_direction==='vertical'?'/*':''} max-width: ${_GALLERY.max_width}; ${!_GALLERY.masonry||_GALLERY.masonry_direction==='vertical'?'*/':''} ${_GALLERY.masonry&&_GALLERY.masonry_direction!=='horizontal' ? '/*' : ''} max-height: ${_GALLERY.min_height||_GALLERY.min_width}; ${_GALLERY.masonry&&_GALLERY.masonry_direction!=='horizontal' ? '*/' : ''} } .card { display: grid; width: fit-content; height: fit-content; ${_GALLERY.masonry&&_GALLERY.masonry_direction==='horizontal'?'':'/*'} grid-template-rows: ${_GALLERY.min_height||_GALLERY.min_width} auto auto; ${_GALLERY.masonry&&_GALLERY.masonry_direction==='horizontal'?'':'*/'} ${_GALLERY.masonry? '/*':''} flex: ${_GALLERY.min_width}px; grid-template-rows: ${_GALLERY.min_height||_GALLERY.min_width} auto auto; grid-template-columns: ${_GALLERY.min_width}; ${_GALLERY.masonry? '*/':''} } .card a { margin: auto; text-align: center; } `; document.querySelector('head').prepend(style_el); const first_image = (_GALLERY.curPage-1) * _GALLERY.images_per_page; const last_image = Math.min(first_image + _GALLERY.images_per_page, arr.length); res.innerHTML = _GALLERY.Showing_results[0] + `${first_image+1}–${last_image}` + _GALLERY.Showing_results[1] + arr.length; for (let i = first_image; i < last_image; i++) { const card = getCard(arr[i]); grid.append(card); _GALLERY.results.push(card); const img = card.querySelector('img,video,iframe'); function check() { if ((img.tagName==='VIDEO' && img.classList.contains('ready')) || (img.tagName!=='VIDEO' && img.complete)||img.tagName==='IFRAME') resizeGridItem(card); else setTimeout(check,100); } if (_GALLERY.masonry) check(); } } const search = filterArchive(); function createNav(bool) { if (bool && search.length <= _GALLERY.images_per_page) return ''; const nav = document.createElement('nav'); nav.classList.add(bool?'bottom':'top','pagination'); let allTags = ''; if (_GALLERY.find.length) allTags = '

'+_GALLERY.See_all_tags+'

'; if (!bool) nav.innerHTML = allTags; const number_of_pages = Math.ceil(search.length / _GALLERY.images_per_page); if (number_of_pages === 1) { if (!_GALLERY.find.length && !_GALLERY.avoid.length) return '' else return nav; } const find = _GALLERY.find.length?'&find='+encodeURIComponent(_GALLERY.find.join(',')):''; const avoid = _GALLERY.avoid.length?'&avoid='+encodeURIComponent(_GALLERY.avoid.join(',')):''; if (number_of_pages > _GALLERY.max_pagination_links) { let str = ''; for (let i = 0; i < number_of_pages; i++) { const curPage = i + 1; str += ''+curPage+''; } const frm = document.createElement('form'); frm.hidden = true; if (_GALLERY.find.length) frm.innerHTML += ``; if (_GALLERY.avoid.length) frm.innerHTML += ``; const inp = document.createElement('input'); inp.type='hidden'; inp.name='page' frm.append(inp); const sel = document.createElement('select'); sel.innerHTML = str; sel.oninput = $ => { inp.value = sel.value; frm.submit(); } const lab = document.createElement('label'); lab.innerHTML = '' + _GALLERY.Page + ' '; const prev = document.createElement('a'); const next = document.createElement('a'); prev.innerHTML = _GALLERY.Prev_page; next.innerHTML = _GALLERY.Next_page; prev.href = (_GALLERY.curPage - 1>0) ? '?page='+(_GALLERY.curPage-1)+find+avoid : ''; next.href = (_GALLERY.curPage+1<=number_of_pages) ? '?page='+(_GALLERY.curPage+1)+find+avoid : ''; lab.append(sel); nav.append( (prev.href===location.href?'':prev),' ', lab,' ', (next.href===location.href?'':next), frm ); } else { let str = (_GALLERY.curPage - 1 > 0) ? `${_GALLERY.Prev_page}` : ``; for (let i = 0; i < number_of_pages; i++) { const curPage = i + 1; str += ` ${curPage}`; } str += (_GALLERY.curPage+1<=number_of_pages)?` ${_GALLERY.Next_page}`:''; nav.innerHTML = (!bool ? allTags : '') + str; } return nav; } _GALLERY.gallery.innerHTML = ''; _GALLERY.gallery.append( searchForm, res, createNav(0), grid, createNav(1) ); createGrid(search); } // END grid view //=====================================// /* VIEW */ //=====================================// else { _GALLERY.find = sessionStorage['do-gallery-find'] ? sessionStorage['do-gallery-find'].split(',') : ['']; _GALLERY.avoid = sessionStorage['do-gallery-avoid'] ? sessionStorage['do-gallery-avoid'].split(',') : ['']; if(_GALLERY.find[0]==='') _GALLERY.find = []; if(_GALLERY.avoid[0]==='') _GALLERY.avoid = []; const searchForm = makeSearchForm(); const search = filterArchive(); const index = search.findIndex( o => { return o.src === _GALLERY.curSrc; }); const img = search[index]; _GALLERY.curImg = img; const card = getCard(img); _GALLERY.gallery.classList.add('view'); const pic = card.querySelector('img'); function createNav(bool) { const nav = document.createElement('nav'); nav.classList.add(bool?'bottom':'top','navigation'); nav.innerHTML = '' + (index - 1 < 0 ? '' : `${_GALLERY.Prev_result} `) + `${_GALLERY.Return_to_gallery}` + (index + 1 < search.length ? ` ${_GALLERY.Next_result}` : '') return nav; } _GALLERY.gallery.innerHTML = ''; _GALLERY.gallery.append( searchForm, createNav(0), card, createNav(1) ); } //=====================================// /* FUNCTIONS */ //=====================================// function getQueries() { const queryarr = location.search.slice(1).split('&'); queryarr.forEach(q=>{ let [key,val] = q.split('=') key = key.trim().toLowerCase(); if (key === 'page') { _GALLERY.curPage = Number(val.trim()); } if (key === 'image') { _GALLERY.do_grid = false; _GALLERY.curSrc = decodeURIComponent(val.trim()); } if (key === 'search_mode') { if (val.trim().toUpperCase() === 'AND') _GALLERY.s_mode = 'AND'; else _GALLERY.s_mode = 'OR'; } if (key === 'find') { if (val.trim()) { const etags = val.split('+').join(' ').split('%2C'); etags.forEach( et => { _GALLERY.find.push(decodeURIComponent(et.trim())); }); } } if (key === 'avoid') { if (val.trim()) { const etags = val.split('+').join(' ').split('%2C'); etags.forEach( et => { _GALLERY.avoid.push(decodeURIComponent(et.trim())); }); } } }); } function parse() { const lines = _GALLERY.archive_text.split(/\n/); const vidre = /\.(?:webm|mkv|flv|vob|ogv|ogg|drc|gifv|mng|avi|mts|m2ts|ts|mov|qt|wmv|yuv|rm|rmvb|viv|asf|amv|mp4|m4p|m4v|mpg|mp2|mpeg?|m2v|m4v|svi|3gp|3g2|mxf|roq|nsv|flv|f4v|f4p|f4a|f4b).*$/i let makeNew = true; let captureCaption = ''; lines.forEach( li => { const t = li.trim(); // empty line - expect to make a new obj if(t === '') { makeNew = true; captureCaption = ''; return; } // first nonempty line = image source if (makeNew) { makeNew = false; _GALLERY.archive.push( { src: t, id: 'image-' + t.replace(/\W+/g,'-'), tags: [], fileName: t.slice(t.lastIndexOf('/')+1), attributes: [], isVideo: vidre.test(t) } ); return; } // parse lines for most recent image const img = _GALLERY.archive[_GALLERY.archive.length-1]; // tags if (t.startsWith('#')) { const tags = t.split('#')[1].trim().split(','); tags.forEach( tag => { tag = tag.trim(); addGALLERYTag(tag); if (tag) img.tags.push(tag); }); captureCaption = ''; return; } // key: value const match = /^(\w+)\s*:\s*(.*?)$/.exec(t); if (match) { const [key,val] = [match[1].trim(),match[2].trim()]; if(key==='caption'||key==='description'||key==='details') { captureCaption = key; img[captureCaption] = '

'+val+'

'; return; } else captureCaption = ''; if(key === 'tags') { const tags = val.split(','); tags.forEach( tag => { tag = tag.trim(); addGALLERYTag(tag); if (tag) img.tags.push(tag); }); return; } // otherwise img[key] = val; return; } // attribute=content const matchA = /^(\w+)\s*=\s*(.*?)$/.exec(t); if(matchA) { const [att,con] = [matchA[1].trim(),matchA[2].trim()]; captureCaption = ''; img.attributes.push( {name:att,content:con} ); return; } // new paragraph per line when capturing caption const blockre = /^<\/?(?:body|article|address|aside|footer|header|h\d|hgroup|main|nav|section|blockquote|dd|div|dl|dt|figcaption|hr|li|menu|nav|ol|p|pre|el|area|map|table|col|colgroup|tbody|td|tfoot|th|thead|tr|fieldset|section|script|noscript|form|details|summary|dialog|figure)/i; if (captureCaption!=='') { img[captureCaption] += blockre.test(t) ? t : '

' + t ; return; } }); } function addGALLERYTag(tag) { if (_GALLERY.allTags.findIndex( t => { return t.match( RegExp('\\b' + tag.replace(/\s+/g,'\\s*') + '\\b','i') ); }) < 0) _GALLERY.allTags.push(tag); } function getCard(obj) { if (obj.card) return obj.card; const card = document.createElement('article'); const description = document.createElement('div'); const taglist = document.createElement('ul'); const ref = document.createElement('a'); card.id = obj.id; card.classList.add('card'); taglist.classList.add('taglist'); const img = obj.isVideo ? document.createElement('video') : obj.isYoutube ? document.createElement('iframe') : document.createElement('img'); if (obj.isVideo) { card.classList.add('video'); const vid = img; const source = document.createElement('source'); source.setAttribute('src',_GALLERY.path + obj.src); vid.append(source); if (!_GALLERY.do_grid) { vid.setAttribute('controls','true'); vid.setAttribute('autoplay','true'); } else { vid.setAttribute('preload','metadata'); vid.addEventListener('canplay',()=>{ vid.classList.add('ready'); }); } } else if (obj.isYoutube) { card.classList.add('youtube'); const fr = img; fr.src = obj.src + (_GALLERY.do_grid?'&controls=0':''); fr.setAttribute('frameborder','0'); fr.setAttribute('allow','accelerometer;'+ (_GALLERY.do_grid ? '' : ' autoplay;') +' clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'); fr.setAttribute('referrerpolicy','strict-origin-when-cross-origin'); fr.setAttribute('allowfullscreen','true'); } else img.src = _GALLERY.path + obj.src; if (_GALLERY.do_grid) { ref.href = "?image=" + encodeURIComponent(obj.src); ref.classList.add('permalink'); // ref.innerHTML = '' + _GALLERY.Permalink + ''; ref.title = obj.title || obj.downloadName || obj.fileName; } else if (obj.isYoutube) { ref.hidden = true; } else { ref.href = _GALLERY.path + obj.src; ref.setAttribute('download', obj.downloadName||obj.fileName); ref.classList.add('download'); ref.innerHTML = '' + _GALLERY.Download + ''; } const title = _GALLERY.do_grid ? ref.cloneNode() : document.createElement('h1'); title.innerHTML = obj.title || obj.downloadName || obj.fileName || ''; title.classList.add('title'); obj.attributes.forEach( attr => { if ( attr.name.toLowerCase()==='class' ) card.classList.add( ...attr.content.split(/\s+/) ); else if ( attr.name.toLowerCase()==='title' ) ref.setAttribute(attr.name,attr.content); else img.setAttribute(attr.name,attr.content); }); description.classList.add('caption'); description.innerHTML = obj.caption || obj.description || obj.details || obj.detail || _GALLERY.No_description; if (obj.tags) { obj.tags.forEach(t => { const li = document.createElement('li'); li.classList.add('tag'); const a = document.createElement('a'); li.append(a); a.href = '?find=' + encodeURIComponent(t) + (_GALLERY.avoid.length? '&avoid='+encodeURIComponent(_GALLERY.avoid.join(',')) : ''); a.textContent = t; taglist.append(li); }); } function determineOrder (arr) { const rarr = []; arr.forEach( str => { switch( str.toLowerCase() ) { case 'image': _GALLERY.do_grid? rarr.push(ref):rarr.push(img); break; case 'title': rarr.push(title); break; case 'tags': rarr.push(taglist); break; case 'download': _GALLERY.do_grid? rarr.push(''):rarr.push(ref); break; case 'description': rarr.push(description); break; } }); return rarr; } if (_GALLERY.do_grid) { ref.append(img) card.append(...determineOrder(_GALLERY.grid_card_layout)); } else card.append(...determineOrder(_GALLERY.view_card_layout)); obj.card = card; return card; } function filterArchive() { const avoid = _GALLERY.avoid.length ? createRegex(_GALLERY.avoid) : null; const find = _GALLERY.find.length ? createRegex(_GALLERY.find) : null; _GALLERY.avoidRe = avoid; _GALLERY.findRe = find; let filter = []; let search = []; if (avoid!==null) { // avoid is always OR _GALLERY.archive.forEach( o => { for (let i=0; i { let s = 0; for (let i=0; i { for (let i=0; i { strs.push('\\b' + tag.replace(/\s+/g,'\\s+') + '\\b|'+'^'+ tag.replace(/\s+/g,'\\s+')+'$'); }); return new RegExp(strs.join('|'),'i'); } function makeSearchForm() { const searchForm = document.createElement('form'); searchForm.classList.add('search-form'); searchForm.innerHTML = ` `; return searchForm; }