PluginProbe
Taboola / 3.0.1
Taboola v3.0.1
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
taboola / js / js_inject.js

js_inject.js in Taboola 3.0.1, at js/js_inject.js

103 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* ────────────────────────────────────────────────────────────────────────────
2 Utility helpers
3 ────────────────────────────────────────────────────────────────────────── */
4
5 (function () {
6 'use strict';
7
8 /* ---------- insertAfter ------------------------------------------------ */
9 /* Fast path for “append” avoids creating a reference to nextSibling. */
10 function insertAfter(newNode, referenceNode) {
11 const parent = referenceNode.parentNode;
12 if (parent.lastChild === referenceNode) {
13 parent.appendChild(newNode);
14 } else {
15 parent.insertBefore(newNode, referenceNode.nextSibling);
16 }
17 }
18
19 /* ---------- getElementByXPath ----------------------------------------- */
20 /* 1) Use native evaluate where available (all evergreen browsers). */
21 /* 2) Small, allocation-free fallback for very old IE engines. */
22 function getElementByXPath(xPath, doc = document) {
23 if (doc.evaluate) {
24 // XPathResult.FIRST_ORDERED_NODE_TYPE = 9
25 return doc.evaluate(
26 xPath,
27 doc,
28 null,
29 9,
30 null
31 ).singleNodeValue;
32 }
33
34 // Fallback (legacy IE) – minimal parsing, no .filter / regex loops
35 xPath = xPath.replace(/^\/+/, ''); // strip leading “/”
36 const steps = xPath.split('/');
37 let current = doc;
38
39 for (let i = 0, l = steps.length; i < l && current; i += 1) {
40 const match = /([^\[\]]+)(?:\[(\d+)\])?/.exec(steps[i]);
41 if (!match) return null;
42 const [, tag, idx] = match;
43 const pos = idx ? (idx - 1) : 0; // XPath indices are 1-based
44 current = current.getElementsByTagName(tag)[pos] || null;
45 }
46 return current;
47 }
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 */
52 if (!Array.prototype.filter) {
53 Array.prototype.filter = function (callback, thisArg) {
54 if (typeof callback !== 'function') throw new TypeError();
55 const out = [];
56 for (let i = 0, l = this.length >>> 0; i < l; i += 1) {
57 if (i in this) {
58 const val = this[i];
59 if (callback.call(thisArg, val, i, this)) out.push(val);
60 }
61 }
62 return out;
63 };
64 }
65
66 /* ---------- Injection helpers ----------------------------------------- */
67
68 function injectWidgetByXpath(xpath) {
69 const anchor =
70 getElementByXPath(xpath) || document.getElementById('tbdefault');
71 if (anchor) innerInject(anchor);
72 }
73
74 function injectWidgetByMarker(markerId) {
75 const markerNode = document.getElementById(markerId);
76 if (markerNode && markerNode.parentNode) innerInject(markerNode.parentNode);
77 }
78
79 /* One reflow: build everything in a fragment, then insert once. */
80 function innerInject(node) {
81 if (!node) return;
82
83 const fragment = document.createDocumentFragment();
84 const container = document.createElement('span');
85 const script = document.createElement('script');
86
87 /* Keep single quotes – some minifiers mangle this otherwise. */
88 container.insertAdjacentHTML('beforeend', '{{HTML}}');
89 script.text = "{{SCRIPT}}";
90
91 fragment.appendChild(container);
92 fragment.appendChild(script);
93 insertAfter(fragment, node);
94 }
95
96 /* ---------- Export to global scope (names unchanged) ------------------- */
97 window.insertAfter = insertAfter;
98 window.getElementByXPath = getElementByXPath;
99 window.injectWidgetByXpath = injectWidgetByXpath;
100 window.injectWidgetByMarker = injectWidgetByMarker;
101 window.innerInject = innerInject;
102 }());
103