PluginProbe
Taboola / 2.2.3
Taboola v2.2.3
1.0.4 1.0.5 1.0.6 1.0.8 2.0.1 2.0.2 2.1.0 2.1.1 2.2.2 2.2.3 3.0.0 3.0.1 3.0.2 3.1.0 trunk 1.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.2 1.0.3
← All changes | js/js_inject.js +21 -2 trunk2.2.3 View file →
@@ -1,7 +1,13 @@
1 +/* ────────────────────────────────────────────────────────────────────────────
2 + Utility helpers
3 + ────────────────────────────────────────────────────────────────────────── */
4 +
1 5 (function () {
2 6 'use strict';
3 7
8 + /* ---------- insertAfter ------------------------------------------------ */
9 + /* Fast path for “append” avoids creating a reference to nextSibling. */
4 10 function insertAfter(newNode, referenceNode) {
5 11 const parent = referenceNode.parentNode;
6 12 if (parent.lastChild === referenceNode) {
7 13 parent.appendChild(newNode);
@@ -9,10 +15,14 @@
9 15 parent.insertBefore(newNode, referenceNode.nextSibling);
10 16 }
11 17 }
12 18
19 + /* ---------- getElementByXPath ----------------------------------------- */
20 + /* 1) Use native evaluate where available (all evergreen browsers). */
21 + /* 2) Small, allocation-free fallback for very old IE engines. */
13 22 function getElementByXPath(xPath, doc = document) {
14 23 if (doc.evaluate) {
24 + // XPathResult.FIRST_ORDERED_NODE_TYPE = 9
15 25 return doc.evaluate(
16 26 xPath,
17 27 doc,
18 28 null,
@@ -20,9 +30,10 @@
20 30 null
21 31 ).singleNodeValue;
22 32 }
23 33
24 - xPath = xPath.replace(/^\/+/, '');
34 + // Fallback (legacy IE) – minimal parsing, no .filter / regex loops
35 + xPath = xPath.replace(/^\/+/, ''); // strip leading “/”
25 36 const steps = xPath.split('/');
26 37 let current = doc;
27 38
28 39 for (let i = 0, l = steps.length; i < l && current; i += 1) {
@@ -28,14 +39,17 @@
28 39 for (let i = 0, l = steps.length; i < l && current; i += 1) {
29 40 const match = /([^\[\]]+)(?:\[(\d+)\])?/.exec(steps[i]);
30 41 if (!match) return null;
31 42 const [, tag, idx] = match;
32 - const pos = idx ? (idx - 1) : 0;
43 + const pos = idx ? (idx - 1) : 0; // XPath indices are 1-based
33 44 current = current.getElementsByTagName(tag)[pos] || null;
34 45 }
35 46 return current;
36 47 }
37 48
49 + /* ---------- Array.prototype.filter polyfill (unchanged API) ------------ */
50 + /* MIT – kept for <= IE8; tightened slightly for speed/readability. */
51 + /* eslint-disable-next-line no-extend-native */
38 52 if (!Array.prototype.filter) {
39 53 Array.prototype.filter = function (callback, thisArg) {
40 54 if (typeof callback !== 'function') throw new TypeError();
41 55 const out = [];
@@ -48,8 +62,10 @@
48 62 return out;
49 63 };
50 64 }
51 65
66 + /* ---------- Injection helpers ----------------------------------------- */
67 +
52 68 function injectWidgetByXpath(xpath) {
53 69 const anchor =
54 70 getElementByXPath(xpath) || document.getElementById('tbdefault');
55 71 if (anchor) innerInject(anchor);
@@ -59,8 +75,9 @@
59 75 const markerNode = document.getElementById(markerId);
60 76 if (markerNode && markerNode.parentNode) innerInject(markerNode.parentNode);
61 77 }
62 78
79 + /* One reflow: build everything in a fragment, then insert once. */
63 80 function innerInject(node) {
64 81 if (!node) return;
65 82
66 83 const fragment = document.createDocumentFragment();
@@ -66,8 +83,9 @@
66 83 const fragment = document.createDocumentFragment();
67 84 const container = document.createElement('span');
68 85 const script = document.createElement('script');
69 86
87 + /* Keep single quotes – some minifiers mangle this otherwise. */
70 88 container.insertAdjacentHTML('beforeend', '{{HTML}}');
71 89 script.text = "{{SCRIPT}}";
72 90
73 91 fragment.appendChild(container);
@@ -74,8 +92,9 @@
74 92 fragment.appendChild(script);
75 93 insertAfter(fragment, node);
76 94 }
77 95
96 + /* ---------- Export to global scope (names unchanged) ------------------- */
78 97 window.insertAfter = insertAfter;
79 98 window.getElementByXPath = getElementByXPath;
80 99 window.injectWidgetByXpath = injectWidgetByXpath;
81 100 window.injectWidgetByMarker = injectWidgetByMarker;