├── .gitignore
├── bin
├── background.js
├── icon_128.png
├── icon_128_pressed.png
├── icon_32.png
├── inject.js
└── manifest.json
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
├── addStyle.js
├── app.js
├── background.js
├── dom-pick
│ ├── element-overlay.d.ts
│ ├── element-overlay.js
│ ├── element-picker.d.ts
│ ├── element-picker.js
│ ├── index.d.ts
│ ├── index.js
│ ├── utils.d.ts
│ └── utils.js
├── icon_128.png
├── icon_128_pressed.png
├── icon_32.png
├── index.js
├── info.js
├── manifest.json
└── scrap.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/bin/background.js:
--------------------------------------------------------------------------------
1 | const updateIcon = async isPressed => {
2 | await chrome.action.setIcon({ path: `icon_128${isPressed ? "_pressed" : ""}.png` });
3 | }
4 |
5 | const sendMessage = data => {
6 | return new Promise(resolve => {
7 | chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
8 | if (tabs.length === 0) resolve();
9 | chrome.tabs.sendMessage(tabs[0].id, data, function(response) {
10 | resolve(response);
11 | });
12 | });
13 | });
14 | }
15 |
16 | const generateCeID = () => {
17 | return Date.now() + '_' + parseInt(Math.random() * 10000) + '_' + parseInt(Math.random() * 10000);
18 | }
19 |
20 | const getCeID = () => {
21 | return new Promise(resolve => {
22 | chrome.storage.local.get(["ce_id"], async function(result){
23 | if (result.ce_id && result.ce_id.length > 10) return resolve(result.ce_id);
24 | const ce_id = generateCeID();
25 | chrome.storage.local.set({ ce_id }, async function(result){
26 | resolve(ce_id)
27 | });
28 | });
29 | });
30 | }
31 |
32 | const getCurrentState = async () => {
33 | return await sendMessage({ type: 'get_state' });
34 | }
35 |
36 | const toggleState = async () => {
37 | return await sendMessage({ type: 'toggle_state' });
38 | }
39 |
40 | const currentTabChanged = async () => {
41 | await updateIcon(await getCurrentState());
42 | const ce_id = await getCeID();
43 | await sendMessage({ type: 'ce_id', ce_id });
44 | }
45 |
46 | chrome.tabs.onUpdated.addListener(async function(tabId, changeInfo, tab) {
47 | if (changeInfo.status === 'complete') {
48 | await currentTabChanged();
49 | }
50 | });
51 |
52 | chrome.tabs.onActivated.addListener(async tab => {
53 | await currentTabChanged();
54 | });
55 |
56 | chrome.runtime.onInstalled.addListener(async ({ reason, version }) => {
57 | if (reason === chrome.runtime.OnInstalledReason.INSTALL) {
58 | }
59 | });
60 |
61 | chrome.action.onClicked.addListener(async (tab) => {
62 | const state = await toggleState();
63 | await updateIcon(state);
64 | });
65 |
66 | chrome.runtime.onMessage.addListener(
67 | async function(request, sender, sendResponse) { //sender.tab
68 | switch(request.type) {
69 | case 'init':
70 | sendResponse({ type: "init" });
71 | break;
72 | case 'close':
73 | sendResponse({ type: "close" });
74 | await updateIcon(false);
75 | break;
76 | }
77 | }
78 | );
79 |
80 |
--------------------------------------------------------------------------------
/bin/icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AAA0109/DomPicker_Extension/563b131f70fa977fe29ffc16e414c3ec75c98afc/bin/icon_128.png
--------------------------------------------------------------------------------
/bin/icon_128_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AAA0109/DomPicker_Extension/563b131f70fa977fe29ffc16e414c3ec75c98afc/bin/icon_128_pressed.png
--------------------------------------------------------------------------------
/bin/icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AAA0109/DomPicker_Extension/563b131f70fa977fe29ffc16e414c3ec75c98afc/bin/icon_32.png
--------------------------------------------------------------------------------
/bin/inject.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | 'use strict';
3 |
4 | /**
5 | * Checks if `value` is the
6 | * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
7 | * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
8 | *
9 | * @static
10 | * @memberOf _
11 | * @since 0.1.0
12 | * @category Lang
13 | * @param {*} value The value to check.
14 | * @returns {boolean} Returns `true` if `value` is an object, else `false`.
15 | * @example
16 | *
17 | * _.isObject({});
18 | * // => true
19 | *
20 | * _.isObject([1, 2, 3]);
21 | * // => true
22 | *
23 | * _.isObject(_.noop);
24 | * // => true
25 | *
26 | * _.isObject(null);
27 | * // => false
28 | */
29 |
30 | var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
31 |
32 | /** Detect free variable `global` from Node.js. */
33 | var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
34 |
35 | var _freeGlobal = freeGlobal;
36 |
37 | /** Detect free variable `self`. */
38 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
39 |
40 | /** Used as a reference to the global object. */
41 | var root = _freeGlobal || freeSelf || Function('return this')();
42 |
43 | var _root = root;
44 |
45 | /** Used to match a single whitespace character. */
46 |
47 | /** Built-in value references. */
48 | var Symbol = _root.Symbol;
49 |
50 | var _Symbol = Symbol;
51 |
52 | /** Built-in value references. */
53 | var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;
54 |
55 | /** Used for built-in method references. */
56 |
57 | /** Built-in value references. */
58 | var symToStringTag$1 = _Symbol ? _Symbol.toStringTag : undefined;
59 |
60 | /**
61 | * Checks if `value` is object-like. A value is object-like if it's not `null`
62 | * and has a `typeof` result of "object".
63 | *
64 | * @static
65 | * @memberOf _
66 | * @since 4.0.0
67 | * @category Lang
68 | * @param {*} value The value to check.
69 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
70 | * @example
71 | *
72 | * _.isObjectLike({});
73 | * // => true
74 | *
75 | * _.isObjectLike([1, 2, 3]);
76 | * // => true
77 | *
78 | * _.isObjectLike(_.noop);
79 | * // => false
80 | *
81 | * _.isObjectLike(null);
82 | * // => false
83 | */
84 |
85 | class ElementOverlay {
86 | constructor(options) {
87 | var _a, _b, _c, _d, _e, _f, _g, _h, _j;
88 | this.overlay = document.createElement("div");
89 | this.overlay.className = options.className || "_ext-element-overlay";
90 | this.overlay.style.background = ((_a = options.style) === null || _a === void 0 ? void 0 : _a.background) || "rgba(250, 240, 202, 0.2)";
91 | this.overlay.style.borderColor = ((_b = options.style) === null || _b === void 0 ? void 0 : _b.borderColor) || "#F95738";
92 | this.overlay.style.borderStyle = ((_c = options.style) === null || _c === void 0 ? void 0 : _c.borderStyle) || "solid";
93 | this.overlay.style.borderRadius = ((_d = options.style) === null || _d === void 0 ? void 0 : _d.borderRadius) || "1px";
94 | this.overlay.style.borderWidth = ((_e = options.style) === null || _e === void 0 ? void 0 : _e.borderWidth) || "1px";
95 | this.overlay.style.boxSizing = ((_f = options.style) === null || _f === void 0 ? void 0 : _f.boxSizing) || "border-box";
96 | this.overlay.style.cursor = ((_g = options.style) === null || _g === void 0 ? void 0 : _g.cursor) || "crosshair";
97 | this.overlay.style.position = ((_h = options.style) === null || _h === void 0 ? void 0 : _h.position) || "absolute";
98 | this.overlay.style.zIndex = ((_j = options.style) === null || _j === void 0 ? void 0 : _j.zIndex) || "2147483647";
99 | // this.overlay.style.transition = "all .2s linear";
100 | this.shadowContainer = document.createElement("div");
101 | this.shadowContainer.className = "_ext-element-overlay-container";
102 | this.shadowContainer.style.position = "absolute";
103 | this.shadowContainer.style.top = "0px";
104 | this.shadowContainer.style.left = "0px";
105 | this.shadowRoot = this.shadowContainer.attachShadow({ mode: "open" });
106 | }
107 | addToDOM(parent, useShadowDOM) {
108 | this.usingShadowDOM = useShadowDOM;
109 | if (useShadowDOM) {
110 | parent.insertBefore(this.shadowContainer, parent.firstChild);
111 | this.shadowRoot.appendChild(this.overlay);
112 | }
113 | else {
114 | parent.appendChild(this.overlay);
115 | }
116 | }
117 | removeFromDOM() {
118 | this.setBounds({ x: 0, y: 0, width: 0, height: 0 });
119 | this.overlay.remove();
120 | if (this.usingShadowDOM) {
121 | this.shadowContainer.remove();
122 | }
123 | }
124 | captureCursor() {
125 | this.overlay.style.pointerEvents = "auto";
126 | }
127 | ignoreCursor() {
128 | this.overlay.style.pointerEvents = "none";
129 | }
130 | setBounds({ x, y, width, height }) {
131 | this.overlay.style.left = x + "px";
132 | this.overlay.style.top = y + "px";
133 | this.overlay.style.width = width + "px";
134 | this.overlay.style.height = height + "px";
135 | }
136 | getBounds() {
137 | return {
138 | x: parseFloat(this.overlay.style.left),
139 | y: parseFloat(this.overlay.style.top),
140 | width: parseFloat(this.overlay.style.width),
141 | height: parseFloat(this.overlay.style.height),
142 | }
143 | }
144 | }
145 |
146 | const getElementBounds = (el) => {
147 | const rect = el.getBoundingClientRect();
148 | return {
149 | x: window.pageXOffset + rect.left,
150 | y: window.pageYOffset + rect.top,
151 | width: el.offsetWidth,
152 | height: el.offsetHeight,
153 | };
154 | };
155 |
156 | const checkSimilarBounds = (b1, b2) => {
157 | const keys = ['x', 'y', 'width', 'height'];
158 | for (let i = 0 ; i < keys.length; i ++) {
159 | if (Math.abs(b1[keys[i]] - b2[keys[i]]) > 0.1 )
160 | return false;
161 | }
162 | return true;
163 | };
164 |
165 | class ElementPicker {
166 | constructor(overlayOptions) {
167 | this.handleMouseMove = (event) => {
168 | this.mouseX = event.clientX;
169 | this.mouseY = event.clientY;
170 | };
171 | this.handleClick = (event) => {
172 | var _a;
173 | if (this.target && this.target.getAttribute('gsallow')) return;
174 | if (this.target && ((_a = this.options) === null || _a === void 0 ? void 0 : _a.onClick)) {
175 | this.options.onClick(this.target);
176 | }
177 | event.preventDefault();
178 | };
179 | this.tick = () => {
180 | this.updateTarget();
181 | this.tickReq = window.requestAnimationFrame(this.tick);
182 | };
183 | this.active = false;
184 | this.overlay = new ElementOverlay(overlayOptions !== null && overlayOptions !== void 0 ? overlayOptions : {});
185 | }
186 | start(options) {
187 | var _a, _b;
188 | if (this.active) {
189 | return false;
190 | }
191 | this.active = true;
192 | this.options = options;
193 | document.addEventListener("mousemove", this.handleMouseMove, true);
194 | document.addEventListener("click", this.handleClick, true);
195 | this.overlay.addToDOM((_a = options.parentElement) !== null && _a !== void 0 ? _a : document.body, (_b = options.useShadowDOM) !== null && _b !== void 0 ? _b : true);
196 | this.tick();
197 | return true;
198 | }
199 | stop() {
200 | this.active = false;
201 | this.options = undefined;
202 | document.removeEventListener("mousemove", this.handleMouseMove, true);
203 | document.removeEventListener("click", this.handleClick, true);
204 | this.overlay.removeFromDOM();
205 | this.target = undefined;
206 | this.mouseX = undefined;
207 | this.mouseY = undefined;
208 | if (this.tickReq) {
209 | window.cancelAnimationFrame(this.tickReq);
210 | }
211 | }
212 | updateTarget() {
213 | var _a, _b;
214 | if (this.mouseX === undefined || this.mouseY === undefined) {
215 | return;
216 | }
217 | // Peek through the overlay to find the new target
218 | this.overlay.ignoreCursor();
219 | const elAtCursor = document.elementFromPoint(this.mouseX, this.mouseY);
220 | const newTarget = elAtCursor;
221 | this.overlay.captureCursor();
222 | // If the target hasn't changed, there's nothing to do
223 | if (!newTarget) return;
224 | // If we have an element filter and the new target doesn't match,
225 | // clear out the target
226 | if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.elementFilter) {
227 | if (!this.options.elementFilter(newTarget)) {
228 | this.target = undefined;
229 | this.overlay.setBounds({ x: 0, y: 0, width: 0, height: 0 });
230 | return;
231 | }
232 | }
233 |
234 | const bounds = getElementBounds(newTarget);
235 | if (newTarget === this.target) {
236 | const ori_bounds = this.overlay.getBounds();
237 | if (checkSimilarBounds(bounds, ori_bounds))
238 | return ;
239 | }
240 |
241 | this.target = newTarget;
242 | this.overlay.setBounds(bounds);
243 | if ((_b = this.options) === null || _b === void 0 ? void 0 : _b.onHover) {
244 | this.options.onHover(newTarget);
245 | }
246 | }
247 | }
248 |
249 | const addStyle = style => {
250 | const styleTag = document.createElement('style');
251 | styleTag.innerHTML = style;
252 | document.head.appendChild(styleTag);
253 | };
254 |
255 | const Constant = {
256 | title: ['title', 'name'],
257 | price: ['price'],
258 | description: ['description', 'detail', 'info']
259 | };
260 |
261 | const checkIfSimilarProductContainer = (el, attrs = []) => {
262 | const area_limit = 80 * 80, txt_limit_ct = 2;
263 | var txt_ct = 0;
264 | const itms = el.getElementsByTagName('*');
265 | for (let i = 0; i < itms.length; i ++) {
266 | if (getText(itms[i])) txt_ct ++;
267 | if (txt_ct > txt_limit_ct) break;
268 | }
269 | if (txt_ct < txt_limit_ct) return false;
270 |
271 | const imgs = el.getElementsByTagName('img');
272 | let i = 0;
273 | for (i = 0; i < imgs.length; i ++) {
274 | const img = imgs[i];
275 | const area = img.width * img.height;
276 | if (area < area_limit) continue;
277 | break;
278 | }
279 | if (i === imgs.length) return false;
280 | if (!attrs.length) return true;
281 |
282 | const htmlStr = (el.innerHTML || '').toLocaleLowerCase();
283 | i = 0;
284 | for (i = 0; i < attrs.length; i ++) {
285 | let j = 0;
286 | for (j = 0; j < attrs[i].length; j ++)
287 | if(htmlStr.includes(attrs[i][j]))
288 | break;
289 | if (j === attrs[i].length) break;
290 | }
291 |
292 | if (i && i === attrs.length) return true;
293 | return false;
294 | };
295 |
296 | const checkIfSimilarItem = (a, b) => {
297 | if (!checkIfSimilarProductContainer(a) || !checkIfSimilarProductContainer(b)) return 0;
298 | const tag1 = a.tagName, tag2 = b.tagName;
299 | if (tag1.toLocaleLowerCase() !== tag2.toLocaleLowerCase()) return 0;
300 | const attr1 = a.attributes, attr2 = b.attributes;
301 | let ct = 0;
302 | for (let i = 0; i < attr1.length; i ++) {
303 | const attr = attr1[i].name || '';
304 | if (!attr) continue;
305 | let j = 0;
306 | for (j = 0; j < attr2.length; j ++) {
307 | if (attr2[j].name == attr) break;
308 | }
309 | if (j === attr2.length) {
310 | continue;
311 | }
312 | ct ++;
313 | }
314 | let rate = Math.min(((ct * 2) / (attr1.length + attr2.length)) * 1.5, 1);
315 | if (attr1.length + attr2.length === 0) rate = 1;
316 | return rate;
317 | };
318 |
319 | const checkIfListContainer = el => {
320 | const t = 0.9;
321 | let p = el.parentNode;
322 | while (p && p.parentNode) {
323 | const pp = p.parentNode;
324 | const chs = pp.children;
325 | let ct = 0;
326 | for (let i = 0; i < chs.length; i ++) {
327 | let max = 0;
328 | for (let j = 0; j < chs.length; j ++) {
329 | if (i === j) continue;
330 | const a = chs[i], b = chs[j];
331 | const ret = checkIfSimilarItem(a, b);
332 | max = Math.max(max, ret);
333 | if (max >= t) break;
334 | }
335 | if (max < t) ct ++;
336 | if (ct > 1) break;
337 | }
338 | if (ct < 2 && chs.length > 2) return p;
339 | p = p.parentNode;
340 | }
341 | return null;
342 | };
343 |
344 | const getProductRootElement = el => {
345 | const check_list = checkIfListContainer(el);
346 | if (check_list) return check_list;
347 | if (checkIfSimilarProductContainer(el, [Constant.title])) return el;
348 | let p = el.parentNode;
349 | while (p && p.tagName.toLocaleLowerCase() !== 'html') {
350 | if (checkIfSimilarProductContainer(p, [Constant.title])) return p;
351 | p = p.parentNode;
352 | }
353 | return el;
354 | };
355 |
356 | const isVisible = el => {
357 | const style = window.getComputedStyle(el);
358 | if (style.opacity === '0') return false;
359 | if (style.visibility == 'hidden') return false;
360 | const r = el.getBoundingClientRect();
361 | if (r.width < 10 || r.height < 10) return false;
362 | return true;
363 | };
364 |
365 | const checkIfHasAttribute = (el, attr) => {
366 | const keys = el.attributes;
367 | for (let i = 0; i < keys.length; i ++) {
368 | const key = keys[i].name || '';
369 | const value = el.getAttribute(key) || '';
370 | if (key.toLocaleLowerCase().includes(attr) || value.toLocaleLowerCase().includes(attr)) return true;
371 | }
372 | return false;
373 | };
374 |
375 | const checkIfDescendOf = (ch, p, signs) => {
376 | while(ch && ch !== p) {
377 | for (let i = 0; i < signs.length; i ++)
378 | if (checkIfHasAttribute(ch, signs[i]))
379 | return true;
380 | ch = ch.parentNode;
381 | }
382 | return false;
383 | };
384 |
385 | const isHovered = (r, e) => {
386 | const x = e.x, y = e.y;
387 | if (r.left <= x && r.right >= x && r.top <= y && r.bottom >= y) return true;
388 | return false;
389 | };
390 |
391 | const checkIfBetterImg = (a, b, mouse, excepts = []) => {
392 | if (!isVisible(a)) return false;
393 | if (!isVisible(b)) return true;
394 | const a_src = getSrcFromImgTag(a), b_src = getSrcFromImgTag(b);
395 | if (!a_src) return false;
396 | if (!b_src) return true;
397 | const excepts_src = excepts.map(itm => getSrcFromImgTag(itm));
398 | if (excepts_src.includes(a_src)) return false;
399 | if (excepts_src.includes(b_src)) return true;
400 |
401 | const offset = 2;
402 | const r1 = a.getBoundingClientRect(), r2 = b.getBoundingClientRect();
403 | const h1 = isHovered(r1, mouse), h2 = isHovered(r2, mouse);
404 | if (h1 && !h2) return true;
405 | if (!h1 && h2) return false;
406 |
407 | const area1 = r1.width * r1.height, area2 = r2.width * r2.height;
408 | if (Math.abs(area1 - area2) < offset * offset) {
409 | if (Math.abs(r1.x - r2.x) < offset && Math.abs(r1.y - r2.y) < offset) return true;
410 | }
411 | if (area1 > area2) return true;
412 | return false;
413 | };
414 |
415 | const containsAnyLetters = str => {
416 | return /[a-zA-Z0-9]/.test(str);
417 | };
418 |
419 | const getText = el => {
420 | if (!el) return '';
421 | if (['noscript', 'img'].indexOf(el.nodeName.toLocaleLowerCase()) > -1) return '';
422 | if (!isVisible(el)) return false;
423 | try {
424 | const childNodes = el.childNodes;
425 | var hasText = false;
426 | for (let i = 0; i < childNodes.length; i++) {
427 | if (childNodes[i].nodeType === Node.TEXT_NODE) {
428 | var txt = childNodes[i].textContent;
429 | if (!containsAnyLetters(txt)) continue;
430 | hasText = true;
431 | break;
432 | }
433 | }
434 | if (hasText) return (el.innerText || el.textContent || '').replace(/\n/g, '');
435 | return ''
436 | } catch (e) {
437 | return '';
438 | }
439 | };
440 |
441 | const getFText = el => {
442 | if (!el) return '';
443 | return (el.innerText || el.textContent || '').replace(/\n\n/g, '\n');
444 | };
445 |
446 | const getEnteredText = el => {
447 | if (!el) return '';
448 | return (el.innerText || el.textContent || '').replace(/\n\n/g, '\n').replace(/\n/g, '\n'); //•
449 | };
450 |
451 | const checkIfBetterTitle = (a, b, p) => {
452 | const txt1 = getText(a), txt2 = getText(b);
453 | if (txt1 && !txt2) return true;
454 | if (!txt1) return false;
455 |
456 | const des1 = checkIfDescendOf(a, p, Constant.title), des2 = checkIfDescendOf(b, p, Constant.title);
457 | if (des1 && !des2) return true;
458 | if (!des1 && des2) return false;
459 |
460 | const fontSize1 = parseFloat(window.getComputedStyle(a).fontSize) || 0,
461 | fontSize2 = parseFloat(window.getComputedStyle(b).fontSize) || 0;
462 |
463 | if (fontSize1 > fontSize2 * 1.2) return true;
464 | return false;
465 | };
466 |
467 | const getCurrencyNumber = (str) => {
468 | try {
469 | return parseFloat(str.replace(/[^0-9.]+/g,"")) || 0;
470 | } catch (ex) {
471 | return 0;
472 | }
473 | };
474 |
475 | const checkIfBetterPrice = (a, b, p) => {
476 | const txt1 = getText(a), txt2 = getText(b);
477 | const isPrice1 = checkIfPrice(txt1), isPrice2 = checkIfPrice(txt2);
478 | if (isPrice1 && !isPrice2) return true;
479 | if (!isPrice1) return false;
480 |
481 | const des1 = checkIfDescendOf(a, p, Constant.price), des2 = checkIfDescendOf(b, p, Constant.price);
482 | if (des1 && !des2) return true;
483 | if (!des1 && des2) return false;
484 |
485 | return false;
486 | };
487 |
488 | const checkIfBetterDescription = (a, b, p) => {
489 | const txt1 = getText(a), txt2 = getText(b);
490 | if (txt1 && !txt2) return true;
491 | if (!txt1) return false;
492 |
493 | // const des1 = checkIfDescendOf(a, p, Constant.description), des2 = checkIfDescendOf(b, p, Constant.description)
494 | // if (des1 && !des2) return true;
495 | // if (!des1 && des2) return false;
496 |
497 | if (txt1.length > txt2.length) return true;
498 | return false;
499 | };
500 |
501 | const findHref = el => {
502 | var p = el;
503 | while(p && p.tagName.toLocaleLowerCase() !== 'html') {
504 | if ((p.tagName.toLocaleLowerCase() === 'a' || p.tagName.toLocaleLowerCase === 'button') && p.href) return p.href;
505 | p = p.parentNode;
506 | }
507 | return '';
508 | };
509 |
510 | const getImgUrl = (el, mouse, excepts = []) => {
511 | if (!el) return '';
512 | if (el.tagName.toLocaleLowerCase() === 'img') return el;
513 | const imgs = el.getElementsByTagName('img');
514 | if (!imgs.length) return '';
515 |
516 | var ret = imgs[0];
517 | for (let i = 1; i < imgs.length; i ++) {
518 | if (checkIfBetterImg(imgs[i], ret, mouse, excepts)) ret = imgs[i];
519 | }
520 | return ret;
521 | };
522 |
523 | const getManualImgUrl = (el, mouse) => {
524 | while(el.tagName !== 'html') {
525 | const img = getImgUrl(el, mouse);
526 | if (img) return img;
527 | el = el.parentNode;
528 | }
529 | return null;
530 | };
531 |
532 | const getName = (el) => {
533 | const itms = el.getElementsByTagName("*");
534 | var ret = itms[0];
535 | for (let i = 1; i < itms.length; i ++) {
536 | if (checkIfBetterTitle(itms[i], ret, el)) ret = itms[i];
537 | }
538 | return ret;
539 | };
540 |
541 | const checkIfPrice = (p) => {
542 | if (!p) return false;
543 | let d = p.replace(/ |\n|,/g, '');
544 | d = d.replace('$', '');
545 | if (!d) return false;
546 | for (let i = 0; i < d.length; i ++) if (d[i] !== '.' && !(d[i] >= '0' && d[i] <= '9')) return false;
547 | return true;
548 | };
549 |
550 | const getPrice = (el) => {
551 | const itms = el.getElementsByTagName("*");
552 | var ret = itms[0];
553 | for (let i = 1; i < itms.length; i ++) {
554 | if (checkIfBetterPrice(itms[i], ret, el)) ret = itms[i];
555 | }
556 | return ret;
557 | };
558 |
559 | const getDescriptin = (el) => {
560 | const itms = el.getElementsByTagName("*");
561 | var ret = itms[0];
562 | for (let i = 1; i < itms.length; i ++) {
563 | if (checkIfBetterDescription(itms[i], ret, el)) ret = itms[i];
564 | }
565 | return ret;
566 | };
567 |
568 | const getPhotos = (el, mouse, photo) => {
569 | const ret = [photo];
570 | for (let i = 0; i < 4; i ++) {
571 | const img = getImgUrl(el, mouse, ret);
572 | if (ret.findIndex(itm => getSrcFromImgTag(itm).split('?')[0] === getSrcFromImgTag(img).split('?')[0]) > -1) break;
573 | ret.push(img);
574 | }
575 | ret.shift();
576 | return ret;
577 | };
578 |
579 | const getUrl = (el) => {
580 | if (!el) return '';
581 | return findHref(el);
582 | };
583 |
584 | const getSrcFromImgTag = (el) => {
585 | if (!el) return '';
586 | return (el.currentSrc || el.src || '').split(' ')[0]
587 | };
588 |
589 | const getProductInfo = (el, picker) => {
590 | const p = getProductRootElement(el);
591 |
592 | const e_img = getImgUrl(p, { x: picker.mouseX, y: picker.mouseY });
593 | const e_name = getName(p);
594 | const e_price = getPrice(p);
595 | const e_description = getDescriptin(p);
596 | const e_photos = getPhotos(p, { x: picker.mouseX, y: picker.mouseY }, e_img);
597 | const name = getText(e_name);
598 | const img = getSrcFromImgTag(e_img);
599 | const url = getUrl(el);
600 | const price = getCurrencyNumber(getText(e_price));
601 | const description = getEnteredText(e_description);
602 | const r_photos = {};
603 | const photos = e_photos.map((p, idx) => {
604 | r_photos['photo' + idx] = p;
605 | return getSrcFromImgTag(p);
606 | });
607 | return {
608 | name,
609 | img,
610 | color: img,
611 | url,
612 | description,
613 | price,
614 | photos,
615 | elements: { e_name, e_img, e_price, e_description, ...r_photos }
616 | }
617 | };
618 |
619 | const getProductInfoIndividual = (el, picker, global) => {
620 | if (!global.productInfo) global.productInfo = {};
621 | const productInfo = global.productInfo;
622 | if (!productInfo.elements) productInfo.elements = {};
623 | if (!productInfo.photos) productInfo.photos = [];
624 | if (!productInfo.photos.length) {
625 | productInfo.photos.push('');
626 | productInfo.elements.photo0 = null;
627 | }
628 |
629 | switch(global.selectMode) {
630 | case 'img':
631 | productInfo.elements.e_img = getManualImgUrl(el, { x: picker.mouseX, y: picker.mouseY });
632 | productInfo.img = getSrcFromImgTag(productInfo.elements.e_img);
633 | break;
634 | case 'color':
635 | productInfo.elements.e_color = getManualImgUrl(el, { x: picker.mouseX, y: picker.mouseY });
636 | productInfo.color = getSrcFromImgTag(productInfo.elements.e_color);
637 | break;
638 | case 'name':
639 | productInfo.elements.e_name = el;
640 | productInfo.name = getFText(el);
641 | break;
642 | case 'description':
643 | productInfo.elements.e_description = el;
644 | productInfo.description = getEnteredText(el);
645 | break;
646 | case 'price':
647 | productInfo.elements.e_price = el;
648 | productInfo.price = getCurrencyNumber(getFText(el));
649 | break;
650 | case 'photos':
651 | const e_photo = getManualImgUrl(el, { x: picker.mouseX, y: picker.mouseY });
652 | const photo = (e_photo.currentSrc || e_photo.src || '').split(' ')[0];
653 | productInfo.elements['temp_photo'] = e_photo;
654 | productInfo.temp_photo = photo;
655 | break;
656 | }
657 | };
658 |
659 | const STYLES = `
660 | .gs_confirm_container, .gs_message, .gs_tooltip {
661 | box-sizing: border-box !important;
662 | }
663 | .gs_confirm_container *, .gs_message *, .gs_tooltip * {
664 | color: black !important;
665 | box-sizing: border-box !important;
666 | font-size: 16px !important;
667 | appearance: unset !important;
668 | position: unset !important;
669 | margin: unset !important;
670 | opacity: unset !important;
671 | visibility: unset !important;
672 | }
673 | .gs_confirm_container input[type=checkbox] {
674 | width: 13px !important;
675 | height: 13px !important;
676 | }
677 | .gs_confirm_container input, .gs_message input {
678 | border: 1px solid black !important;
679 | }
680 | .gs_hidden { visibility: hidden; }
681 | .gs_d-none { display: none !important; }
682 | .gs_tooltip {
683 | position: fixed !important;
684 | z-index: 99999999999999 !important;
685 | max-width: 500px !important;
686 | width: 80% !important;
687 | pointer-events: none !important;
688 | display: none !important;
689 |
690 | background-color: #ffa778 !important;
691 | padding: 5px 10px !important;
692 | box-shadow: 1px 1px 5px 2px #260101 !important;
693 | line-height: 16px !important;
694 | font-size: 16px !important;
695 | color: black !important;
696 | }
697 | .gs_checkbox {
698 | width: 18px !important;
699 | height: 18px !important;
700 | cursor: pointer !important;
701 | }
702 | .gs_tooltip.gs_show {
703 | display: block !important;
704 | }
705 | .gs_confirm_container {
706 | position: fixed !important;
707 | left: 0 !important;
708 | top: 0 !important;
709 | width: 100vw !important;
710 | height: 100vh !important;
711 | background-color: #ff450040 !important;
712 | z-index: 9999999999999 !important;
713 | display: none !important;
714 | }
715 | .gs_confirm_container.gs_hide {
716 | opacity: 0 !important;
717 | transition: opacity 2s !important;
718 | transition-delay: 4s !important;
719 | }
720 | .gs_message, .gs_confirm {
721 | position: fixed !important;
722 | box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.25) !important;
723 | padding: 30px 10px 8px !important;
724 | background-color: #fff !important;
725 | border: 4px solid #eee !important;
726 | }
727 | .gs_confirm {
728 | left: calc(50vw - 350px) !important;
729 | top: 80px !important;
730 | }
731 | .gs_hide .gs_confirm {
732 | display: none !important;
733 | }
734 | .gs_confirm_content {
735 | width: 730px !important;
736 | max-width: 100% !important;
737 | max-height: calc(100vh - 150px) !important;
738 | overflow-y: auto !important;
739 | display: flex !important;
740 | gap: 20px !important;
741 | flex-wrap: wrap !important;
742 | align-items: flex-start !important;
743 | }
744 | @media screen and (max-width: 768px) {
745 | .gs_confirm {
746 | width: 290px !important;
747 | left: calc(50vw - 150px) !important;
748 | }
749 | }
750 | .gs_message {
751 | display: none !important;
752 | left: 10px !important;
753 | bottom: 10px !important;
754 | z-index: 999999999999 !important;
755 | width: 300px !important;
756 | }
757 | .gs_message_content {
758 | display: flex !important;
759 | max-height: calc(100vh - 100px) !important;
760 | overflow-y: auto !important;
761 | min-height: 250px !important;
762 | flex-direction: column !important;
763 | }
764 |
765 | .gs_confirm_container.gs_show, .gs_message.gs_show {
766 | display: inline-block !important;
767 | }
768 | .gs_ollacart_img img {
769 | width: 100% !important;
770 | }
771 | .gs_confirm .gs_ollacart_img {
772 | width: 350px !important;
773 | /* position: sticky; */
774 | /* top: 0; */
775 | }
776 | .gs_name_price {
777 | display: flex !important;
778 | justify-content: space-between !important;
779 | font-size: 16px !important;
780 | color: black !important;
781 | gap: 10px !important;
782 | }
783 | .gs_confirm .gs_name_price {
784 | font-size: 20px !important;
785 | font-weight: bold !important;
786 | color: #303030 !important;
787 | }
788 | .gs_confirm .gs_price {
789 | color: #004400 !important;
790 | }
791 | .gs_description {
792 | font-size: 14px !important;
793 | margin-top: 10px !important;
794 | white-space: break-spaces !important;
795 | }
796 | .gs_message_over, .gs_message_finish {
797 | position: absolute !important;
798 | left: 0 !important;
799 | right: 0 !important;
800 | top: -20px !important;
801 | background-color: orangered !important;
802 | color: white !important;
803 | text-align: center !important;
804 | padding: 8px 0 !important;
805 | font-size: 20px !important;
806 | font-weight: bold !important;
807 | white-space: nowrap !important;
808 | cursor: pointer !important;
809 | }
810 | .gs_message_mask {
811 | position: absolute !important;
812 | left: -4px !important;
813 | right: -4px !important;
814 | top: -4px !important;
815 | bottom: -4px !important;
816 | background-color: #ff450040 !important;
817 | }
818 | .gs_message_finish {
819 | font-size: 30px !important;
820 | top: calc(50% - 100px) !important;
821 | padding: 50px 0 !important;
822 | }
823 | .gs_addtional_photos {
824 | margin-top: 5px !important;
825 | display: flex !important;
826 | flex-wrap: wrap !important;
827 | gap: 10px !important;
828 | }
829 | .gs_addtional_photos>div {
830 | position: relative !important;
831 | width: 46px !important;
832 | height: 60px !important;
833 | overflow: hidden !important;
834 | display: flex !important;
835 | justify-content: center !important;
836 | align-items: center !important;
837 | border: 1px solid blue !important;
838 | }
839 | .gs_addtional_photos .gs_remove_photo {
840 | transform: translateY(100%) !important;
841 | opacity: 0 !important;
842 | transition: all .3s !important;
843 | position: absolute !important;
844 | width: 100% !important;
845 | height: 100% !important;
846 | background-color: #000000A0 !important;
847 | display: flex !important;
848 | justify-content: center !important;
849 | align-items: center !important;
850 | }
851 | .gs_addtional_photos>div:hover .gs_remove_photo {
852 | transform: translateY(0) !important;
853 | opacity: 1 !important;
854 | }
855 | .gs_addtional_photos .gs_remove_photo .gs_remove_btn {
856 | width: 30px !important;
857 | height: 30px !important;
858 | border-radius: 50% !important;
859 | cursor: pointer !important;
860 | display: flex !important;
861 | justify-content: center !important;
862 | align-items: center !important;
863 | font-size: 30px !important;
864 | font-weight: bold !important;
865 | background-color: rgb(200, 200, 200) !important;
866 | color: black !important;
867 | }
868 | .gs_addtional_photos img {
869 | width: 100% !important;
870 | }
871 |
872 | .gs_manual_select_tools {
873 | flex-grow: 1 !important;
874 | display: flex !important;
875 | align-items: flex-end !important;
876 | justify-content: space-between !important;
877 | margin-top: 10px !important;
878 | }
879 | .gs_confirm_tools {
880 | display: flex !important;
881 | gap: 15px !important;
882 | justify-content: flex-end !important;
883 | align-items: flex-end !important;
884 | flex-grow: 1 !important;
885 | margin-top: 10px !important;
886 | }
887 | .gs_btn {
888 | padding: 4px 10px !important;
889 | background-color: orangered !important;
890 | color: white !important;
891 | font-size: 16px !important;
892 | font-weight: bold !important;
893 | cursor: pointer !important;
894 | border-radius: 7px !important;
895 | }
896 | .gs_btn:hover {
897 | opacity: 0.8 !important;
898 | }
899 | .gs_btn:active {
900 | opacity: 0.7 !important;
901 | }
902 | .gs_btn.gs_direct {
903 | padding: 4px 14px !important;
904 | }
905 |
906 | .gs_confirm_right {
907 | display: flex !important;
908 | flex-direction: column !important;
909 | flex-grow: 1 !important;
910 | width: 1px !important;
911 | }
912 | .gs_text_center {
913 | text-align: center !important;
914 | }
915 | .gs_go_ollacart {
916 | margin-top: 20px !important;
917 | font-size: 20px !important;
918 | line-height: 25px !important;
919 | cursor: pointer !important;
920 | color: lightseagreen !important;
921 | }
922 | .gs_textarea {
923 | width: 100% !important;
924 | height: 300px !important;
925 | min-height: 300px !important;
926 | max-height: 300px !important;
927 | font-size: 16px !important;
928 | }
929 |
930 | .gs_close {
931 | position: absolute !important;
932 | top: 5px !important;
933 | right: 5px !important;
934 | cursor: pointer !important;
935 | }
936 | .gs_close:hover {
937 | opacity: 0.8 !important;
938 | }
939 | .gs_close img {
940 | width: 20px !important;
941 | }
942 |
943 | .gs_addtional_picker {
944 | margin-top: 15px !important;
945 | margin-left: auto !important;
946 | }
947 | .gs_addtional_picker>div {
948 | width: 200px !important;
949 | margin-top: 5px !important;
950 | display: flex !important;
951 | align-items: center !important;
952 | justify-content: space-between !important;
953 | }
954 | .gs_addtional_picker>div>div {
955 | display: flex !important;
956 | align-items: center !important;
957 | gap: 5px !important;
958 | }
959 | .gs_addtional_picker>div>*:nth-child(2) {
960 | width: 70px !important;
961 | }
962 | .gs_addtional_picker .gs_color-img {
963 | aspect-ratio: 1 !important;
964 | text-align: center !important;
965 | border: 1px solid orangered !important;
966 | object-fit: contain !important;
967 | padding: 4px !important;
968 | border-radius: 8px !important;
969 | cursor: pointer !important;
970 | }
971 | .gs_addtional_picker .gs_color-img:hover {
972 | opacity: 0.8 !important;
973 | }
974 |
975 | .gs_confirm_content::-webkit-scrollbar, .gs_message_content::-webkit-scrollbar {
976 | width: 7px !important;
977 | }
978 | .gs_confirm_content::-webkit-scrollbar-track, .gs_message_content::-webkit-scrollbar-track {
979 | background: #f1f1f1 !important;
980 | }
981 | .gs_confirm_content::-webkit-scrollbar-thumb, .gs_message_content::-webkit-scrollbar-thumb {
982 | background: #e19b9b !important;
983 | }
984 | .gs_confirm_content::-webkit-scrollbar-thumb:hover, .gs_message_content::-webkit-scrollbar-thumb:hover {
985 | background: #e19b9bd0 !important;
986 | }
987 | `;
988 |
989 | const manualSelect = {
990 | img: 'Main Logo',
991 | name: 'Title',
992 | price: 'Price',
993 | description: 'Description',
994 | photos: 'Images'
995 | };
996 |
997 | const showMessage = (global) => {
998 | const info = global.productInfo;
999 | let html = '
';
1000 | if (!global.selectMode || global.selectMode === 'img') html += `
`;
1001 | if (!global.selectMode) {
1002 | html += `
${info.name}${info.price || ''}
`;
1003 | }
1004 | if (!global.selectMode) html += `
${info.description}
`;
1005 | if (global.selectMode === 'name' || global.selectMode === 'price' || global.selectMode === 'description') {
1006 | html += `
`;
1007 | }
1008 | if (!global.selectMode || global.selectMode === 'photos') {
1009 | html += `
`;
1010 | for (let i = 0; info.photos && (i < info.photos.length); i ++ ) {
1011 | if (info.photos[i])
1012 | html += `
`;
1013 | }
1014 | html += `
`;
1015 | }
1016 | if (global.selectMode === 'photos' && info.temp_photo) {
1017 | html += `
`;
1018 | }
1019 |
1020 | if (global.selectMode) {
1021 | html += `
`;
1026 | }
1027 | html += `
`;
1028 |
1029 | if (global.selectMode) {
1030 | html += `Select ${manualSelect[global.selectMode]}
`;
1031 | } else {
1032 | html += `Auto Select
`;
1033 | }
1034 |
1035 | global.popup.innerHTML = html;
1036 | global.popup.classList.toggle("gs_show", true);
1037 | };
1038 |
1039 | const showColorModal = (global) => {
1040 | const info = global.productInfo;
1041 | let html = '';
1042 | html += `
`;
1043 |
1044 | if (global.selectMode) {
1045 | html += `
`;
1050 | }
1051 | html += `
`;
1052 |
1053 | html += `Specify Color
`;
1054 |
1055 | global.colormodal.innerHTML = html;
1056 | global.colormodal.classList.toggle("gs_show", true);
1057 | };
1058 |
1059 | const showConfirm = global => {
1060 | hideMessage(global);
1061 | hideColorModal(global);
1062 | hideTooltip(global);
1063 |
1064 | const info = global.productInfo;
1065 | let html = ``;
1066 | html += `

Go to OllaCart
`;
1067 | html += `
${info.name}$${info.price || '0'}
`;
1068 | html += `
1069 |
1070 |

Size notes
1071 |
1072 |
1073 |
1077 |
`;
1078 | if (info.description) html += `
${info.description}
`;
1079 | for (let i = 0; info.photos && (i < info.photos.length); i ++ ) {
1080 | if (i === 0) html += `
`;
1081 | if (info.photos[i])
1082 | html += `
`;
1083 | if (i === info.photos.length - 1) html += `
`;
1084 | }
1085 |
1086 | html += `
`;
1090 |
1091 | html += '
';
1092 | // html += `
You selected item
`;
1093 | html += `
`;
1094 |
1095 | if (global.finish) html += `Added to OllaCart
`;
1096 |
1097 | global.confirm.innerHTML = html;
1098 | global.confirm.classList.toggle("gs_show", true);
1099 | global.showConfirm = true;
1100 |
1101 | if (global.finish) global.confirm.classList.toggle("gs_hide", true);
1102 | else global.confirm.classList.toggle("gs_hide", false);
1103 | };
1104 |
1105 | const showTooltip = global => {
1106 | global.tooltip.classList.toggle("gs_show", true);
1107 | };
1108 |
1109 | const hideTooltip = global => {
1110 | global.tooltip.classList.toggle("gs_show", false);
1111 | };
1112 |
1113 | const hideMessage = global => {
1114 | global.popup.classList.toggle("gs_show", false);
1115 | };
1116 |
1117 | const hideColorModal = global => {
1118 | global.colormodal.classList.toggle("gs_show", false);
1119 | };
1120 |
1121 | const hideConfirm = global => {
1122 | global.confirm.classList.toggle("gs_show", false);
1123 | global.showConfirm = false;
1124 | };
1125 |
1126 | const initMessage = global => {
1127 | addStyle(STYLES);
1128 | global.popup = document.createElement("div");
1129 | global.popup.className = "gs_message";
1130 | document.body.appendChild(global.popup);
1131 |
1132 | global.colormodal = document.createElement("div");
1133 | global.colormodal.className = "gs_message";
1134 | document.body.appendChild(global.colormodal);
1135 |
1136 | global.confirm = document.createElement("div");
1137 | global.confirm.className = "gs_confirm_container";
1138 | document.body.appendChild(global.confirm);
1139 |
1140 | global.tooltip = document.createElement("div");
1141 | global.tooltip.innerHTML = 'Click whenever OllaCart shows appropriate product information. You can manually select and edit information after.';
1142 | global.tooltip.className = "gs_tooltip";
1143 | document.body.appendChild(global.tooltip);
1144 | };
1145 |
1146 | // const API_URL = 'https://www.ollacart.com/api/'
1147 | const API_URL = 'https://ollacart-dev.herokuapp.com/api/';
1148 | // const API_URL2 = 'http://localhost:5000/api/'
1149 |
1150 | const clearClass = (cl) => {
1151 | const itms = document.getElementsByClassName(cl);
1152 | for (let i = itms.length - 1 ; i >= 0; i --) itms[i].classList.remove(cl);
1153 | };
1154 | const addClass = (obj, cl) => {
1155 | const itms = Object.keys(obj).map(key => obj[key]);
1156 | for (let i = 0 ; i < itms.length; i ++) {
1157 | if (!itms[i]) continue;
1158 | itms[i].classList.add(cl);
1159 | }
1160 | };
1161 |
1162 | const copyToTemp = (global) => {
1163 | global.productInfo.temp_photo = '';
1164 | global.tempInfo = {
1165 | ...global.productInfo,
1166 | elements: {...(global.productInfo.elements || {})},
1167 | photos: [...(global.productInfo.photos || [])]
1168 | };
1169 | };
1170 | const copyFromTemp = (global) => {
1171 | const keys = Object.keys(global.productInfo);
1172 | let i = 0;
1173 | for (i = 0; i < keys.length; i ++)
1174 | if (global.productInfo[keys[i]] !== global.tempInfo[keys[i]])
1175 | break;
1176 | if (i === keys.length) return;
1177 | global.productInfo = {
1178 | ...global.tempInfo,
1179 | temp_photo: ''
1180 | };
1181 | if (global.selectMode === 'color') showColorModal(global);
1182 | else showMessage(global);
1183 | };
1184 |
1185 | const toggle = global => {
1186 | const state = !global.state;
1187 | global.state = state;
1188 | global.selectMode = null;
1189 |
1190 | if (state) {
1191 | global.picker.start({
1192 | onHover: global.selectElement,
1193 | onClick: global.domPick
1194 | });
1195 | document.addEventListener('input', global.inputValueChanged);
1196 | document.addEventListener('mousemove', global.onMouseMove);
1197 | } else {
1198 | global.picker.stop();
1199 | document.removeEventListener('input', global.inputValueChanged);
1200 | document.removeEventListener('mousemove', global.onMouseMove);
1201 | }
1202 |
1203 | if (!state) {
1204 | clearClass('gs_copied');
1205 | hideMessage(global);
1206 | hideConfirm(global);
1207 | hideTooltip(global);
1208 | }
1209 | };
1210 |
1211 | const init = global => {
1212 | global.init = true;
1213 | global.state = false;
1214 | global.selectMode = null;
1215 | global.productInfo = {};
1216 | global.tempInfo = {};
1217 | global.picker = new ElementPicker({
1218 | style: {
1219 | background: "rgba(153, 235, 255, 0.5)",
1220 | borderColor: "yellow"
1221 | },
1222 | });
1223 | global.items = ['img', 'name', 'price', 'description', 'photos'];
1224 |
1225 | global.sendAPI = () => {
1226 | const productInfo = global.productInfo;
1227 | if (!productInfo.img || !productInfo.name) return;
1228 |
1229 | const { name, price, description, photos } = productInfo;
1230 | const photo = productInfo.img;
1231 | const url = productInfo.url || findHref(productInfo.elements.e_img) || findHref(productInfo.elements.e_name) || location.href;
1232 | const original_url = location.href;
1233 | const size = productInfo.chooseSize ? productInfo.size : '';
1234 | // console.log('url', url);
1235 |
1236 | fetch(API_URL + 'product/create', {
1237 | method: 'POST',
1238 | headers: {
1239 | 'Accept': 'application/json',
1240 | 'Content-Type': 'application/json'
1241 | },
1242 | body: JSON.stringify({ photo, original_url, url, name, price, description, photos, size, ce_id: localStorage.getItem('ce_id') || '' })
1243 | });
1244 | };
1245 |
1246 | global.popupBtnClicked = (attr, target) => {
1247 | if(!global.showConfirm) copyFromTemp(global);
1248 | if (attr === 'gs__close') {
1249 | toggle(global);
1250 | global.sendClose();
1251 | return;
1252 | }
1253 | if (attr === 'gs__goollacart') {
1254 | window.open('https://www.ollacart.com', '_blank');
1255 | return;
1256 | }
1257 | if (attr === 'gs__confirm') {
1258 | global.sendAPI();
1259 | global.finish = true;
1260 | global.picker.stop();
1261 | showConfirm(global);
1262 | setTimeout(() => {
1263 | global.finish = false;
1264 | toggle(global);
1265 | global.sendClose();
1266 | }, 5000);
1267 | return;
1268 | }
1269 | if (attr === 'gs__color') {
1270 | copyToTemp(global);
1271 | hideConfirm(global);
1272 | global.selectMode = 'color';
1273 | showColorModal(global);
1274 | return;
1275 | }
1276 | if (attr === 'gs__togglecolor') {
1277 | global.productInfo.chooseColor = !global.productInfo.chooseColor;
1278 | showConfirm(global);
1279 | return;
1280 | }
1281 | if (attr === 'gs__togglesize') {
1282 | global.productInfo.chooseSize = !global.productInfo.chooseSize;
1283 | showConfirm(global);
1284 | return;
1285 | }
1286 | if (attr === 'gs__manual') {
1287 | copyToTemp(global);
1288 | hideConfirm(global);
1289 | global.selectMode = 'img';
1290 | showMessage(global);
1291 | return;
1292 | }
1293 | if (attr === 'gs__finish') {
1294 | global.selectMode = '';
1295 | showConfirm(global);
1296 | return;
1297 | }
1298 | if (attr === 'gs__remove') {
1299 | const t = parseInt(target) || 0;
1300 | for (let i = t; i < global.productInfo.photos.length - 1; i ++) {
1301 | global.productInfo.photos[i] = global.productInfo.photos[i + 1];
1302 | global.productInfo.elements['photo' + i] = global.productInfo.elements['photo' + (i + 1)];
1303 | }
1304 | if (global.productInfo.photos.length) {
1305 | global.productInfo.photos.pop();
1306 | delete global.productInfo.elements['photo' + global.productInfo.photos.length];
1307 | }
1308 | copyToTemp(global);
1309 | if (global.showConfirm) showConfirm(global);
1310 | else showMessage(global);
1311 | return;
1312 | }
1313 | let idx = global.items.indexOf(global.selectMode);
1314 | if (attr === 'gs__prev') idx --;
1315 | if (attr === 'gs__next') idx ++;
1316 | if (idx < 0) idx = 0;
1317 | if (idx >= global.items.length) return idx = global.items.length - 1;
1318 |
1319 | global.selectMode = global.items[idx];
1320 |
1321 | if (global.selectMode === 'photos') {
1322 | global.productInfo.elements['temp_photo'] = null;
1323 | global.productInfo.temp_photo = '';
1324 | }
1325 | showMessage(global);
1326 | };
1327 |
1328 | global.selectElement = el => {
1329 | if (!el) return;
1330 | if (el.tagName.toLocaleLowerCase() === 'html') return;
1331 | if (global.finish || !global.popup || global.confirm.contains(el)) return;
1332 | if (global.popup.contains(el) || global.colormodal.contains(el)) {
1333 | if(global.selectMode !== 'photos') copyFromTemp(global);
1334 | return;
1335 | }
1336 |
1337 | if (!global.selectMode) {
1338 | global.productInfo = getProductInfo(el, global.picker);
1339 | } else {
1340 | getProductInfoIndividual(el, global.picker, global);
1341 | }
1342 | if (global.selectMode === 'color') showColorModal(global);
1343 | else showMessage(global);
1344 | };
1345 |
1346 | global.domPick = (el) => {
1347 | console.log('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', el);
1348 | if (!el) return ;
1349 | if (el.tagName.toLocaleLowerCase() === 'html') return;
1350 | if (!global.popup) return;
1351 | if (global.popup.contains(el) || global.confirm.contains(el) || global.colormodal.contains(el)) {
1352 | const attr = el.getAttribute('tag');
1353 | const target = el.getAttribute('target') || '';
1354 | if (attr && attr !== 'gs__text')
1355 | global.popupBtnClicked(attr, target);
1356 | return ;
1357 | }
1358 |
1359 | clearClass('gs_copied');
1360 | if (!global.selectMode) global.productInfo = getProductInfo(el, global.picker);
1361 | addClass(global.productInfo.elements, 'gs_copied');
1362 |
1363 | if (global.selectMode) {
1364 | if (global.selectMode === 'color') {
1365 | copyToTemp(global);
1366 | showColorModal(global);
1367 | return;
1368 | }
1369 | let idx = global.items.indexOf(global.selectMode) + 1;
1370 | if (global.selectMode === 'photos') {
1371 | global.productInfo.elements['photo' + global.productInfo.photos.length] = global.productInfo.elements['temp_photo'];
1372 | global.productInfo.photos.push(global.productInfo.temp_photo);
1373 | idx --;
1374 | }
1375 | global.selectMode = global.items[idx];
1376 | copyToTemp(global);
1377 |
1378 | showMessage(global);
1379 | return ;
1380 | }
1381 | copyToTemp(global);
1382 | showConfirm(global);
1383 | };
1384 |
1385 | global.inputValueChanged = (e) => {
1386 | const tag = e.target.getAttribute("tag");
1387 | const target = e.target.getAttribute("target");
1388 | if (tag === 'gs__text' || !target) {
1389 | global.productInfo[target] = e.target.value;
1390 | global.tempInfo[target] = e.target.value;
1391 | console.log(global.productInfo);
1392 | }
1393 | };
1394 |
1395 | global.onMouseMove = (e) => {
1396 | if(global.selectMode || global.showConfirm) {
1397 | hideTooltip(global);
1398 | return ;
1399 | }
1400 | global.tooltip.style.left = e.clientX + 'px';
1401 | global.tooltip.style.top = e.clientY + 'px';
1402 | showTooltip(global);
1403 | };
1404 |
1405 | addStyle(`
1406 | .gs_hover {
1407 | border: 2px solid #cdcdcd !important;
1408 | background: repeating-linear-gradient( 135deg, rgba(225, 225, 226, 0.3), rgba(229, 229, 229, 0.3) 10px, rgba(173, 173, 173, 0.3) 10px, rgba(172, 172, 172, 0.3) 20px ) !important;
1409 | box-shadow: inset 0px 0px 0px 1px #d7d7d7;
1410 | }
1411 |
1412 | .gs_copied {
1413 | border: 3px solid #ff0a00 !important;
1414 | background: repeating-linear-gradient( 135deg, rgba(183, 240, 200, 0.3), rgba(192, 231, 194, 0.3) 10px, rgba(124, 189, 126, 0.3) 10px, rgba(137, 180, 129, 0.3) 20px ) !important;
1415 | box-shadow: inset 0px 0px 0px 1px #c4d9c2 !important;
1416 | }
1417 | `);
1418 | initMessage(global);
1419 | };
1420 |
1421 | !(() => {
1422 | const global = window.__gs = window.__gs || {};
1423 | // console.log('[Ollacart] Init', global);
1424 | if (!global.init) {
1425 | // console.log("[Ollacart Selector]: Started");
1426 | init(global);
1427 |
1428 | global.sendClose = () => {
1429 | chrome.runtime.sendMessage({type: "close"}, function(response) {
1430 | // console.log(response);
1431 | });
1432 | };
1433 |
1434 | chrome.runtime.sendMessage({type: "init"}, function(response) {
1435 | // console.log(response);
1436 | });
1437 |
1438 | chrome.runtime.onMessage.addListener(
1439 | function(request, sender, sendResponse) {
1440 | // console.log(request);
1441 | switch(request.type) {
1442 | case 'get_state':
1443 | sendResponse(global.state);
1444 | break;
1445 | case 'toggle_state':
1446 | toggle(global);
1447 | sendResponse(global.state);
1448 | case 'ce_id':
1449 | if (request.ce_id)
1450 | localStorage.setItem('ce_id', request.ce_id);
1451 | }
1452 | }
1453 | );
1454 | }
1455 | })();
1456 |
1457 | }());
1458 |
--------------------------------------------------------------------------------
/bin/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "OllaCart",
3 | "version": "1.0.0",
4 | "manifest_version": 3,
5 | "description": "Chrome Extension for Ollacart. Add your items to OllaCart.",
6 | "permissions": ["storage", "tabs", "activeTab"],
7 | "content_scripts": [{
8 | "matches": [""],
9 | "js": ["inject.js"],
10 | "all_frames": false
11 | }],
12 | "background": {
13 | "service_worker": "background.js"
14 | },
15 | "action": { },
16 | "icons": {
17 | "32": "icon_32.png",
18 | "128": "icon_128.png"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getselector",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@medv/finder": {
8 | "version": "1.1.0",
9 | "resolved": "https://registry.npmjs.org/@medv/finder/-/finder-1.1.0.tgz",
10 | "integrity": "sha512-UPjX+hWYTxYQioAMG2xk7Cm/kh/NbPNQaQWjO4a1lS04ns4xMINDxlXljrCt2ODGrtFkGSsU6iVm3+gUK8KT4A==",
11 | "requires": {
12 | "cssesc": "2.0.0"
13 | }
14 | },
15 | "acorn": {
16 | "version": "5.4.1",
17 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz",
18 | "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==",
19 | "dev": true
20 | },
21 | "arr-diff": {
22 | "version": "2.0.0",
23 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
24 | "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
25 | "dev": true,
26 | "requires": {
27 | "arr-flatten": "1.1.0"
28 | }
29 | },
30 | "arr-flatten": {
31 | "version": "1.1.0",
32 | "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
33 | "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
34 | "dev": true
35 | },
36 | "array-unique": {
37 | "version": "0.2.1",
38 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
39 | "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
40 | "dev": true
41 | },
42 | "asynckit": {
43 | "version": "0.4.0",
44 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
45 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
46 | },
47 | "axios": {
48 | "version": "1.6.0",
49 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz",
50 | "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==",
51 | "requires": {
52 | "follow-redirects": "^1.15.0",
53 | "form-data": "^4.0.0",
54 | "proxy-from-env": "^1.1.0"
55 | }
56 | },
57 | "braces": {
58 | "version": "1.8.5",
59 | "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
60 | "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
61 | "dev": true,
62 | "requires": {
63 | "expand-range": "1.8.2",
64 | "preserve": "0.2.0",
65 | "repeat-element": "1.1.2"
66 | }
67 | },
68 | "builtin-modules": {
69 | "version": "1.1.1",
70 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
71 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
72 | "dev": true
73 | },
74 | "combined-stream": {
75 | "version": "1.0.8",
76 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
77 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
78 | "requires": {
79 | "delayed-stream": "~1.0.0"
80 | }
81 | },
82 | "cssesc": {
83 | "version": "2.0.0",
84 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
85 | "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg=="
86 | },
87 | "delayed-stream": {
88 | "version": "1.0.0",
89 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
90 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
91 | },
92 | "estree-walker": {
93 | "version": "0.5.1",
94 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.1.tgz",
95 | "integrity": "sha512-7HgCgz1axW7w5aOvgOQkoR1RMBkllygJrssU3BvymKQ95lxXYv6Pon17fBRDm9qhkvXZGijOULoSF9ShOk/ZLg==",
96 | "dev": true
97 | },
98 | "expand-brackets": {
99 | "version": "0.1.5",
100 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
101 | "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
102 | "dev": true,
103 | "requires": {
104 | "is-posix-bracket": "0.1.1"
105 | }
106 | },
107 | "expand-range": {
108 | "version": "1.8.2",
109 | "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
110 | "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
111 | "dev": true,
112 | "requires": {
113 | "fill-range": "2.2.3"
114 | }
115 | },
116 | "extglob": {
117 | "version": "0.3.2",
118 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
119 | "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
120 | "dev": true,
121 | "requires": {
122 | "is-extglob": "1.0.0"
123 | }
124 | },
125 | "filename-regex": {
126 | "version": "2.0.1",
127 | "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
128 | "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
129 | "dev": true
130 | },
131 | "fill-range": {
132 | "version": "2.2.3",
133 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
134 | "integrity": "sha512-P1WnpaJQ8BQdSEIjEmgyCHm9ESwkO6sMu+0Moa4s0u9B+iQ5M9tBbbCYvWmF7vRvqyMO2ENqC+w4Hev8wErQcg==",
135 | "dev": true,
136 | "requires": {
137 | "is-number": "^2.1.0",
138 | "isobject": "^2.0.0",
139 | "randomatic": "^1.1.3",
140 | "repeat-element": "^1.1.2",
141 | "repeat-string": "^1.5.2"
142 | }
143 | },
144 | "follow-redirects": {
145 | "version": "1.15.6",
146 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
147 | "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA=="
148 | },
149 | "for-in": {
150 | "version": "1.0.2",
151 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
152 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
153 | "dev": true
154 | },
155 | "for-own": {
156 | "version": "0.1.5",
157 | "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
158 | "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
159 | "dev": true,
160 | "requires": {
161 | "for-in": "1.0.2"
162 | }
163 | },
164 | "form-data": {
165 | "version": "4.0.0",
166 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
167 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
168 | "requires": {
169 | "asynckit": "^0.4.0",
170 | "combined-stream": "^1.0.8",
171 | "mime-types": "^2.1.12"
172 | }
173 | },
174 | "glob-base": {
175 | "version": "0.3.0",
176 | "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
177 | "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
178 | "dev": true,
179 | "requires": {
180 | "glob-parent": "2.0.0",
181 | "is-glob": "2.0.1"
182 | }
183 | },
184 | "glob-parent": {
185 | "version": "2.0.0",
186 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
187 | "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
188 | "dev": true,
189 | "requires": {
190 | "is-glob": "2.0.1"
191 | }
192 | },
193 | "is-buffer": {
194 | "version": "1.1.6",
195 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
196 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
197 | "dev": true
198 | },
199 | "is-dotfile": {
200 | "version": "1.0.3",
201 | "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
202 | "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
203 | "dev": true
204 | },
205 | "is-equal-shallow": {
206 | "version": "0.1.3",
207 | "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
208 | "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
209 | "dev": true,
210 | "requires": {
211 | "is-primitive": "2.0.0"
212 | }
213 | },
214 | "is-extendable": {
215 | "version": "0.1.1",
216 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
217 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
218 | "dev": true
219 | },
220 | "is-extglob": {
221 | "version": "1.0.0",
222 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
223 | "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
224 | "dev": true
225 | },
226 | "is-glob": {
227 | "version": "2.0.1",
228 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
229 | "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
230 | "dev": true,
231 | "requires": {
232 | "is-extglob": "1.0.0"
233 | }
234 | },
235 | "is-module": {
236 | "version": "1.0.0",
237 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
238 | "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
239 | "dev": true
240 | },
241 | "is-number": {
242 | "version": "2.1.0",
243 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
244 | "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
245 | "dev": true,
246 | "requires": {
247 | "kind-of": "3.2.2"
248 | }
249 | },
250 | "is-posix-bracket": {
251 | "version": "0.1.1",
252 | "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
253 | "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
254 | "dev": true
255 | },
256 | "is-primitive": {
257 | "version": "2.0.0",
258 | "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
259 | "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
260 | "dev": true
261 | },
262 | "isarray": {
263 | "version": "1.0.0",
264 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
265 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
266 | "dev": true
267 | },
268 | "isobject": {
269 | "version": "2.1.0",
270 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
271 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
272 | "dev": true,
273 | "requires": {
274 | "isarray": "1.0.0"
275 | }
276 | },
277 | "kind-of": {
278 | "version": "3.2.2",
279 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
280 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
281 | "dev": true,
282 | "requires": {
283 | "is-buffer": "1.1.6"
284 | }
285 | },
286 | "lodash": {
287 | "version": "4.17.21",
288 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
289 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
290 | },
291 | "magic-string": {
292 | "version": "0.22.4",
293 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz",
294 | "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==",
295 | "dev": true,
296 | "requires": {
297 | "vlq": "0.2.3"
298 | }
299 | },
300 | "micromatch": {
301 | "version": "2.3.11",
302 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
303 | "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
304 | "dev": true,
305 | "requires": {
306 | "arr-diff": "2.0.0",
307 | "array-unique": "0.2.1",
308 | "braces": "1.8.5",
309 | "expand-brackets": "0.1.5",
310 | "extglob": "0.3.2",
311 | "filename-regex": "2.0.1",
312 | "is-extglob": "1.0.0",
313 | "is-glob": "2.0.1",
314 | "kind-of": "3.2.2",
315 | "normalize-path": "2.1.1",
316 | "object.omit": "2.0.1",
317 | "parse-glob": "3.0.4",
318 | "regex-cache": "0.4.4"
319 | }
320 | },
321 | "mime-db": {
322 | "version": "1.52.0",
323 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
324 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
325 | },
326 | "mime-types": {
327 | "version": "2.1.35",
328 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
329 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
330 | "requires": {
331 | "mime-db": "1.52.0"
332 | }
333 | },
334 | "normalize-path": {
335 | "version": "2.1.1",
336 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
337 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
338 | "dev": true,
339 | "requires": {
340 | "remove-trailing-separator": "1.1.0"
341 | }
342 | },
343 | "object.omit": {
344 | "version": "2.0.1",
345 | "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
346 | "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
347 | "dev": true,
348 | "requires": {
349 | "for-own": "0.1.5",
350 | "is-extendable": "0.1.1"
351 | }
352 | },
353 | "parse-glob": {
354 | "version": "3.0.4",
355 | "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
356 | "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
357 | "dev": true,
358 | "requires": {
359 | "glob-base": "0.3.0",
360 | "is-dotfile": "1.0.3",
361 | "is-extglob": "1.0.0",
362 | "is-glob": "2.0.1"
363 | }
364 | },
365 | "path-parse": {
366 | "version": "1.0.5",
367 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
368 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
369 | "dev": true
370 | },
371 | "preserve": {
372 | "version": "0.2.0",
373 | "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
374 | "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
375 | "dev": true
376 | },
377 | "proxy-from-env": {
378 | "version": "1.1.0",
379 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
380 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
381 | },
382 | "randomatic": {
383 | "version": "1.1.7",
384 | "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
385 | "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
386 | "dev": true,
387 | "requires": {
388 | "is-number": "3.0.0",
389 | "kind-of": "4.0.0"
390 | },
391 | "dependencies": {
392 | "is-number": {
393 | "version": "3.0.0",
394 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
395 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
396 | "dev": true,
397 | "requires": {
398 | "kind-of": "3.2.2"
399 | },
400 | "dependencies": {
401 | "kind-of": {
402 | "version": "3.2.2",
403 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
404 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
405 | "dev": true,
406 | "requires": {
407 | "is-buffer": "1.1.6"
408 | }
409 | }
410 | }
411 | },
412 | "kind-of": {
413 | "version": "4.0.0",
414 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
415 | "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
416 | "dev": true,
417 | "requires": {
418 | "is-buffer": "1.1.6"
419 | }
420 | }
421 | }
422 | },
423 | "regex-cache": {
424 | "version": "0.4.4",
425 | "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
426 | "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
427 | "dev": true,
428 | "requires": {
429 | "is-equal-shallow": "0.1.3"
430 | }
431 | },
432 | "remove-trailing-separator": {
433 | "version": "1.1.0",
434 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
435 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
436 | "dev": true
437 | },
438 | "repeat-element": {
439 | "version": "1.1.2",
440 | "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
441 | "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
442 | "dev": true
443 | },
444 | "repeat-string": {
445 | "version": "1.6.1",
446 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
447 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
448 | "dev": true
449 | },
450 | "resolve": {
451 | "version": "1.5.0",
452 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
453 | "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
454 | "dev": true,
455 | "requires": {
456 | "path-parse": "1.0.5"
457 | }
458 | },
459 | "rollup": {
460 | "version": "0.56.2",
461 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.56.2.tgz",
462 | "integrity": "sha512-vZIn0P+xA1glmc4DwRsUC9ce6SSE5gZT2YKaRiSYHwJXHcRtXWHOvrY2NtUR8Gk+EoszyyoXMfw9OrYCCKCYCA==",
463 | "dev": true
464 | },
465 | "rollup-plugin-commonjs": {
466 | "version": "8.3.0",
467 | "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.3.0.tgz",
468 | "integrity": "sha512-PYs3OiYgENFYEmI3vOEm5nrp3eY90YZqd5vGmQqeXmhJsAWFIrFdROCvOasqJ1HgeTvqyYo9IGXnFDyoboNcgQ==",
469 | "dev": true,
470 | "requires": {
471 | "acorn": "5.4.1",
472 | "estree-walker": "0.5.1",
473 | "magic-string": "0.22.4",
474 | "resolve": "1.5.0",
475 | "rollup-pluginutils": "2.0.1"
476 | }
477 | },
478 | "rollup-plugin-node-resolve": {
479 | "version": "3.0.3",
480 | "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.3.tgz",
481 | "integrity": "sha512-qJLXJ1aASV6p8SrEfRdQdHmb5OQmqXyIWIdVGcju8QFzftSsHcuL554Vy+n8mr0fZCC+ksO6aWJ7TAVl2F+Qwg==",
482 | "dev": true,
483 | "requires": {
484 | "builtin-modules": "1.1.1",
485 | "is-module": "1.0.0",
486 | "resolve": "1.5.0"
487 | }
488 | },
489 | "rollup-pluginutils": {
490 | "version": "2.0.1",
491 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz",
492 | "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=",
493 | "dev": true,
494 | "requires": {
495 | "estree-walker": "0.3.1",
496 | "micromatch": "2.3.11"
497 | },
498 | "dependencies": {
499 | "estree-walker": {
500 | "version": "0.3.1",
501 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz",
502 | "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=",
503 | "dev": true
504 | }
505 | }
506 | },
507 | "vlq": {
508 | "version": "0.2.3",
509 | "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
510 | "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
511 | "dev": true
512 | }
513 | }
514 | }
515 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getselector",
3 | "version": "1.0.0",
4 | "description": "Get Selector Browser Extension",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "copy": "del /f /q .\\bin && rd /q .\\bin && mkdir .\\bin && copy src\\manifest.json bin\\manifest.json && copy src\\background.js bin\\background.js && copy src\\*.png bin\\",
9 | "build": "npm run copy && ./node_modules/.bin/rollup -c rollup.config.js"
10 | },
11 | "keywords": [
12 | "get",
13 | "css",
14 | "selector",
15 | "find",
16 | "unique",
17 | "browser",
18 | "extension"
19 | ],
20 | "author": "AAA",
21 | "devDependencies": {
22 | "rollup": "^0.56.2",
23 | "rollup-plugin-commonjs": "^8.3.0",
24 | "rollup-plugin-node-resolve": "^3.0.3"
25 | },
26 | "dependencies": {
27 | "@medv/finder": "^1.1.0",
28 | "axios": "^1.6.0",
29 | "lodash": "^4.17.21"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-node-resolve';
2 | import commonjs from 'rollup-plugin-commonjs';
3 |
4 | export default {
5 | input: 'src/index.js',
6 | output: {
7 | format: 'iife',
8 | file: 'bin/inject.js',
9 | name: 'getselector'
10 | },
11 | plugins: [
12 | resolve(),
13 | commonjs({
14 | exclude: [],
15 | include: [
16 | 'node_modules/**'
17 | ]
18 | })
19 | ]
20 | };
21 |
--------------------------------------------------------------------------------
/src/addStyle.js:
--------------------------------------------------------------------------------
1 | export const addStyle = style => {
2 | const styleTag = document.createElement('style');
3 | styleTag.innerHTML = style;
4 | document.head.appendChild(styleTag);
5 | };
6 |
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | import debounce from "lodash/debounce";
2 | import { ElementPicker } from "./dom-pick";
3 | import { addStyle } from "./addStyle";
4 | import { findHref, getProductInfo, getProductInfoIndividual } from "./scrap";
5 | import { initMessage, showMessage, showColorModal, showConfirm, showTooltip, hideMessage, hideColorModal, hideConfirm, hideTooltip } from "./info";
6 |
7 | // const API_URL = 'https://www.ollacart.com/api/'
8 | const API_URL = 'https://ollacart-dev.herokuapp.com/api/'
9 | // const API_URL2 = 'http://localhost:5000/api/'
10 |
11 | const clearClass = (cl) => {
12 | const itms = document.getElementsByClassName(cl);
13 | for (let i = itms.length - 1 ; i >= 0; i --) itms[i].classList.remove(cl);
14 | }
15 | const addClass = (obj, cl) => {
16 | const itms = Object.keys(obj).map(key => obj[key]);
17 | for (let i = 0 ; i < itms.length; i ++) {
18 | if (!itms[i]) continue;
19 | itms[i].classList.add(cl);
20 | }
21 | }
22 |
23 | const copyToTemp = (global) => {
24 | global.productInfo.temp_photo = '';
25 | global.tempInfo = {
26 | ...global.productInfo,
27 | elements: {...(global.productInfo.elements || {})},
28 | photos: [...(global.productInfo.photos || [])]
29 | }
30 | }
31 | const copyFromTemp = (global) => {
32 | const keys = Object.keys(global.productInfo);
33 | let i = 0;
34 | for (i = 0; i < keys.length; i ++)
35 | if (global.productInfo[keys[i]] !== global.tempInfo[keys[i]])
36 | break;
37 | if (i === keys.length) return;
38 | global.productInfo = {
39 | ...global.tempInfo,
40 | temp_photo: ''
41 | }
42 | if (global.selectMode === 'color') showColorModal(global);
43 | else showMessage(global);
44 | }
45 |
46 | export const toggle = global => {
47 | const state = !global.state;
48 | global.state = state;
49 | global.selectMode = null;
50 |
51 | if (state) {
52 | global.picker.start({
53 | onHover: global.selectElement,
54 | onClick: global.domPick
55 | });
56 | document.addEventListener('input', global.inputValueChanged);
57 | document.addEventListener('mousemove', global.onMouseMove);
58 | } else {
59 | global.picker.stop();
60 | document.removeEventListener('input', global.inputValueChanged);
61 | document.removeEventListener('mousemove', global.onMouseMove);
62 | }
63 |
64 | if (!state) {
65 | clearClass('gs_copied');
66 | hideMessage(global);
67 | hideConfirm(global);
68 | hideTooltip(global);
69 | }
70 | };
71 |
72 | export const init = global => {
73 | global.init = true;
74 | global.state = false;
75 | global.selectMode = null;
76 | global.productInfo = {};
77 | global.tempInfo = {};
78 | global.picker = new ElementPicker({
79 | style: {
80 | background: "rgba(153, 235, 255, 0.5)",
81 | borderColor: "yellow"
82 | },
83 | });
84 | global.items = ['img', 'name', 'price', 'description', 'photos'];
85 |
86 | global.sendAPI = () => {
87 | const productInfo = global.productInfo;
88 | if (!productInfo.img || !productInfo.name) return;
89 |
90 | const { name, price, description, photos } = productInfo;
91 | const photo = productInfo.img;
92 | const url = productInfo.url || findHref(productInfo.elements.e_img) || findHref(productInfo.elements.e_name) || location.href;
93 | const original_url = location.href;
94 | const size = productInfo.chooseSize ? productInfo.size : '';
95 | // console.log('url', url);
96 |
97 | fetch(API_URL + 'product/create', {
98 | method: 'POST',
99 | headers: {
100 | 'Accept': 'application/json',
101 | 'Content-Type': 'application/json'
102 | },
103 | body: JSON.stringify({ photo, original_url, url, name, price, description, photos, size, ce_id: localStorage.getItem('ce_id') || '' })
104 | });
105 | }
106 |
107 | global.popupBtnClicked = (attr, target) => {
108 | if(!global.showConfirm) copyFromTemp(global);
109 | if (attr === 'gs__close') {
110 | toggle(global);
111 | global.sendClose();
112 | return;
113 | }
114 | if (attr === 'gs__goollacart') {
115 | window.open('https://www.ollacart.com', '_blank');
116 | return;
117 | }
118 | if (attr === 'gs__confirm') {
119 | global.sendAPI();
120 | global.finish = true;
121 | global.picker.stop();
122 | showConfirm(global);
123 | setTimeout(() => {
124 | global.finish = false;
125 | toggle(global);
126 | global.sendClose();
127 | }, 5000);
128 | return;
129 | }
130 | if (attr === 'gs__color') {
131 | copyToTemp(global);
132 | hideConfirm(global);
133 | global.selectMode = 'color';
134 | showColorModal(global);
135 | return;
136 | }
137 | if (attr === 'gs__togglecolor') {
138 | global.productInfo.chooseColor = !global.productInfo.chooseColor;
139 | showConfirm(global);
140 | return;
141 | }
142 | if (attr === 'gs__togglesize') {
143 | global.productInfo.chooseSize = !global.productInfo.chooseSize;
144 | showConfirm(global);
145 | return;
146 | }
147 | if (attr === 'gs__manual') {
148 | copyToTemp(global);
149 | hideConfirm(global);
150 | global.selectMode = 'img';
151 | showMessage(global);
152 | return;
153 | }
154 | if (attr === 'gs__finish') {
155 | global.selectMode = '';
156 | showConfirm(global);
157 | return;
158 | }
159 | if (attr === 'gs__remove') {
160 | const t = parseInt(target) || 0;
161 | for (let i = t; i < global.productInfo.photos.length - 1; i ++) {
162 | global.productInfo.photos[i] = global.productInfo.photos[i + 1]
163 | global.productInfo.elements['photo' + i] = global.productInfo.elements['photo' + (i + 1)];
164 | }
165 | if (global.productInfo.photos.length) {
166 | global.productInfo.photos.pop();
167 | delete global.productInfo.elements['photo' + global.productInfo.photos.length];
168 | }
169 | copyToTemp(global);
170 | if (global.showConfirm) showConfirm(global);
171 | else showMessage(global);
172 | return;
173 | }
174 | let idx = global.items.indexOf(global.selectMode);
175 | if (attr === 'gs__prev') idx --;
176 | if (attr === 'gs__next') idx ++;
177 | if (idx < 0) idx = 0;
178 | if (idx >= global.items.length) return idx = global.items.length - 1;
179 |
180 | global.selectMode = global.items[idx];
181 |
182 | if (global.selectMode === 'photos') {
183 | global.productInfo.elements['temp_photo'] = null;
184 | global.productInfo.temp_photo = '';
185 | }
186 | showMessage(global);
187 | }
188 |
189 | global.selectElement = el => {
190 | if (!el) return;
191 | if (el.tagName.toLocaleLowerCase() === 'html') return;
192 | if (global.finish || !global.popup || global.confirm.contains(el)) return;
193 | if (global.popup.contains(el) || global.colormodal.contains(el)) {
194 | if(global.selectMode !== 'photos') copyFromTemp(global);
195 | return;
196 | }
197 |
198 | if (!global.selectMode) {
199 | global.productInfo = getProductInfo(el, global.picker);
200 | } else {
201 | getProductInfoIndividual(el, global.picker, global);
202 | }
203 | if (global.selectMode === 'color') showColorModal(global);
204 | else showMessage(global);
205 | }
206 |
207 | global.domPick = (el) => {
208 | console.log('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', el);
209 | if (!el) return ;
210 | if (el.tagName.toLocaleLowerCase() === 'html') return;
211 | if (!global.popup) return;
212 | if (global.popup.contains(el) || global.confirm.contains(el) || global.colormodal.contains(el)) {
213 | const attr = el.getAttribute('tag')
214 | const target = el.getAttribute('target') || '';
215 | if (attr && attr !== 'gs__text')
216 | global.popupBtnClicked(attr, target);
217 | return ;
218 | }
219 |
220 | clearClass('gs_copied');
221 | if (!global.selectMode) global.productInfo = getProductInfo(el, global.picker);
222 | addClass(global.productInfo.elements, 'gs_copied')
223 |
224 | if (global.selectMode) {
225 | if (global.selectMode === 'color') {
226 | copyToTemp(global);
227 | showColorModal(global);
228 | return;
229 | }
230 | let idx = global.items.indexOf(global.selectMode) + 1;
231 | if (global.selectMode === 'photos') {
232 | global.productInfo.elements['photo' + global.productInfo.photos.length] = global.productInfo.elements['temp_photo'];
233 | global.productInfo.photos.push(global.productInfo.temp_photo);
234 | idx --;
235 | }
236 | global.selectMode = global.items[idx];
237 | copyToTemp(global);
238 |
239 | showMessage(global);
240 | return ;
241 | }
242 | copyToTemp(global);
243 | showConfirm(global);
244 | };
245 |
246 | global.inputValueChanged = (e) => {
247 | const tag = e.target.getAttribute("tag");
248 | const target = e.target.getAttribute("target");
249 | if (tag === 'gs__text' || !target) {
250 | global.productInfo[target] = e.target.value;
251 | global.tempInfo[target] = e.target.value;
252 | console.log(global.productInfo)
253 | }
254 | }
255 |
256 | global.onMouseMove = (e) => {
257 | if(global.selectMode || global.showConfirm) {
258 | hideTooltip(global);
259 | return ;
260 | }
261 | global.tooltip.style.left = e.clientX + 'px';
262 | global.tooltip.style.top = e.clientY + 'px';
263 | showTooltip(global);
264 | }
265 |
266 | addStyle(`
267 | .gs_hover {
268 | border: 2px solid #cdcdcd !important;
269 | background: repeating-linear-gradient( 135deg, rgba(225, 225, 226, 0.3), rgba(229, 229, 229, 0.3) 10px, rgba(173, 173, 173, 0.3) 10px, rgba(172, 172, 172, 0.3) 20px ) !important;
270 | box-shadow: inset 0px 0px 0px 1px #d7d7d7;
271 | }
272 |
273 | .gs_copied {
274 | border: 3px solid #ff0a00 !important;
275 | background: repeating-linear-gradient( 135deg, rgba(183, 240, 200, 0.3), rgba(192, 231, 194, 0.3) 10px, rgba(124, 189, 126, 0.3) 10px, rgba(137, 180, 129, 0.3) 20px ) !important;
276 | box-shadow: inset 0px 0px 0px 1px #c4d9c2 !important;
277 | }
278 | `);
279 | initMessage(global);
280 | };
281 |
--------------------------------------------------------------------------------
/src/background.js:
--------------------------------------------------------------------------------
1 | const updateIcon = async isPressed => {
2 | await chrome.action.setIcon({ path: `icon_128${isPressed ? "_pressed" : ""}.png` });
3 | }
4 |
5 | const sendMessage = data => {
6 | return new Promise(resolve => {
7 | chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
8 | if (tabs.length === 0) resolve();
9 | chrome.tabs.sendMessage(tabs[0].id, data, function(response) {
10 | resolve(response);
11 | });
12 | });
13 | });
14 | }
15 |
16 | const generateCeID = () => {
17 | return Date.now() + '_' + parseInt(Math.random() * 10000) + '_' + parseInt(Math.random() * 10000);
18 | }
19 |
20 | const getCeID = () => {
21 | return new Promise(resolve => {
22 | chrome.storage.local.get(["ce_id"], async function(result){
23 | if (result.ce_id && result.ce_id.length > 10) return resolve(result.ce_id);
24 | const ce_id = generateCeID();
25 | chrome.storage.local.set({ ce_id }, async function(result){
26 | resolve(ce_id)
27 | });
28 | });
29 | });
30 | }
31 |
32 | const getCurrentState = async () => {
33 | return await sendMessage({ type: 'get_state' });
34 | }
35 |
36 | const toggleState = async () => {
37 | return await sendMessage({ type: 'toggle_state' });
38 | }
39 |
40 | const currentTabChanged = async () => {
41 | await updateIcon(await getCurrentState());
42 | const ce_id = await getCeID();
43 | await sendMessage({ type: 'ce_id', ce_id });
44 | }
45 |
46 | chrome.tabs.onUpdated.addListener(async function(tabId, changeInfo, tab) {
47 | if (changeInfo.status === 'complete') {
48 | await currentTabChanged();
49 | }
50 | });
51 |
52 | chrome.tabs.onActivated.addListener(async tab => {
53 | await currentTabChanged();
54 | });
55 |
56 | chrome.runtime.onInstalled.addListener(async ({ reason, version }) => {
57 | if (reason === chrome.runtime.OnInstalledReason.INSTALL) {
58 | }
59 | });
60 |
61 | chrome.action.onClicked.addListener(async (tab) => {
62 | const state = await toggleState();
63 | await updateIcon(state);
64 | });
65 |
66 | chrome.runtime.onMessage.addListener(
67 | async function(request, sender, sendResponse) { //sender.tab
68 | switch(request.type) {
69 | case 'init':
70 | sendResponse({ type: "init" });
71 | break;
72 | case 'close':
73 | sendResponse({ type: "close" });
74 | await updateIcon(false);
75 | break;
76 | }
77 | }
78 | );
79 |
80 |
--------------------------------------------------------------------------------
/src/dom-pick/element-overlay.d.ts:
--------------------------------------------------------------------------------
1 | import { BoundingBox, ElementOverlayOptions } from "./utils";
2 | export default class ElementOverlay {
3 | overlay: HTMLDivElement;
4 | shadowContainer: HTMLDivElement;
5 | shadowRoot: ShadowRoot;
6 | usingShadowDOM?: boolean;
7 | constructor(options: ElementOverlayOptions);
8 | addToDOM(parent: Node, useShadowDOM: boolean): void;
9 | removeFromDOM(): void;
10 | captureCursor(): void;
11 | ignoreCursor(): void;
12 | setBounds({ x, y, width, height }: BoundingBox): void;
13 | getBounds(): BoundingBox
14 | }
15 |
--------------------------------------------------------------------------------
/src/dom-pick/element-overlay.js:
--------------------------------------------------------------------------------
1 | export default class ElementOverlay {
2 | constructor(options) {
3 | var _a, _b, _c, _d, _e, _f, _g, _h, _j;
4 | this.overlay = document.createElement("div");
5 | this.overlay.className = options.className || "_ext-element-overlay";
6 | this.overlay.style.background = ((_a = options.style) === null || _a === void 0 ? void 0 : _a.background) || "rgba(250, 240, 202, 0.2)";
7 | this.overlay.style.borderColor = ((_b = options.style) === null || _b === void 0 ? void 0 : _b.borderColor) || "#F95738";
8 | this.overlay.style.borderStyle = ((_c = options.style) === null || _c === void 0 ? void 0 : _c.borderStyle) || "solid";
9 | this.overlay.style.borderRadius = ((_d = options.style) === null || _d === void 0 ? void 0 : _d.borderRadius) || "1px";
10 | this.overlay.style.borderWidth = ((_e = options.style) === null || _e === void 0 ? void 0 : _e.borderWidth) || "1px";
11 | this.overlay.style.boxSizing = ((_f = options.style) === null || _f === void 0 ? void 0 : _f.boxSizing) || "border-box";
12 | this.overlay.style.cursor = ((_g = options.style) === null || _g === void 0 ? void 0 : _g.cursor) || "crosshair";
13 | this.overlay.style.position = ((_h = options.style) === null || _h === void 0 ? void 0 : _h.position) || "absolute";
14 | this.overlay.style.zIndex = ((_j = options.style) === null || _j === void 0 ? void 0 : _j.zIndex) || "2147483647";
15 | // this.overlay.style.transition = "all .2s linear";
16 | this.shadowContainer = document.createElement("div");
17 | this.shadowContainer.className = "_ext-element-overlay-container";
18 | this.shadowContainer.style.position = "absolute";
19 | this.shadowContainer.style.top = "0px";
20 | this.shadowContainer.style.left = "0px";
21 | this.shadowRoot = this.shadowContainer.attachShadow({ mode: "open" });
22 | }
23 | addToDOM(parent, useShadowDOM) {
24 | this.usingShadowDOM = useShadowDOM;
25 | if (useShadowDOM) {
26 | parent.insertBefore(this.shadowContainer, parent.firstChild);
27 | this.shadowRoot.appendChild(this.overlay);
28 | }
29 | else {
30 | parent.appendChild(this.overlay);
31 | }
32 | }
33 | removeFromDOM() {
34 | this.setBounds({ x: 0, y: 0, width: 0, height: 0 });
35 | this.overlay.remove();
36 | if (this.usingShadowDOM) {
37 | this.shadowContainer.remove();
38 | }
39 | }
40 | captureCursor() {
41 | this.overlay.style.pointerEvents = "auto";
42 | }
43 | ignoreCursor() {
44 | this.overlay.style.pointerEvents = "none";
45 | }
46 | setBounds({ x, y, width, height }) {
47 | this.overlay.style.left = x + "px";
48 | this.overlay.style.top = y + "px";
49 | this.overlay.style.width = width + "px";
50 | this.overlay.style.height = height + "px";
51 | }
52 | getBounds() {
53 | return {
54 | x: parseFloat(this.overlay.style.left),
55 | y: parseFloat(this.overlay.style.top),
56 | width: parseFloat(this.overlay.style.width),
57 | height: parseFloat(this.overlay.style.height),
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/dom-pick/element-picker.d.ts:
--------------------------------------------------------------------------------
1 | import { ElementOverlayOptions } from "./utils";
2 | declare type ElementCallback = (el: HTMLElement) => T;
3 | declare type ElementPickerOptions = {
4 | parentElement?: Node;
5 | useShadowDOM?: boolean;
6 | onClick?: ElementCallback;
7 | onHover?: ElementCallback;
8 | elementFilter?: ElementCallback;
9 | };
10 | export default class ElementPicker {
11 | private overlay;
12 | private active;
13 | private options?;
14 | private target?;
15 | private mouseX?;
16 | private mouseY?;
17 | private tickReq?;
18 | constructor(overlayOptions?: ElementOverlayOptions);
19 | start(options: ElementPickerOptions): boolean;
20 | stop(): void;
21 | private handleMouseMove;
22 | private handleClick;
23 | private tick;
24 | private updateTarget;
25 | }
26 | export {};
27 |
--------------------------------------------------------------------------------
/src/dom-pick/element-picker.js:
--------------------------------------------------------------------------------
1 | import ElementOverlay from "./element-overlay";
2 | import { getElementBounds, checkSimilarBounds } from "./utils";
3 | export default class ElementPicker {
4 | constructor(overlayOptions) {
5 | this.handleMouseMove = (event) => {
6 | this.mouseX = event.clientX;
7 | this.mouseY = event.clientY;
8 | };
9 | this.handleClick = (event) => {
10 | var _a;
11 | if (this.target && this.target.getAttribute('gsallow')) return;
12 | if (this.target && ((_a = this.options) === null || _a === void 0 ? void 0 : _a.onClick)) {
13 | this.options.onClick(this.target);
14 | }
15 | event.preventDefault();
16 | };
17 | this.tick = () => {
18 | this.updateTarget();
19 | this.tickReq = window.requestAnimationFrame(this.tick);
20 | };
21 | this.active = false;
22 | this.overlay = new ElementOverlay(overlayOptions !== null && overlayOptions !== void 0 ? overlayOptions : {});
23 | }
24 | start(options) {
25 | var _a, _b;
26 | if (this.active) {
27 | return false;
28 | }
29 | this.active = true;
30 | this.options = options;
31 | document.addEventListener("mousemove", this.handleMouseMove, true);
32 | document.addEventListener("click", this.handleClick, true);
33 | this.overlay.addToDOM((_a = options.parentElement) !== null && _a !== void 0 ? _a : document.body, (_b = options.useShadowDOM) !== null && _b !== void 0 ? _b : true);
34 | this.tick();
35 | return true;
36 | }
37 | stop() {
38 | this.active = false;
39 | this.options = undefined;
40 | document.removeEventListener("mousemove", this.handleMouseMove, true);
41 | document.removeEventListener("click", this.handleClick, true);
42 | this.overlay.removeFromDOM();
43 | this.target = undefined;
44 | this.mouseX = undefined;
45 | this.mouseY = undefined;
46 | if (this.tickReq) {
47 | window.cancelAnimationFrame(this.tickReq);
48 | }
49 | }
50 | updateTarget() {
51 | var _a, _b;
52 | if (this.mouseX === undefined || this.mouseY === undefined) {
53 | return;
54 | }
55 | // Peek through the overlay to find the new target
56 | this.overlay.ignoreCursor();
57 | const elAtCursor = document.elementFromPoint(this.mouseX, this.mouseY);
58 | const newTarget = elAtCursor;
59 | this.overlay.captureCursor();
60 | // If the target hasn't changed, there's nothing to do
61 | if (!newTarget) return;
62 | // If we have an element filter and the new target doesn't match,
63 | // clear out the target
64 | if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.elementFilter) {
65 | if (!this.options.elementFilter(newTarget)) {
66 | this.target = undefined;
67 | this.overlay.setBounds({ x: 0, y: 0, width: 0, height: 0 });
68 | return;
69 | }
70 | }
71 |
72 | const bounds = getElementBounds(newTarget);
73 | if (newTarget === this.target) {
74 | const ori_bounds = this.overlay.getBounds();
75 | if (checkSimilarBounds(bounds, ori_bounds))
76 | return ;
77 | }
78 |
79 | this.target = newTarget;
80 | this.overlay.setBounds(bounds);
81 | if ((_b = this.options) === null || _b === void 0 ? void 0 : _b.onHover) {
82 | this.options.onHover(newTarget);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/dom-pick/index.d.ts:
--------------------------------------------------------------------------------
1 | import ElementPicker from "./element-picker";
2 | export { ElementPicker };
3 |
--------------------------------------------------------------------------------
/src/dom-pick/index.js:
--------------------------------------------------------------------------------
1 | import ElementPicker from "./element-picker";
2 | export { ElementPicker };
3 |
--------------------------------------------------------------------------------
/src/dom-pick/utils.d.ts:
--------------------------------------------------------------------------------
1 | export interface BoundingBox {
2 | x: number;
3 | y: number;
4 | width: number;
5 | height: number;
6 | }
7 | export interface ElementOverlayStyleOptions {
8 | background?: string;
9 | borderColor?: string;
10 | borderStyle?: string;
11 | borderRadius?: string;
12 | borderWidth?: string;
13 | boxSizing?: string;
14 | cursor?: string;
15 | position?: string;
16 | zIndex?: string;
17 | }
18 | export declare type ElementOverlayOptions = {
19 | className?: string;
20 | style?: ElementOverlayStyleOptions;
21 | };
22 | export declare const getElementBounds: (el: HTMLElement) => BoundingBox;
23 | export declare const checkSimilarBounds: (b1: BoundingBox, b2: BoundingBox) => boolean
24 |
--------------------------------------------------------------------------------
/src/dom-pick/utils.js:
--------------------------------------------------------------------------------
1 | ;
2 | export const getElementBounds = (el) => {
3 | const rect = el.getBoundingClientRect();
4 | return {
5 | x: window.pageXOffset + rect.left,
6 | y: window.pageYOffset + rect.top,
7 | width: el.offsetWidth,
8 | height: el.offsetHeight,
9 | };
10 | };
11 |
12 | export const checkSimilarBounds = (b1, b2) => {
13 | const keys = ['x', 'y', 'width', 'height'];
14 | for (let i = 0 ; i < keys.length; i ++) {
15 | if (Math.abs(b1[keys[i]] - b2[keys[i]]) > 0.1 )
16 | return false;
17 | }
18 | return true;
19 | }
--------------------------------------------------------------------------------
/src/icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AAA0109/DomPicker_Extension/563b131f70fa977fe29ffc16e414c3ec75c98afc/src/icon_128.png
--------------------------------------------------------------------------------
/src/icon_128_pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AAA0109/DomPicker_Extension/563b131f70fa977fe29ffc16e414c3ec75c98afc/src/icon_128_pressed.png
--------------------------------------------------------------------------------
/src/icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AAA0109/DomPicker_Extension/563b131f70fa977fe29ffc16e414c3ec75c98afc/src/icon_32.png
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { init, toggle } from "./app";
2 |
3 | !(() => {
4 | const global = window.__gs = window.__gs || {};
5 | // console.log('[Ollacart] Init', global);
6 | if (!global.init) {
7 | // console.log("[Ollacart Selector]: Started");
8 | init(global);
9 |
10 | global.sendClose = () => {
11 | chrome.runtime.sendMessage({type: "close"}, function(response) {
12 | // console.log(response);
13 | });
14 | }
15 |
16 | chrome.runtime.sendMessage({type: "init"}, function(response) {
17 | // console.log(response);
18 | });
19 |
20 | chrome.runtime.onMessage.addListener(
21 | function(request, sender, sendResponse) {
22 | // console.log(request);
23 | switch(request.type) {
24 | case 'get_state':
25 | sendResponse(global.state);
26 | break;
27 | case 'toggle_state':
28 | toggle(global);
29 | sendResponse(global.state);
30 | case 'ce_id':
31 | if (request.ce_id)
32 | localStorage.setItem('ce_id', request.ce_id);
33 | }
34 | }
35 | );
36 | }
37 | })();
--------------------------------------------------------------------------------
/src/info.js:
--------------------------------------------------------------------------------
1 | import { addStyle } from "./addStyle";
2 |
3 | const STYLES = `
4 | .gs_confirm_container, .gs_message, .gs_tooltip {
5 | box-sizing: border-box !important;
6 | }
7 | .gs_confirm_container *, .gs_message *, .gs_tooltip * {
8 | color: black !important;
9 | box-sizing: border-box !important;
10 | font-size: 16px !important;
11 | appearance: unset !important;
12 | position: unset !important;
13 | margin: unset !important;
14 | opacity: unset !important;
15 | visibility: unset !important;
16 | }
17 | .gs_confirm_container input[type=checkbox] {
18 | width: 13px !important;
19 | height: 13px !important;
20 | }
21 | .gs_confirm_container input, .gs_message input {
22 | border: 1px solid black !important;
23 | }
24 | .gs_hidden { visibility: hidden; }
25 | .gs_d-none { display: none !important; }
26 | .gs_tooltip {
27 | position: fixed !important;
28 | z-index: 99999999999999 !important;
29 | max-width: 500px !important;
30 | width: 80% !important;
31 | pointer-events: none !important;
32 | display: none !important;
33 |
34 | background-color: #ffa778 !important;
35 | padding: 5px 10px !important;
36 | box-shadow: 1px 1px 5px 2px #260101 !important;
37 | line-height: 16px !important;
38 | font-size: 16px !important;
39 | color: black !important;
40 | }
41 | .gs_checkbox {
42 | width: 18px !important;
43 | height: 18px !important;
44 | cursor: pointer !important;
45 | }
46 | .gs_tooltip.gs_show {
47 | display: block !important;
48 | }
49 | .gs_confirm_container {
50 | position: fixed !important;
51 | left: 0 !important;
52 | top: 0 !important;
53 | width: 100vw !important;
54 | height: 100vh !important;
55 | background-color: #ff450040 !important;
56 | z-index: 9999999999999 !important;
57 | display: none !important;
58 | }
59 | .gs_confirm_container.gs_hide {
60 | opacity: 0 !important;
61 | transition: opacity 2s !important;
62 | transition-delay: 4s !important;
63 | }
64 | .gs_message, .gs_confirm {
65 | position: fixed !important;
66 | box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.25) !important;
67 | padding: 30px 10px 8px !important;
68 | background-color: #fff !important;
69 | border: 4px solid #eee !important;
70 | }
71 | .gs_confirm {
72 | left: calc(50vw - 350px) !important;
73 | top: 80px !important;
74 | }
75 | .gs_hide .gs_confirm {
76 | display: none !important;
77 | }
78 | .gs_confirm_content {
79 | width: 730px !important;
80 | max-width: 100% !important;
81 | max-height: calc(100vh - 150px) !important;
82 | overflow-y: auto !important;
83 | display: flex !important;
84 | gap: 20px !important;
85 | flex-wrap: wrap !important;
86 | align-items: flex-start !important;
87 | }
88 | @media screen and (max-width: 768px) {
89 | .gs_confirm {
90 | width: 290px !important;
91 | left: calc(50vw - 150px) !important;
92 | }
93 | }
94 | .gs_message {
95 | display: none !important;
96 | left: 10px !important;
97 | bottom: 10px !important;
98 | z-index: 999999999999 !important;
99 | width: 300px !important;
100 | }
101 | .gs_message_content {
102 | display: flex !important;
103 | max-height: calc(100vh - 100px) !important;
104 | overflow-y: auto !important;
105 | min-height: 250px !important;
106 | flex-direction: column !important;
107 | }
108 |
109 | .gs_confirm_container.gs_show, .gs_message.gs_show {
110 | display: inline-block !important;
111 | }
112 | .gs_ollacart_img img {
113 | width: 100% !important;
114 | }
115 | .gs_confirm .gs_ollacart_img {
116 | width: 350px !important;
117 | /* position: sticky; */
118 | /* top: 0; */
119 | }
120 | .gs_name_price {
121 | display: flex !important;
122 | justify-content: space-between !important;
123 | font-size: 16px !important;
124 | color: black !important;
125 | gap: 10px !important;
126 | }
127 | .gs_confirm .gs_name_price {
128 | font-size: 20px !important;
129 | font-weight: bold !important;
130 | color: #303030 !important;
131 | }
132 | .gs_confirm .gs_price {
133 | color: #004400 !important;
134 | }
135 | .gs_description {
136 | font-size: 14px !important;
137 | margin-top: 10px !important;
138 | white-space: break-spaces !important;
139 | }
140 | .gs_message_over, .gs_message_finish {
141 | position: absolute !important;
142 | left: 0 !important;
143 | right: 0 !important;
144 | top: -20px !important;
145 | background-color: orangered !important;
146 | color: white !important;
147 | text-align: center !important;
148 | padding: 8px 0 !important;
149 | font-size: 20px !important;
150 | font-weight: bold !important;
151 | white-space: nowrap !important;
152 | cursor: pointer !important;
153 | }
154 | .gs_message_mask {
155 | position: absolute !important;
156 | left: -4px !important;
157 | right: -4px !important;
158 | top: -4px !important;
159 | bottom: -4px !important;
160 | background-color: #ff450040 !important;
161 | }
162 | .gs_message_finish {
163 | font-size: 30px !important;
164 | top: calc(50% - 100px) !important;
165 | padding: 50px 0 !important;
166 | }
167 | .gs_addtional_photos {
168 | margin-top: 5px !important;
169 | display: flex !important;
170 | flex-wrap: wrap !important;
171 | gap: 10px !important;
172 | }
173 | .gs_addtional_photos>div {
174 | position: relative !important;
175 | width: 46px !important;
176 | height: 60px !important;
177 | overflow: hidden !important;
178 | display: flex !important;
179 | justify-content: center !important;
180 | align-items: center !important;
181 | border: 1px solid blue !important;
182 | }
183 | .gs_addtional_photos .gs_remove_photo {
184 | transform: translateY(100%) !important;
185 | opacity: 0 !important;
186 | transition: all .3s !important;
187 | position: absolute !important;
188 | width: 100% !important;
189 | height: 100% !important;
190 | background-color: #000000A0 !important;
191 | display: flex !important;
192 | justify-content: center !important;
193 | align-items: center !important;
194 | }
195 | .gs_addtional_photos>div:hover .gs_remove_photo {
196 | transform: translateY(0) !important;
197 | opacity: 1 !important;
198 | }
199 | .gs_addtional_photos .gs_remove_photo .gs_remove_btn {
200 | width: 30px !important;
201 | height: 30px !important;
202 | border-radius: 50% !important;
203 | cursor: pointer !important;
204 | display: flex !important;
205 | justify-content: center !important;
206 | align-items: center !important;
207 | font-size: 30px !important;
208 | font-weight: bold !important;
209 | background-color: rgb(200, 200, 200) !important;
210 | color: black !important;
211 | }
212 | .gs_addtional_photos img {
213 | width: 100% !important;
214 | }
215 |
216 | .gs_manual_select_tools {
217 | flex-grow: 1 !important;
218 | display: flex !important;
219 | align-items: flex-end !important;
220 | justify-content: space-between !important;
221 | margin-top: 10px !important;
222 | }
223 | .gs_confirm_tools {
224 | display: flex !important;
225 | gap: 15px !important;
226 | justify-content: flex-end !important;
227 | align-items: flex-end !important;
228 | flex-grow: 1 !important;
229 | margin-top: 10px !important;
230 | }
231 | .gs_btn {
232 | padding: 4px 10px !important;
233 | background-color: orangered !important;
234 | color: white !important;
235 | font-size: 16px !important;
236 | font-weight: bold !important;
237 | cursor: pointer !important;
238 | border-radius: 7px !important;
239 | }
240 | .gs_btn:hover {
241 | opacity: 0.8 !important;
242 | }
243 | .gs_btn:active {
244 | opacity: 0.7 !important;
245 | }
246 | .gs_btn.gs_direct {
247 | padding: 4px 14px !important;
248 | }
249 |
250 | .gs_confirm_right {
251 | display: flex !important;
252 | flex-direction: column !important;
253 | flex-grow: 1 !important;
254 | width: 1px !important;
255 | }
256 | .gs_text_center {
257 | text-align: center !important;
258 | }
259 | .gs_go_ollacart {
260 | margin-top: 20px !important;
261 | font-size: 20px !important;
262 | line-height: 25px !important;
263 | cursor: pointer !important;
264 | color: lightseagreen !important;
265 | }
266 | .gs_textarea {
267 | width: 100% !important;
268 | height: 300px !important;
269 | min-height: 300px !important;
270 | max-height: 300px !important;
271 | font-size: 16px !important;
272 | }
273 |
274 | .gs_close {
275 | position: absolute !important;
276 | top: 5px !important;
277 | right: 5px !important;
278 | cursor: pointer !important;
279 | }
280 | .gs_close:hover {
281 | opacity: 0.8 !important;
282 | }
283 | .gs_close img {
284 | width: 20px !important;
285 | }
286 |
287 | .gs_addtional_picker {
288 | margin-top: 15px !important;
289 | margin-left: auto !important;
290 | }
291 | .gs_addtional_picker>div {
292 | width: 200px !important;
293 | margin-top: 5px !important;
294 | display: flex !important;
295 | align-items: center !important;
296 | justify-content: space-between !important;
297 | }
298 | .gs_addtional_picker>div>div {
299 | display: flex !important;
300 | align-items: center !important;
301 | gap: 5px !important;
302 | }
303 | .gs_addtional_picker>div>*:nth-child(2) {
304 | width: 70px !important;
305 | }
306 | .gs_addtional_picker .gs_color-img {
307 | aspect-ratio: 1 !important;
308 | text-align: center !important;
309 | border: 1px solid orangered !important;
310 | object-fit: contain !important;
311 | padding: 4px !important;
312 | border-radius: 8px !important;
313 | cursor: pointer !important;
314 | }
315 | .gs_addtional_picker .gs_color-img:hover {
316 | opacity: 0.8 !important;
317 | }
318 |
319 | .gs_confirm_content::-webkit-scrollbar, .gs_message_content::-webkit-scrollbar {
320 | width: 7px !important;
321 | }
322 | .gs_confirm_content::-webkit-scrollbar-track, .gs_message_content::-webkit-scrollbar-track {
323 | background: #f1f1f1 !important;
324 | }
325 | .gs_confirm_content::-webkit-scrollbar-thumb, .gs_message_content::-webkit-scrollbar-thumb {
326 | background: #e19b9b !important;
327 | }
328 | .gs_confirm_content::-webkit-scrollbar-thumb:hover, .gs_message_content::-webkit-scrollbar-thumb:hover {
329 | background: #e19b9bd0 !important;
330 | }
331 | `;
332 |
333 | const manualSelect = {
334 | img: 'Main Logo',
335 | name: 'Title',
336 | price: 'Price',
337 | description: 'Description',
338 | photos: 'Images'
339 | }
340 |
341 | export const showMessage = (global) => {
342 | const info = global.productInfo;
343 | let html = '';
344 | if (!global.selectMode || global.selectMode === 'img') html += `
`;
345 | if (!global.selectMode) {
346 | html += `
${info.name}${info.price || ''}
`;
347 | }
348 | if (!global.selectMode) html += `
${info.description}
`
349 | if (global.selectMode === 'name' || global.selectMode === 'price' || global.selectMode === 'description') {
350 | html += `
`
351 | }
352 | if (!global.selectMode || global.selectMode === 'photos') {
353 | html += `
`
354 | for (let i = 0; info.photos && (i < info.photos.length); i ++ ) {
355 | if (info.photos[i])
356 | html += `
`;
357 | }
358 | html += `
`
359 | }
360 | if (global.selectMode === 'photos' && info.temp_photo) {
361 | html += `
`;
362 | }
363 |
364 | if (global.selectMode) {
365 | html += `
`
370 | }
371 | html += `
`;
372 |
373 | if (global.selectMode) {
374 | html += `Select ${manualSelect[global.selectMode]}
`
375 | } else {
376 | html += `Auto Select
`;
377 | }
378 |
379 | global.popup.innerHTML = html;
380 | global.popup.classList.toggle("gs_show", true);
381 | };
382 |
383 | export const showColorModal = (global) => {
384 | const info = global.productInfo;
385 | let html = '';
386 | html += `
`;
387 |
388 | if (global.selectMode) {
389 | html += `
`
394 | }
395 | html += `
`;
396 |
397 | html += `Specify Color
`
398 |
399 | global.colormodal.innerHTML = html;
400 | global.colormodal.classList.toggle("gs_show", true);
401 | };
402 |
403 | export const showConfirm = global => {
404 | hideMessage(global);
405 | hideColorModal(global);
406 | hideTooltip(global);
407 |
408 | const info = global.productInfo;
409 | let html = ``
410 | html += `

Go to OllaCart
`;
411 | html += `
${info.name}$${info.price || '0'}
`;
412 | html += `
413 |
414 |

Size notes
415 |
416 |
417 |
421 |
`;
422 | if (info.description) html += `
${info.description}
`
423 | for (let i = 0; info.photos && (i < info.photos.length); i ++ ) {
424 | if (i === 0) html += `
`
425 | if (info.photos[i])
426 | html += `
`;
427 | if (i === info.photos.length - 1) html += `
`
428 | }
429 |
430 | html += `
`
434 |
435 | html += '
';
436 | // html += `
You selected item
`;
437 | html += `
`
438 |
439 | if (global.finish) html += `Added to OllaCart
`;
440 |
441 | global.confirm.innerHTML = html;
442 | global.confirm.classList.toggle("gs_show", true);
443 | global.showConfirm = true;
444 |
445 | if (global.finish) global.confirm.classList.toggle("gs_hide", true);
446 | else global.confirm.classList.toggle("gs_hide", false);
447 | }
448 |
449 | export const showTooltip = global => {
450 | global.tooltip.classList.toggle("gs_show", true);
451 | }
452 |
453 | export const hideTooltip = global => {
454 | global.tooltip.classList.toggle("gs_show", false);
455 | };
456 |
457 | export const hideMessage = global => {
458 | global.popup.classList.toggle("gs_show", false);
459 | };
460 |
461 | export const hideColorModal = global => {
462 | global.colormodal.classList.toggle("gs_show", false);
463 | }
464 |
465 | export const hideConfirm = global => {
466 | global.confirm.classList.toggle("gs_show", false);
467 | global.showConfirm = false;
468 | }
469 |
470 | export const initMessage = global => {
471 | addStyle(STYLES);
472 | global.popup = document.createElement("div");
473 | global.popup.className = "gs_message";
474 | document.body.appendChild(global.popup);
475 |
476 | global.colormodal = document.createElement("div");
477 | global.colormodal.className = "gs_message";
478 | document.body.appendChild(global.colormodal);
479 |
480 | global.confirm = document.createElement("div");
481 | global.confirm.className = "gs_confirm_container";
482 | document.body.appendChild(global.confirm);
483 |
484 | global.tooltip = document.createElement("div");
485 | global.tooltip.innerHTML = 'Click whenever OllaCart shows appropriate product information. You can manually select and edit information after.';
486 | global.tooltip.className = "gs_tooltip";
487 | document.body.appendChild(global.tooltip);
488 | };
489 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "OllaCart",
3 | "version": "1.0.0",
4 | "manifest_version": 3,
5 | "description": "Chrome Extension for Ollacart. Add your items to OllaCart.",
6 | "permissions": ["storage", "tabs", "activeTab"],
7 | "content_scripts": [{
8 | "matches": [""],
9 | "js": ["inject.js"],
10 | "all_frames": false
11 | }],
12 | "background": {
13 | "service_worker": "background.js"
14 | },
15 | "action": { },
16 | "icons": {
17 | "32": "icon_32.png",
18 | "128": "icon_128.png"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/scrap.js:
--------------------------------------------------------------------------------
1 | const Constant = {
2 | title: ['title', 'name'],
3 | price: ['price'],
4 | description: ['description', 'detail', 'info']
5 | }
6 |
7 | const checkIfSimilarProductContainer = (el, attrs = []) => {
8 | const area_limit = 80 * 80, txt_limit_ct = 2;
9 | var txt_ct = 0;
10 | const itms = el.getElementsByTagName('*');
11 | for (let i = 0; i < itms.length; i ++) {
12 | if (getText(itms[i])) txt_ct ++;
13 | if (txt_ct > txt_limit_ct) break;
14 | }
15 | if (txt_ct < txt_limit_ct) return false;
16 |
17 | const imgs = el.getElementsByTagName('img');
18 | let i = 0;
19 | for (i = 0; i < imgs.length; i ++) {
20 | const img = imgs[i];
21 | const area = img.width * img.height;
22 | if (area < area_limit) continue;
23 | break;
24 | }
25 | if (i === imgs.length) return false;
26 | if (!attrs.length) return true;
27 |
28 | const htmlStr = (el.innerHTML || '').toLocaleLowerCase();
29 | i = 0;
30 | for (i = 0; i < attrs.length; i ++) {
31 | let j = 0;
32 | for (j = 0; j < attrs[i].length; j ++)
33 | if(htmlStr.includes(attrs[i][j]))
34 | break;
35 | if (j === attrs[i].length) break;
36 | }
37 |
38 | if (i && i === attrs.length) return true;
39 | return false;
40 | }
41 |
42 | const checkIfSimilarItem = (a, b) => {
43 | if (!checkIfSimilarProductContainer(a) || !checkIfSimilarProductContainer(b)) return 0;
44 | const tag1 = a.tagName, tag2 = b.tagName;
45 | if (tag1.toLocaleLowerCase() !== tag2.toLocaleLowerCase()) return 0;
46 | const attr1 = a.attributes, attr2 = b.attributes;
47 | let ct = 0;
48 | for (let i = 0; i < attr1.length; i ++) {
49 | const attr = attr1[i].name || '';
50 | if (!attr) continue;
51 | let j = 0;
52 | for (j = 0; j < attr2.length; j ++) {
53 | if (attr2[j].name == attr) break;
54 | }
55 | if (j === attr2.length) {
56 | continue;
57 | }
58 | ct ++;
59 | }
60 | let rate = Math.min(((ct * 2) / (attr1.length + attr2.length)) * 1.5, 1);
61 | if (attr1.length + attr2.length === 0) rate = 1;
62 | return rate;
63 | }
64 |
65 | const checkIfListContainer = el => {
66 | const t = 0.9;
67 | let p = el.parentNode;
68 | while (p && p.parentNode) {
69 | const pp = p.parentNode;
70 | const chs = pp.children;
71 | const rets = [];
72 | let ct = 0;
73 | for (let i = 0; i < chs.length; i ++) {
74 | let max = 0;
75 | for (let j = 0; j < chs.length; j ++) {
76 | if (i === j) continue;
77 | const a = chs[i], b = chs[j];
78 | const ret = checkIfSimilarItem(a, b);
79 | max = Math.max(max, ret);
80 | if (max >= t) break;
81 | }
82 | if (max < t) ct ++;
83 | if (ct > 1) break;
84 | }
85 | if (ct < 2 && chs.length > 2) return p;
86 | p = p.parentNode;
87 | }
88 | return null;
89 | }
90 |
91 | const getProductRootElement = el => {
92 | const check_list = checkIfListContainer(el);
93 | if (check_list) return check_list;
94 | if (checkIfSimilarProductContainer(el, [Constant.title])) return el;
95 | let p = el.parentNode;
96 | while (p && p.tagName.toLocaleLowerCase() !== 'html') {
97 | if (checkIfSimilarProductContainer(p, [Constant.title])) return p;
98 | p = p.parentNode;
99 | }
100 | return el;
101 | }
102 |
103 | const isVisible = el => {
104 | const style = window.getComputedStyle(el);
105 | if (style.opacity === '0') return false;
106 | if (style.visibility == 'hidden') return false;
107 | const r = el.getBoundingClientRect();
108 | if (r.width < 10 || r.height < 10) return false;
109 | return true;
110 | }
111 |
112 | const checkIfHasAttribute = (el, attr) => {
113 | const keys = el.attributes;
114 | for (let i = 0; i < keys.length; i ++) {
115 | const key = keys[i].name || '';
116 | const value = el.getAttribute(key) || '';
117 | if (key.toLocaleLowerCase().includes(attr) || value.toLocaleLowerCase().includes(attr)) return true;
118 | }
119 | return false;
120 | }
121 |
122 | const checkIfDescendOf = (ch, p, signs) => {
123 | while(ch && ch !== p) {
124 | for (let i = 0; i < signs.length; i ++)
125 | if (checkIfHasAttribute(ch, signs[i]))
126 | return true;
127 | ch = ch.parentNode;
128 | }
129 | return false;
130 | }
131 |
132 | const isHovered = (r, e) => {
133 | const x = e.x, y = e.y;
134 | if (r.left <= x && r.right >= x && r.top <= y && r.bottom >= y) return true;
135 | return false;
136 | }
137 |
138 | const checkIfBetterImg = (a, b, mouse, excepts = []) => {
139 | if (!isVisible(a)) return false;
140 | if (!isVisible(b)) return true;
141 | const a_src = getSrcFromImgTag(a), b_src = getSrcFromImgTag(b);
142 | if (!a_src) return false;
143 | if (!b_src) return true;
144 | const excepts_src = excepts.map(itm => getSrcFromImgTag(itm));
145 | if (excepts_src.includes(a_src)) return false;
146 | if (excepts_src.includes(b_src)) return true;
147 |
148 | const offset = 2;
149 | const r1 = a.getBoundingClientRect(), r2 = b.getBoundingClientRect();
150 | const h1 = isHovered(r1, mouse), h2 = isHovered(r2, mouse);
151 | if (h1 && !h2) return true;
152 | if (!h1 && h2) return false;
153 |
154 | const area1 = r1.width * r1.height, area2 = r2.width * r2.height;
155 | if (Math.abs(area1 - area2) < offset * offset) {
156 | if (Math.abs(r1.x - r2.x) < offset && Math.abs(r1.y - r2.y) < offset) return true;
157 | }
158 | if (area1 > area2) return true;
159 | return false;
160 | }
161 |
162 | const containsAnyLetters = str => {
163 | return /[a-zA-Z0-9]/.test(str);
164 | }
165 |
166 | const getText = el => {
167 | if (!el) return '';
168 | if (['noscript', 'img'].indexOf(el.nodeName.toLocaleLowerCase()) > -1) return '';
169 | if (!isVisible(el)) return false;
170 | try {
171 | const childNodes = el.childNodes;
172 | var hasText = false;
173 | for (let i = 0; i < childNodes.length; i++) {
174 | if (childNodes[i].nodeType === Node.TEXT_NODE) {
175 | var txt = childNodes[i].textContent;
176 | if (!containsAnyLetters(txt)) continue;
177 | hasText = true;
178 | break;
179 | }
180 | }
181 | if (hasText) return (el.innerText || el.textContent || '').replace(/\n/g, '');
182 | return ''
183 | } catch (e) {
184 | return '';
185 | }
186 | }
187 |
188 | const getFText = el => {
189 | if (!el) return '';
190 | return (el.innerText || el.textContent || '').replace(/\n\n/g, '\n');
191 | }
192 |
193 | const getEnteredText = el => {
194 | if (!el) return '';
195 | return (el.innerText || el.textContent || '').replace(/\n\n/g, '\n').replace(/\n/g, '\n'); //•
196 | }
197 |
198 | const checkIfBetterTitle = (a, b, p) => {
199 | const txt1 = getText(a), txt2 = getText(b);
200 | if (txt1 && !txt2) return true;
201 | if (!txt1) return false;
202 |
203 | const des1 = checkIfDescendOf(a, p, Constant.title), des2 = checkIfDescendOf(b, p, Constant.title)
204 | if (des1 && !des2) return true;
205 | if (!des1 && des2) return false;
206 |
207 | const fontSize1 = parseFloat(window.getComputedStyle(a).fontSize) || 0,
208 | fontSize2 = parseFloat(window.getComputedStyle(b).fontSize) || 0;
209 |
210 | if (fontSize1 > fontSize2 * 1.2) return true;
211 | return false;
212 | }
213 |
214 | const getCurrencyNumber = (str) => {
215 | try {
216 | return parseFloat(str.replace(/[^0-9.]+/g,"")) || 0;
217 | } catch (ex) {
218 | return 0;
219 | }
220 | }
221 |
222 | const checkIfBetterPrice = (a, b, p) => {
223 | const txt1 = getText(a), txt2 = getText(b);
224 | const isPrice1 = checkIfPrice(txt1), isPrice2 = checkIfPrice(txt2);
225 | if (isPrice1 && !isPrice2) return true;
226 | if (!isPrice1) return false;
227 |
228 | const des1 = checkIfDescendOf(a, p, Constant.price), des2 = checkIfDescendOf(b, p, Constant.price)
229 | if (des1 && !des2) return true;
230 | if (!des1 && des2) return false;
231 |
232 | return false;
233 | }
234 |
235 | const checkIfBetterDescription = (a, b, p) => {
236 | const txt1 = getText(a), txt2 = getText(b);
237 | if (txt1 && !txt2) return true;
238 | if (!txt1) return false;
239 |
240 | // const des1 = checkIfDescendOf(a, p, Constant.description), des2 = checkIfDescendOf(b, p, Constant.description)
241 | // if (des1 && !des2) return true;
242 | // if (!des1 && des2) return false;
243 |
244 | if (txt1.length > txt2.length) return true;
245 | return false;
246 | }
247 |
248 | export const findHref = el => {
249 | var p = el;
250 | while(p && p.tagName.toLocaleLowerCase() !== 'html') {
251 | if ((p.tagName.toLocaleLowerCase() === 'a' || p.tagName.toLocaleLowerCase === 'button') && p.href) return p.href;
252 | p = p.parentNode;
253 | }
254 | return '';
255 | }
256 |
257 | const getImgUrl = (el, mouse, excepts = []) => {
258 | if (!el) return '';
259 | if (el.tagName.toLocaleLowerCase() === 'img') return el;
260 | const imgs = el.getElementsByTagName('img')
261 | if (!imgs.length) return '';
262 |
263 | var ret = imgs[0];
264 | for (let i = 1; i < imgs.length; i ++) {
265 | if (checkIfBetterImg(imgs[i], ret, mouse, excepts)) ret = imgs[i];
266 | }
267 | return ret;
268 | }
269 |
270 | const getManualImgUrl = (el, mouse) => {
271 | while(el.tagName !== 'html') {
272 | const img = getImgUrl(el, mouse);
273 | if (img) return img;
274 | el = el.parentNode;
275 | }
276 | return null;
277 | }
278 |
279 | const getName = (el) => {
280 | const itms = el.getElementsByTagName("*");
281 | var ret = itms[0];
282 | for (let i = 1; i < itms.length; i ++) {
283 | if (checkIfBetterTitle(itms[i], ret, el)) ret = itms[i];
284 | }
285 | return ret;
286 | }
287 |
288 | const checkIfPrice = (p) => {
289 | if (!p) return false;
290 | let d = p.replace(/ |\n|,/g, '');
291 | d = d.replace('$', '');
292 | if (!d) return false;
293 | for (let i = 0; i < d.length; i ++) if (d[i] !== '.' && !(d[i] >= '0' && d[i] <= '9')) return false;
294 | return true;
295 | }
296 |
297 | const getPrice = (el) => {
298 | const itms = el.getElementsByTagName("*");
299 | var ret = itms[0];
300 | for (let i = 1; i < itms.length; i ++) {
301 | if (checkIfBetterPrice(itms[i], ret, el)) ret = itms[i];
302 | }
303 | return ret;
304 | }
305 |
306 | const getDescriptin = (el) => {
307 | const itms = el.getElementsByTagName("*");
308 | var ret = itms[0];
309 | for (let i = 1; i < itms.length; i ++) {
310 | if (checkIfBetterDescription(itms[i], ret, el)) ret = itms[i];
311 | }
312 | return ret;
313 | }
314 |
315 | const getPhotos = (el, mouse, photo) => {
316 | const ret = [photo];
317 | for (let i = 0; i < 4; i ++) {
318 | const img = getImgUrl(el, mouse, ret);
319 | if (ret.findIndex(itm => getSrcFromImgTag(itm).split('?')[0] === getSrcFromImgTag(img).split('?')[0]) > -1) break;
320 | ret.push(img);
321 | }
322 | ret.shift();
323 | return ret;
324 | }
325 |
326 | const getUrl = (el) => {
327 | if (!el) return '';
328 | return findHref(el);
329 | }
330 |
331 | const getSrcFromImgTag = (el) => {
332 | if (!el) return '';
333 | return (el.currentSrc || el.src || '').split(' ')[0]
334 | }
335 |
336 | export const getProductInfo = (el, picker) => {
337 | const p = getProductRootElement(el);
338 |
339 | const e_img = getImgUrl(p, { x: picker.mouseX, y: picker.mouseY });
340 | const e_name = getName(p);
341 | const e_price = getPrice(p);
342 | const e_description = getDescriptin(p);
343 | const e_photos = getPhotos(p, { x: picker.mouseX, y: picker.mouseY }, e_img);
344 | const name = getText(e_name);
345 | const img = getSrcFromImgTag(e_img);
346 | const url = getUrl(el);
347 | const price = getCurrencyNumber(getText(e_price));
348 | const description = getEnteredText(e_description);
349 | const r_photos = {};
350 | const photos = e_photos.map((p, idx) => {
351 | r_photos['photo' + idx] = p;
352 | return getSrcFromImgTag(p);
353 | })
354 | return {
355 | name,
356 | img,
357 | color: img,
358 | url,
359 | description,
360 | price,
361 | photos,
362 | elements: { e_name, e_img, e_price, e_description, ...r_photos }
363 | }
364 | }
365 |
366 | export const getProductInfoIndividual = (el, picker, global) => {
367 | if (!global.productInfo) global.productInfo = {};
368 | const productInfo = global.productInfo;
369 | if (!productInfo.elements) productInfo.elements = {};
370 | if (!productInfo.photos) productInfo.photos = [];
371 | if (!productInfo.photos.length) {
372 | productInfo.photos.push('');
373 | productInfo.elements.photo0 = null;
374 | }
375 |
376 | switch(global.selectMode) {
377 | case 'img':
378 | productInfo.elements.e_img = getManualImgUrl(el, { x: picker.mouseX, y: picker.mouseY });
379 | productInfo.img = getSrcFromImgTag(productInfo.elements.e_img);
380 | break;
381 | case 'color':
382 | productInfo.elements.e_color = getManualImgUrl(el, { x: picker.mouseX, y: picker.mouseY });
383 | productInfo.color = getSrcFromImgTag(productInfo.elements.e_color);
384 | break;
385 | case 'name':
386 | productInfo.elements.e_name = el;
387 | productInfo.name = getFText(el);
388 | break;
389 | case 'description':
390 | productInfo.elements.e_description = el;
391 | productInfo.description = getEnteredText(el);
392 | break;
393 | case 'price':
394 | productInfo.elements.e_price = el;
395 | productInfo.price = getCurrencyNumber(getFText(el));
396 | break;
397 | case 'photos':
398 | const e_photo = getManualImgUrl(el, { x: picker.mouseX, y: picker.mouseY });
399 | const photo = (e_photo.currentSrc || e_photo.src || '').split(' ')[0];
400 | productInfo.elements['temp_photo'] = e_photo
401 | productInfo.temp_photo = photo;
402 | break;
403 | }
404 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@medv/finder@^1.1.0":
6 | version "1.1.3"
7 | resolved "https://registry.yarnpkg.com/@medv/finder/-/finder-1.1.3.tgz#01d90511b3cf1420276c5fa7a5cc4ac5fd7e1527"
8 | integrity sha512-hq6O7/4YpnBdfOzTFRF/0cNIg3IuJcF55LSOWq67lG/JQVtTwEu5ydv6L3fleoiwEOpQxF/zZq+NupVqgDVy6Q==
9 | dependencies:
10 | cssesc "^2.0.0"
11 |
12 | acorn@^5.2.1:
13 | version "5.7.4"
14 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
15 | integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
16 |
17 | asynckit@^0.4.0:
18 | version "0.4.0"
19 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
20 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
21 |
22 | axios@^1.6.0:
23 | version "1.6.0"
24 | resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102"
25 | integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==
26 | dependencies:
27 | follow-redirects "^1.15.0"
28 | form-data "^4.0.0"
29 | proxy-from-env "^1.1.0"
30 |
31 | builtin-modules@^2.0.0:
32 | version "2.0.0"
33 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-2.0.0.tgz#60b7ef5ae6546bd7deefa74b08b62a43a232648e"
34 | integrity sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg==
35 |
36 | combined-stream@^1.0.8:
37 | version "1.0.8"
38 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
39 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
40 | dependencies:
41 | delayed-stream "~1.0.0"
42 |
43 | cssesc@^2.0.0:
44 | version "2.0.0"
45 | resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703"
46 | integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==
47 |
48 | delayed-stream@~1.0.0:
49 | version "1.0.0"
50 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
51 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
52 |
53 | estree-walker@^0.5.0:
54 | version "0.5.2"
55 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39"
56 | integrity sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==
57 |
58 | estree-walker@^0.6.1:
59 | version "0.6.1"
60 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
61 | integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
62 |
63 | follow-redirects@^1.15.0:
64 | version "1.15.6"
65 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
66 | integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
67 |
68 | form-data@^4.0.0:
69 | version "4.0.0"
70 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
71 | integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
72 | dependencies:
73 | asynckit "^0.4.0"
74 | combined-stream "^1.0.8"
75 | mime-types "^2.1.12"
76 |
77 | function-bind@^1.1.1:
78 | version "1.1.1"
79 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
80 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
81 |
82 | has@^1.0.3:
83 | version "1.0.3"
84 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
85 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
86 | dependencies:
87 | function-bind "^1.1.1"
88 |
89 | is-core-module@^2.9.0:
90 | version "2.11.0"
91 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
92 | integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
93 | dependencies:
94 | has "^1.0.3"
95 |
96 | is-module@^1.0.0:
97 | version "1.0.0"
98 | resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
99 | integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==
100 |
101 | lodash@^4.17.21:
102 | version "4.17.21"
103 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
104 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
105 |
106 | magic-string@^0.22.4:
107 | version "0.22.5"
108 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e"
109 | integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==
110 | dependencies:
111 | vlq "^0.2.2"
112 |
113 | mime-db@1.52.0:
114 | version "1.52.0"
115 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
116 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
117 |
118 | mime-types@^2.1.12:
119 | version "2.1.35"
120 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
121 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
122 | dependencies:
123 | mime-db "1.52.0"
124 |
125 | path-parse@^1.0.7:
126 | version "1.0.7"
127 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
128 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
129 |
130 | proxy-from-env@^1.1.0:
131 | version "1.1.0"
132 | resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
133 | integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
134 |
135 | resolve@^1.1.6, resolve@^1.4.0:
136 | version "1.22.1"
137 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
138 | integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
139 | dependencies:
140 | is-core-module "^2.9.0"
141 | path-parse "^1.0.7"
142 | supports-preserve-symlinks-flag "^1.0.0"
143 |
144 | rollup-plugin-commonjs@^8.3.0:
145 | version "8.4.1"
146 | resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.4.1.tgz#5c9cea2b2c3de322f5fbccd147e07ed5e502d7a0"
147 | integrity sha512-mg+WuD+jlwoo8bJtW3Mvx7Tz6TsIdMsdhuvCnDMoyjh0oxsVgsjB/N0X984RJCWwc5IIiqNVJhXeeITcc73++A==
148 | dependencies:
149 | acorn "^5.2.1"
150 | estree-walker "^0.5.0"
151 | magic-string "^0.22.4"
152 | resolve "^1.4.0"
153 | rollup-pluginutils "^2.0.1"
154 |
155 | rollup-plugin-node-resolve@^3.0.3:
156 | version "3.4.0"
157 | resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz#908585eda12e393caac7498715a01e08606abc89"
158 | integrity sha512-PJcd85dxfSBWih84ozRtBkB731OjXk0KnzN0oGp7WOWcarAFkVa71cV5hTJg2qpVsV2U8EUwrzHP3tvy9vS3qg==
159 | dependencies:
160 | builtin-modules "^2.0.0"
161 | is-module "^1.0.0"
162 | resolve "^1.1.6"
163 |
164 | rollup-pluginutils@^2.0.1:
165 | version "2.8.2"
166 | resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
167 | integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
168 | dependencies:
169 | estree-walker "^0.6.1"
170 |
171 | rollup@^0.56.2:
172 | version "0.56.5"
173 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.56.5.tgz#40fe3cf0cd1659d469baad11f4d5b6336c14ce84"
174 | integrity sha512-IGPk5vdWrsc4vkiW9XMeXr5QMtxmvATTttTi59w2jBQWe9G/MMQtn8teIBAj+DdK51TrpVT6P0aQUaQUlUYCJA==
175 |
176 | supports-preserve-symlinks-flag@^1.0.0:
177 | version "1.0.0"
178 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
179 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
180 |
181 | vlq@^0.2.2:
182 | version "0.2.3"
183 | resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
184 | integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==
185 |
--------------------------------------------------------------------------------