(async(window, document)=>{ // https://gist.github.com/hagb4rd/6843803a6674fe1b9ead6f1e60f14f15#file-queue-download-images-js // ----------- // queue() returns a promise returning function. 'tasks' is an array of higher order functions that return 'promise returning'/'async' functions [()=>async(){ }]. // the purpose of that wrapping is not to start resolving the promise immediately, but being able to map parameters for the task. //'concurrent' is the max. number of tasks to be executed in parallel. function queue(tasks, concurrent) { return function() { var result = new Array(tasks.length); var running = 0; var pending = tasks.length; var cursor = 0; function next(onDone, onError) { if (cursor < tasks.length && running < concurrent) { let index = cursor; ++cursor; ++running; function save(v) { result[index] = v; --running; --pending; if (pending === 0) onDone(result); else next(onDone, onError); return v; } //execute task/resolve promise, and save result tasks[index]().then(save, save); //load next task next(onDone, onError); } } return new Promise(function(resolve, reject) { next(function(result) { resolve(result); }, reject); }); } } window.urlcreate=(u=`https://content4.coedcherry.com/watch-my-gf/184395/91122_#.jpg`,n=1,m=20)=>[...(new Array(m-n+1)).keys()].map(x=>(x+n)).map(x=>{ var pad=u.match(/#+/)[0].length; return u.replace(`#`.repeat(pad), String(x).padStart(pad, '0'));}) window.loadImage=(u)=>new Promise((resolve,reject)=>{var i=new Image(); i.onload=(e)=>resolve(i); i.onerror=(e)=>{var a=document.createElement('a');a.target='imageview';a.href=u; a.innerText=u;resolve(a)}; i.src=u; }); window.findImageLinks=(extensions=['.jpg','.png','.jpeg','.gif','.tif','.wbem'])=>[...document.querySelectorAll('a')].map(a=>a.href).filter(href=>extensions.some(ext=>ext==href.slice(-ext.length))); window.prepend=(elem)=>(document.body||document.rootElement).prepend(elem); window.loadImages=(list)=>(document.documentElement.innerHTML=``,list.map(u=>()=>(console.log(u), loadImage(u)).then(x=>prepend(x))).reduce((prev,next)=>prev.then(next),Promise.resolve())) window.linkedImages=(d)=>{ d=d||window.document; var xs=d.querySelectorAll("[href$=\".jpg\"],[href$=\".png\"]") var is=[...xs].map(x=>x.href); return is; } window.embedImages=(minW=250,minH=250)=>[...document.querySelectorAll('img')].filter(({width, height})=>(width>=minW && height>=minH)); window.dataUrlFromCanvas=(img)=>new Promise((resolve,reject) => { if(img instanceof Image) { try { var n=document.createElement("CANVAS"); n.height=img.height; n.width=img.width; n.getContext("2d").drawImage(img,0,0); var dataUrl=n.toDataURL("image/jpeg"); return resolve(dataUrl); } catch(err) { reject(err.message); } } else { var e=new Image(); e.crossOrigin='Anonymous'; var n=document.createElement("CANVAS"); e.addEventListener("error", (e)=>reject(e.message)); e.addEventListener("load", () => { try { n.height=e.height; n.width=e.width; n.getContext("2d").drawImage(e,0,0); var dataUrl=n.toDataURL("image/jpeg"); resolve(dataUrl); } catch(err) { reject(err.message); } }); e.src = img.src ? img.src : img; } }) window.dataUrlByFileReader = (url) => new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.responseType = 'blob'; xhr.onerror=(e)=>reject(e); xhr.onload = function () { var reader = new FileReader(); reader.onerror = function(e) { reject(e.message) } reader.onloadend = function () { resolve(reader.result); } reader.readAsDataURL(xhr.response); }; xhr.open('GET', url); xhr.send(); }) window.readAsDataUrl=async(img)=>{ var dataUrl; try { dataUrl=await dataUrlFromCanvas(img); return dataUrl; } catch(err) { conole.log(err); } try { dataUrl=await dataUrlFromCanvas(`https://jslave.herokuapp.com/proxy/?url=${img}`); return dataUrl; } catch(err) { conole.log(err); } try { dataUrl=await dataUrlFromCanvas(`https://jslave2.herokuapp.com/proxy/?url=${img}`); return dataUrl; } catch(err) { conole.log(err); } try { dataUrl=await dataUrlByFileReader(img); return dataUrl; } catch(err) { console.log(err); } try { dataUrl=await dataUrlByFileReader(`https://jslave.herokuapp.com/proxy/?url=${img}`); return dataUrl; } catch(err) { console.log(err); } try { dataUrl=await dataUrlByFileReader(`https://jslave2.herokuapp.com/proxy/?url=${img}`); return dataUrl; } catch(err) { console.log(err); } throw Error('could not resolve create dataUrl'); }; window.download=async(image,name)=>{ try { var a=document.createElement('a'); var dataUrl=await readAsDataUrl(image); a.href=dataUrl; a.setAttribute('download', name); a.style.display='none'; (document.body || document.documentElement).appendChild(a); console.log('dowload:'+name); console.log(image); a.click(); } catch (err) { console.log(err, [image, name]); } return [image, name] } window.downloadText=async(txt,name)=>{ try { var rndName=()=>Date.now()+(Math.random()*100000|0)+'.txt' name=name||rndName(); var a=document.createElement('a'); var dataUrl=`data:text/plain;charset=utf-8,${encodeURIComponent(txt)}`; a.href=dataUrl; a.setAttribute('download', name); a.style.display='none'; (document.body || document.documentElement).appendChild(a); console.log(`downloading: ${name}`); console.log(`--------------`); console.log(txt); a.click(); } catch (err) { console.log(err, [txt, name]); } return [txt, name] } window.downloadLinkedImages=()=>{ return [...linkedImages()].map((url)=>{ var name=`${location.host}${location.pathname.replace(/\//g,'.')}.${url.split(/\//).pop()}`; return ()=>download(url,name) }) }; window.downloadImages=(w=250,h=250)=>embedImages(w,h).map((i)=>{ var url=new URL(i.src); var name=[url.host].concat(i.alt?i.alt.match(/\w+/g):[]).concat(url.pathname.match(/[^/\?]+/g)).filter(x=>!!x).join('-'); return ()=>download(i.src,name); }); downloadText(findImageLinks().join('\n')); })(window, window.document) //Bookmarklet