Files
gallery.mjs/gallery.mjs.min

1 line
4.9 KiB
Plaintext

"use strict";export default class gallery{#wrap;get wrap(){return this.#wrap}#input;get input(){return this.#input}#gallery;get gallery(){return this.#gallery}#identifiers;get identifiers(){return this.#identifiers}#update;prefixes={wrap:"",image:"image_"};allowed=/\.(jpe?g|png|gif|webp)$/i;#dragged;get dragged(){return this.#dragged}#events=new Map([["system",new Map([["dragstart",(event)=>{this.#dragged=event.target.getAttribute("id");event.dataTransfer.effectAllowed="move";this.#events.get("moving").get("dragstart")(event)}],["dragover",(event)=>{event.preventDefault();event.dataTransfer.dropEffect="move";this.#events.get("moving").get("dragover")(event)}],["dragenter",(event)=>{const wrap=event.target.closest("div.image");if(wrap?.getAttribute("id")!==this.#dragged){wrap?.classList.add("target")}this.#events.get("moving").get("dragenter")(event)}],["dragleave",(event)=>{const wrap=event.target.closest("div.image");if(wrap instanceof HTMLElement){wrap.classList.remove("target")}this.#events.get("moving").get("dragleave")(event)}],["dragend",(event)=>{const wrap=event.target.closest("div.image");if(wrap instanceof HTMLElement){wrap.classList.remove("target")}this.#events.get("moving").get("dragend")(event)}],["drop",(event)=>{const wrap=event.target.closest("div.image");if(wrap instanceof HTMLElement&&wrap.getAttribute("id")&&wrap.getAttribute("id")!==this.#dragged){this.#gallery.querySelector("div.image.target")?.classList.remove("target");const from=this.#identifiers.indexOf(this.#dragged);const to=this.#identifiers.indexOf(wrap.getAttribute("id"));[this.#identifiers[from],this.#identifiers[to]]=[this.#identifiers[to],this.#identifiers[from]]}this.#events.get("moving").get("drop")(event)}]])],["moving",new Map([["dragstart",(event)=>{}],["dragover",(event)=>{}],["dragenter",(event)=>{}],["dragleave",(event)=>{}],["dragend",(event)=>{}],["drop",(event)=>{}]])],["wrap",new Map([["delete",(event)=>{}]])]]);get events(){return this.#events}constructor(wrap,input,gallery,inject=false){if(wrap instanceof HTMLElement){this.#wrap=wrap;if(inject){this.#wrap.gallery=this}}if(input instanceof HTMLInputElement){this.#input=input}if(gallery instanceof HTMLElement){this.#gallery=gallery}this.proxy();this.#identifiers.push(...[...this.#gallery.querySelectorAll("div.image")].map((image)=>image.getAttribute("id")))}proxy(){this.#identifiers=new Proxy([],{set:(target,property,value)=>{this.#update??=Promise.resolve().then(()=>{this.#update=null;target.forEach((identifier)=>this.#gallery.appendChild(document.getElementById(identifier)))});return Reflect.set(target,property,value)}})}ascending(){this.#identifiers.sort((a,b)=>a-b)}start(){for(const[event,handler]of this.#events.get("system")){this.#gallery.addEventListener(event,handler)}}stop(){for(const[event,handler]of this.#events.get("system")){this.#gallery.removeEventListener(event,handler)}}generate(order,target){const wrap=document.createElement("div");wrap.classList.add("image");wrap.setAttribute("id",this.prefixes.wrap+order);wrap.setAttribute("draggable",true);const button=document.createElement("button");button.classList.add("delete");button.addEventListener("click",(event)=>{const index=this.#identifiers.indexOf(this.prefixes.wrap+order);if(index>-1){this.#identifiers.splice(index,1);wrap.remove();this.#events.get("wrap")?.get("delete")(event)}});const trash=document.createElement("i");trash.classList.add("icon","trash");const image=document.createElement("img");image.setAttribute("id",this.prefixes.image+order);image.setAttribute("draggable",false);image.setAttribute("src",target instanceof File?window.URL.createObjectURL(target):target+"?updated="+Date.now());wrap.appendChild(image);button.appendChild(trash);wrap.appendChild(button);return wrap}import(files){this.stop();this.proxy();this.#gallery.innerHTML="";for(const[index,file]of files instanceof FileList?Object.entries(files):files){if(file){const extension=file.name??file.match(/\.\w{3,4}$/)[0];if(this.allowed.test(extension)){const wrap=this.generate(index,file);this.#gallery.appendChild(wrap);this.#identifiers.push(wrap.getAttribute("id"))}}}this.start()}async export(identifier,base64=false){const reader=new FileReader();if(typeof identifier==="string"||typeof identifier==="number"){const image=this.#gallery.querySelector("div.image#"+CSS.escape(identifier)+">img");if(image instanceof HTMLImageElement){const content=image.getAttribute("src")?.split("?")[0];try{if(new URL(content).protocol==="blob:"){return new Promise((resolve)=>{reader.onloadend=()=>resolve(reader.result);fetch(content).then((r)=>r.blob()).then((value)=>{if(base64){reader.readAsDataURL(value)}else{resolve(value)}})})}else{return content}}catch{return content}}}else{const wraps=this.#gallery.querySelectorAll("div.image");if(wraps.length>0){const converted=[];for(const wrap of wraps){const identifier=wrap.getAttribute("id");if(typeof identifier==="string"||typeof identifier==="number"){converted.push((await this.export(identifier))??null)}}return converted}}}}