-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfetch-img.js
138 lines (126 loc) · 3.66 KB
/
fetch-img.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
const db = new Dexie('ImageCache');
db.version(1).stores({
images: 'url, blob'
});
var hostImg = ""; // use cookie instead
async function saveImageIndexedDB(src) {
const key = { url: src };
let data = await db.images.get(key);
if (!data) {
data = await fetchImageToBlob(src);
db.images.add(data); // dont need await save, just render immediately
}
return data;
}
async function applyXSrcIndexedDB(sender, ignoreFetched=false) {
try {
if (sender.src && ignoreFetched) return;
const imgs = [...document.querySelectorAll("img[data-x-src]")].filter(t => t.dataset.xSrc == sender.dataset.xSrc);
let data = await saveImageIndexedDB(sender.dataset.xSrc);
await renderBlob(imgs, data.blob);
}
catch (e) {
console.log(e)
}
}
async function applyXSrcIndexedDBCanvas(sender, ignoreFetched=false) {
try {
if (sender.src && ignoreFetched) return;
const key = { url: sender.dataset.xSrc };
const imgs = [...document.querySelectorAll("img[data-x-src]")].filter(t => t.dataset.xSrc == key.url);
let data = await db.images.get(key);
if (!data) {
return fakeImg(sender).onload = (e) => getCanvas(e.target).toBlob(async (b) => {
db.images.add({ url: key.url, blob: b });
await renderBlob(imgs, b);
});
}
await renderBlob(imgs, data.blob);
}
catch (e) {
console.log(e)
}
}
async function renderBlob(imgs, b) {
const u = URL.createObjectURL(b);
try {
await Promise.allSettled([...imgs].map(img => {
return new Promise((res, rej) => {
function er() {
img.removeEventListener("error", er);
rej();
}
img.src = u;
img.addEventListener("load", function l() {
img.removeEventListener("load", l);
img.removeEventListener("error", er);
img.removeAttribute("data-x-src"); // hide it :))
res();
});
img.addEventListener("error", er);
});
}));
}
catch (e) {
console.log(e);
}
finally {
URL.revokeObjectURL(u);
}
}
function applyXSrcLocalStorage(target) {
let imgSrc = target.dataset.xSrc;
let data = localStorage.getItem(imgSrc);
if (data) {
setNewSrc(imgSrc, data);
}
else {
fakeImg(target).addEventListener("load", imageReceivedLocalStorage, false);
}
}
function imageReceivedLocalStorage(e) {
let sender = e.target;
const canvas = getCanvas(sender);
try {
sender.removeEventListener("load", imageReceivedLocalStorage);
let data = canvas.toDataURL("image/png");
localStorage.setItem(sender.origin.dataset.xSrc, data);
setNewSrc(sender.origin.dataset.xSrc, data);
} catch (err) {
console.error(`Error: ${err}`);
}
}
function setNewSrc(xSrc, src) {
[...document.querySelectorAll("img[data-x-src]")].filter(t => t.dataset.xSrc == xSrc).forEach(img => {
img.src = src;
img.removeAttribute("data-x-src");
});
}
function fakeImg(target) {
let imgSrc = target.dataset.xSrc;
let img = new Image();
img.origin = target;
img.crossOrigin = "anonymous"; // canvas need it
img.src = hostImg + imgSrc;
return img;
}
function fetchImageToBlob(src) {
return fetch(hostImg + src)
.then(response => response.blob())
.then(b => Object({ url: src, blob: b }));
}
function getCanvas(sender) {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.width = sender.width;
canvas.height = sender.height;
context.drawImage(sender, 0, 0);
return canvas;
}
function fetchImgOnLoad(ignoreFetched=true) {
const imgGroup = Object.groupBy(document.querySelectorAll("img[data-x-src]"), i => i.dataset.xSrc);
//Object.keys(imgGroup).map(src => imgGroup[src][0]).forEach(applyXSrcLocalStorage);
Object.keys(imgGroup).map(src => imgGroup[src][0]).forEach(i => applyXSrcIndexedDB(i, ignoreFetched));
}
fetchImgOnLoad();
let lsSize = new Blob(Object.values(localStorage)).size;