Commit 56325b61 authored by Sven Franck's avatar Sven Franck

jslint (sans code from JQM, Mozilla, requireJS)

parent 9c5a59ce
...@@ -41,32 +41,36 @@ ...@@ -41,32 +41,36 @@
// Info: // Info:
// iframe communication: // iframe communication:
// http://stackoverflow.com/questions/15884994/javascript-can-data-be-passed-bi-directionally-through-an-iframe/ // http://bit.ly/11gjl1e
// http://stackoverflow.com/questions/16689280/how-to-set-jquery-data-on-an-iframe-body-tag-and-retrieve-it-from-inside-the-i/16689994?noredirect=1#16689994 // http://bit.ly/1434ZSV
// custom URI schemes: // custom URI schemes:
// http://stackoverflow.com/questions/4403992/possible-to-handle-your-own-http-url-schemes-in-ios/5149668#5149668 // http://bit.ly/11tn2MJ
// validate URL: // validate URL:
// http://stackoverflow.com/questions/161738/what-is-the-best-regular-expression-to-check-if-a-string-is-a-valid-url // http://bit.ly/2Ol4gj
(function ($, window, undefined) { /*jslint indent: 2, maxlen: 80, nomen: true */
var priv = {}; /*global window: true, $: true, undefined: true, console: true,
var that = {}; document: true, require: true*/
(function ($, window) {
"use strict";
var priv = {},
that = {};
// ================== utility methods ================== // ================== utility methods ==================
// => cross-browser reduce (no support in ie8-, opera 12-) // => cross-browser reduce (no support in ie8-, opera 12-)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FReduce // http://mzl.la/11tnDy1
if ('function' !== typeof Array.prototype.reduce) { if ('function' !== typeof Array.prototype.reduce) {
Array.prototype.reduce = function(callback, opt_initialValue){ Array.prototype.reduce = function (callback, opt_initialValue) {
'use strict';
if (null === this || 'undefined' === typeof this) { if (null === this || 'undefined' === typeof this) {
// At the moment all modern browsers, that support strict mode, have // At the moment all modern browsers, that support strict mode, have
// native implementation of Array.prototype.reduce. For instance, IE8 // native implementation of Array.prototype.reduce. For instance, IE8
// does not support strict mode, so this check is actually useless. // does not support strict mode, so this check is actually useless.
throw new TypeError( throw new TypeError(
'Array.prototype.reduce called on null or undefined'); 'Array.prototype.reduce called on null or undefined'
);
} }
if ('function' !== typeof callback) { if ('function' !== typeof callback) {
throw new TypeError(callback + ' is not a function'); throw new TypeError(callback + ' is not a function');
...@@ -100,7 +104,6 @@ ...@@ -100,7 +104,6 @@
priv.removeWhiteSpace = /\s+/mg; priv.removeWhiteSpace = /\s+/mg;
priv.removeWhiteSpaceBetweenElements = />\s+</mg; priv.removeWhiteSpaceBetweenElements = />\s+</mg;
// => convert all URLs to absolute URLs // => convert all URLs to absolute URLs
// thx JQM - http://code.jquery.com/mobile/latest/jquery.mobile.js // thx JQM - http://code.jquery.com/mobile/latest/jquery.mobile.js
...@@ -224,7 +227,6 @@ ...@@ -224,7 +227,6 @@
return protocol + doubleSlash + authority + pathname + search + hash; return protocol + doubleSlash + authority + pathname + search + hash;
}; };
// => generate unique identifier // => generate unique identifier
priv.generateUuid = function () { priv.generateUuid = function () {
var S4 = function () { var S4 = function () {
...@@ -243,17 +245,17 @@ ...@@ -243,17 +245,17 @@
// extract module name from path // extract module name from path
priv.extractModuleName = function (src) { priv.extractModuleName = function (src) {
var re = /([\w\d_-]*)\.?[^\\\/]*$/i; var re = /([\w\d_-]*)\.?[^\\\/]*$/i;
return src.match(re)[1] return src.match(re)[1];
} };
// => safe getAttribute for data-* // => safe getAttribute for data-*
// thx JQM - http://code.jquery.com/mobile/latest/jquery.mobile.js // thx JQM - http://code.jquery.com/mobile/latest/jquery.mobile.js
priv.getAttribute = function (element, attribute, json) { priv.getAttribute = function (element, attribute, json) {
var value; var value;
value = element.getAttribute( "data-" + attribute ); value = element.getAttribute("data-" + attribute);
return value === "true" ? true : return value === "true" ? true :
value === "false" ? false : value === "false" ? false :
value === null ? (json ? "" : undefined ) : value; value === null ? (json ? "" : undefined) : value;
}; };
// => URI methods // => URI methods
...@@ -267,7 +269,7 @@ ...@@ -267,7 +269,7 @@
}; };
// decode URI array // decode URI array
priv.decodeURIArray = function (array) { priv.decodeURIArray = function (array) {
var i, newArray; var i, newArray = [];
for (i = 0; i < array.length; i += 1) { for (i = 0; i < array.length; i += 1) {
newArray.push(priv.decodeURI(array[i])); newArray.push(priv.decodeURI(array[i]));
} }
...@@ -306,46 +308,46 @@ ...@@ -306,46 +308,46 @@
obj = spec.slice(1).split("="); obj = spec.slice(1).split("=");
key = obj[0]; key = obj[0];
switch (key) { switch (key) {
case "string": case "string":
case "url": case "url":
config.root = priv.decodeURI(obj[1]); config.root = priv.decodeURI(obj[1]);
break; break;
case "json": case "json":
parsedJSON = JSON.parse(priv.decodeURI(obj[1])); parsedJSON = JSON.parse(priv.decodeURI(obj[1]));
config.root = parsedJSON.root || window.location.pathname; config.root = parsedJSON.root || window.location.pathname;
config.src = priv.decodeURIArray(parsedJSON.src) || []; config.src = priv.decodeURIArray(parsedJSON.src) || [];
break; break;
case "hal": case "hal":
parsedJSON = JSON.parse(priv.decodeURI(obj[1])); parsedJSON = JSON.parse(priv.decodeURI(obj[1]));
config.root = parsedJSON._links.self || window.location.pathname; config.root = parsedJSON._links.self || window.location.pathname;
config.src = priv.decodeURIArray(parsedJSON.src) || []; config.src = priv.decodeURIArray(parsedJSON.src) || [];
break; break;
case "data": case "data":
break; break;
default: default:
// no allowable-type - ignore config-parameter! // no allowable-type - ignore config-parameter!
config.root = window.location.href config.root = window.location.href;
config.src = []; config.src = [];
break; break;
} }
} else { } else {
config = {"root": window.location.href} config = {"root": window.location.href};
} }
return config; return config;
}; };
// => create Index of gadgets on page (excluding gadgets inside iFrame/Sandbox) // => create Index of gadgets on page (excluding gadgets in iFrame/Sandbox)
priv.createGadgetIndex = function () { priv.createGadgetIndex = function () {
that.gadgetIndex = []; that.gadgetIndex = [];
}; };
// => create gadget reference tree (includes gadgets inside iFrame/Sandbox) // => create gadget reference tree (includes gadgets in iFrame/Sandbox)
priv.createGadgetTree = function () { priv.createGadgetTree = function () {
that.gadgetTree = { that.gadgetTree = {
"id": "root", "id": "root",
"src": window.location.href, "src": window.location.href,
"children":[] "children": []
} };
}; };
// => add gadget to index // => add gadget to index
...@@ -375,10 +377,9 @@ ...@@ -375,10 +377,9 @@
delete options.parentFrame; delete options.parentFrame;
priv.addGadgetToTree(options, newNode); priv.addGadgetToTree(options, newNode);
break; break;
} else { }
if (newNode.children.length > 0) { if (newNode.children.length > 0) {
priv.addGadgetToTree(options, newNode); priv.addGadgetToTree(options, newNode);
}
} }
} }
} }
...@@ -389,7 +390,7 @@ ...@@ -389,7 +390,7 @@
if (window.top !== window) { if (window.top !== window) {
window.top.postMessage({ window.top.postMessage({
// this will trigger addGagdetToTree() on root-in // this will trigger addGagdetToTree() on root-in
"type":"tree/update", "type": "tree/update",
"options": { "options": {
// passing "options":options will procude a DataCloneError, so // passing "options":options will procude a DataCloneError, so
// this is the only way (it seems) to pass the options object. // this is the only way (it seems) to pass the options object.
...@@ -398,7 +399,7 @@ ...@@ -398,7 +399,7 @@
"src": options.src, "src": options.src,
"children": [] "children": []
} }
}, window.location.href.split("?")[0]) }, window.location.href.split("?")[0]);
} }
}; };
...@@ -414,7 +415,11 @@ ...@@ -414,7 +415,11 @@
return selector; return selector;
} }
for (i = 0; i < node.children.length; i += 1) { for (i = 0; i < node.children.length; i += 1) {
result = priv.constructSelectorForService(src, node.children[i], selector); result = priv.constructSelectorForService(
src,
node.children[i],
selector
);
if (result !== undefined) { if (result !== undefined) {
return result; return result;
} }
...@@ -431,7 +436,7 @@ ...@@ -431,7 +436,7 @@
"root": spec.root || window.location.href, "root": spec.root || window.location.href,
"directories": spec.src || [], "directories": spec.src || [],
"map": [] "map": []
} };
// listen for service postings to THIS renderJs instance // listen for service postings to THIS renderJs instance
window.addEventListener("message", priv.serviceHandler, false); window.addEventListener("message", priv.serviceHandler, false);
}; };
...@@ -446,36 +451,37 @@ ...@@ -446,36 +451,37 @@
// route // route
switch (route[0]) { switch (route[0]) {
case "service": case "service":
priv.registerNewService(event); priv.registerNewService(event);
break; break;
case "request": case "request":
trackingId = priv.generateUuid(); trackingId = priv.generateUuid();
// track this request, so we know where to send the response // track this request, so we know where to send the response
priv.trackRequest(trackingId, event.originalTarget); priv.trackRequest(trackingId, event.originalTarget);
// request the service // request the service
priv.requestServiceFromGadget(event, trackingId); priv.requestServiceFromGadget(event, trackingId);
break; break;
case "tree": case "tree":
if (route[1] === "update") { if (route[1] === "update") {
priv.addGadgetToTree(event.data.options, that.gadgetTree); priv.addGadgetToTree(event.data.options, that.gadgetTree);
} }
break; break;
case "run": case "run":
priv.runService(event); priv.runService(event);
break; break;
case "result": case "result":
priv.sendServiceReply(event); priv.sendServiceReply(event);
break; break;
case "reply": case "reply":
priv.returnResult(event.data.result); priv.returnResult(event.data.result);
break; break;
} }
}; };
// => return the result to the function call // => return the result to the function call
priv.returnResult = function (result) { priv.returnResult = function (result) {
console.log("hello inside reply"); // need a way to return this result to the calling function
console.log(result);
return result; return result;
}; };
// => sends a response message after a service has been run // => sends a response message after a service has been run
...@@ -491,33 +497,37 @@ ...@@ -491,33 +497,37 @@
priv.runService = function (event) { priv.runService = function (event) {
var result = window[event.data.service].apply(this, event.data.parameters); var result = window[event.data.service].apply(this, event.data.parameters);
window.top.postMessage({ window.top.postMessage({
"type":"result", "type": "result",
"result": result, "result": result,
"trackingId" : event.data.trackingId, "trackingId" : event.data.trackingId
}, window.location.href.split("?")[0]); }, window.location.href.split("?")[0]);
}; };
// => request a service provided by a gadget // => request a service provided by a gadget
priv.requestServiceFromGadget = function (event, trackingId) { priv.requestServiceFromGadget = function (event, trackingId) {
var callService = priv.findServiceInMap( var callService = priv.findServiceInMap(
event.data.service, event.data.type.split("/")[1] event.data.service,
event.data.type.split("/")[1]
), ),
selector, i, targetWindow; selector,
targetWindow;
if (callService) { if (callService) {
// services are stored by URL (not id), so we need to find the service // services are stored by URL (not id), so we need to find the service
// in our gadget tree by using the URL provided by the service... // in our gadget tree by using the URL provided by the service...
// and return an id path, so we can create a selector // and return an id path, so we can create a selector
selector = priv.constructSelectorForService( selector = priv.constructSelectorForService(
callService.src, that.gadgetTree, [] callService.src,
that.gadgetTree,
[]
); );
// for plain nested gadgets (no iFrame/sandbox) this will return // for plain nested gadgets (no iFrame/sandbox) this will return
// only an empty array // only an empty array
// for iFrames/sandbox, selector will be an array of ids from // for iFrames/sandbox, selector will be an array of ids from
// which we have to construct our window element to postMessage to // which we have to construct our window element to postMessage to
// see http://stackoverflow.com/questions/15076293/window-postmessage-to-a-nested-iframe-in-cross-domain // http://bit.ly/12m3wJD
// https://developer.mozilla.org/en-US/docs/Web/API/window.frames // http://mzl.la/17EeDiN
if (selector.length === 0) { if (selector.length === 0) {
targetWindow = window; targetWindow = window;
} else { } else {
...@@ -527,11 +537,11 @@ ...@@ -527,11 +537,11 @@
} }
// and request the service // and request the service
targetWindow.postMessage({ targetWindow.postMessage({
"type":"run", "type": "run",
"trackingId": trackingId, "trackingId": trackingId,
"service": event.data.service, "service": event.data.service,
"parameters":event.data.parameters "parameters": event.data.parameters
}, window.location.href) }, window.location.href);
} }
}; };
...@@ -586,9 +596,13 @@ ...@@ -586,9 +596,13 @@
}; };
// => find hardcoded services in source HTML // => find hardcoded services in source HTML
priv.findServiceInHTML = function (spec, root) { priv.findServiceInHTML = function (spec, sentRoot) {
var root = root ? root : document, var root = sentRoot || document,
services, service, options, i, j; services,
service,
options,
i,
j;
try { try {
services = root.querySelectorAll('[data-service], link[type^=service]'); services = root.querySelectorAll('[data-service], link[type^=service]');
...@@ -600,20 +614,22 @@ ...@@ -600,20 +614,22 @@
"rel": service[j].rel, "rel": service[j].rel,
"type": service[j].type, "type": service[j].type,
"src": service[j].src || window.location.href.split("?")[0] "src": service[j].src || window.location.href.split("?")[0]
} };
$(root).addService(options); $(root).addService(options);
} }
} }
} } catch (error) {
catch (error) { console.log(error);
// permission denied accessing document of foreign domains
} }
}; };
// => find hardcoded gadgets in source HTML // => find hardcoded gadgets in source HTML
priv.findGadgetinHTML = function (spec, root) { priv.findGadgetinHTML = function (spec, sentRoot) {
var root = root ? root : document, var root = sentRoot || document,
gadgets, gadget, options, i; gadgets,
gadget,
options,
i;
// need to try/catch because cross domain will not permit qsa // need to try/catch because cross domain will not permit qsa
// > so any cross domain gadgets have to be self-sufficient // > so any cross domain gadgets have to be self-sufficient
...@@ -625,9 +641,11 @@ ...@@ -625,9 +641,11 @@
for (i = 0; i < gadgets.length; i += 1) { for (i = 0; i < gadgets.length; i += 1) {
gadget = gadgets[i]; gadget = gadgets[i];
options = { options = {
"src" : priv.makeUrlAbsolute(priv.getAttribute(gadget, 'gadget')) || null, "src" : priv.makeUrlAbsolute(priv.getAttribute(gadget, 'gadget')),
"id": priv.generateUuid(), "id": priv.generateUuid(),
"param" : JSON.parse(priv.getAttribute(gadget, 'param', true) || null), "param" : JSON.parse(
priv.getAttribute(gadget, 'param', true) || null
),
"sandbox" : priv.getAttribute(gadget, 'sandbox') || false, "sandbox" : priv.getAttribute(gadget, 'sandbox') || false,
"iframe" : priv.getAttribute(gadget, 'iframe') || false, "iframe" : priv.getAttribute(gadget, 'iframe') || false,
"wrapper": gadget, "wrapper": gadget,
...@@ -637,9 +655,8 @@ ...@@ -637,9 +655,8 @@
// add gadget // add gadget
$(root).addGadget(options); $(root).addGadget(options);
} }
} } catch (error) {
catch(error) { console.log(error);
// permission denied accessing document of foreign domains
} }
}; };
...@@ -666,7 +683,7 @@ ...@@ -666,7 +683,7 @@
// extract relevant page elements here! // extract relevant page elements here!
cleanedString = gadgetData cleanedString = gadgetData
.replace(priv.removeJSComments, "") .replace(priv.removeJSComments, "")
.replace(priv.removeHTMLComments,"") .replace(priv.removeHTMLComments, "")
.replace(priv.removeLineBreaks, "") .replace(priv.removeLineBreaks, "")
.replace(priv.removeWhiteSpace, " ") .replace(priv.removeWhiteSpace, " ")
.replace(priv.removeWhiteSpaceBetweenElements, "><"); .replace(priv.removeWhiteSpaceBetweenElements, "><");
...@@ -676,33 +693,34 @@ ...@@ -676,33 +693,34 @@
for (i = 0; i < content.length; i += 1) { for (i = 0; i < content.length; i += 1) {
element = content[i]; element = content[i];
switch(element.tagName) { switch (element.tagName) {
case "LINK": case "LINK":
if (element.getAttribute("type").split("/")[0] === "service") { if (element.getAttribute("type").split("/")[0] === "service") {
$(element).addService({ $(element).addService({
"src": element.getAttribute("src") || window.location.href.split("?")[0], "src": element.getAttribute("src") ||
"type": element.getAttribute("type"), window.location.href.split("?")[0],
"rel": element.getAttribute("rel") "type": element.getAttribute("type"),
}); "rel": element.getAttribute("rel")
} });
break; }
case "META": break;
case "TITLE": case "META":
break; case "TITLE":
case "SCRIPT": break;
// TODOS: this is bad, problem is gadgets being injected into case "SCRIPT":
// the DOM without iFrame, will also have all script tags // TODOS: this is bad, problem is gadgets being injected into
// inserted, so if they share any plugins (like renderJs), they // the DOM without iFrame, will also have all script tags
// will be re-requested and end up as additional instances // inserted, so if they share any plugins (like renderJs), they
// in the same scope, so renderJs.addGadget() will trigger x-times // will be re-requested and end up as additional instances
if (!content[i].getAttribute("src")) { // in the same scope, so renderJs.addGadget() will trigger x-times
newHTML.push(content[i]); if (!content[i].getAttribute("src")) {
}
break;
default:
// create a collection to append
newHTML.push(content[i]); newHTML.push(content[i]);
break; }
break;
default:
// create a collection to append
newHTML.push(content[i]);
break;
} }
} }
} }
...@@ -710,13 +728,13 @@ ...@@ -710,13 +728,13 @@
// append or replace (as below, remove duplicate code later) // append or replace (as below, remove duplicate code later)
if (options.wrapper) { if (options.wrapper) {
newParentElement = options.parent[0] || options.parent; newParentElement = options.parent[0] || options.parent;
$(options.wrapper).replaceWith( newHTML ); $(options.wrapper).replaceWith(newHTML);
} else if (options.replaceParent) { } else if (options.replaceParent) {
newParentElement = options.parent.parent()[0]; newParentElement = options.parent.parent()[0];
options.parent.replaceWith( newHTML ); options.parent.replaceWith(newHTML);
} else { } else {
newParentElement = options.parent; newParentElement = options.parent;
$( newHTML ).prependTo(options.parent); $(newHTML).prependTo(options.parent);
} }
if (callback) { if (callback) {
callback(); callback();
...@@ -728,7 +746,10 @@ ...@@ -728,7 +746,10 @@
} else { } else {
// IFRAME handler // IFRAME handler
newHTML = document.createElement("iframe"); newHTML = document.createElement("iframe");
newHTML.setAttribute("src", options.src + "?base=" + priv.encodeURI(options.directory.root)); newHTML.setAttribute(
"src",
options.src + "?base=" + priv.encodeURI(options.directory.root)
);
newHTML.setAttribute("frameborder", 0); newHTML.setAttribute("frameborder", 0);
newHTML.setAttribute("seamless", "seamless"); newHTML.setAttribute("seamless", "seamless");
newHTML.setAttribute("id", options.id); newHTML.setAttribute("id", options.id);
...@@ -736,25 +757,23 @@ ...@@ -736,25 +757,23 @@
// append or replace // append or replace
if (options.wrapper) { if (options.wrapper) {
newParentElement = options.parent[0] || options.parent; newParentElement = options.parent[0] || options.parent;
$(options.wrapper).replaceWith( newHTML ); $(options.wrapper).replaceWith(newHTML);
} else if (options.replaceParent) { } else if (options.replaceParent) {
newParentElement = options.parent.parent()[0]; newParentElement = options.parent.parent()[0];
options.parent.replaceWith( newHTML ); options.parent.replaceWith(newHTML);
} else { } else {
newParentElement = options.parent; newParentElement = options.parent;
$( newHTML ).prependTo(options.parent); $(newHTML).prependTo(options.parent);
} }
// select iframe // select iframe
newRootElement = newParentElement.querySelectorAll( newRootElement = newParentElement.querySelectorAll(
'[id="'+options.id+'"]' '[id="' + options.id + '"]'
); );
// add configuration and find recursive gadgets // add configuration and find recursive gadgets
$( newRootElement[0] ).load(function () { $(newRootElement[0]).load(function () {
var newElement = $(this); var newElement = $(this);
newWindow = newElement[0].contentWindow;
//newHref = newWindow.location.href;
// pass parameters to nested iFrame by setting on <iframe> body // pass parameters to nested iFrame by setting on <iframe> body
// if (options.param) { // if (options.param) {
...@@ -768,7 +787,7 @@ ...@@ -768,7 +787,7 @@
}); });
} }
}; };
// => initialize // => initialize
priv.initialize = function () { priv.initialize = function () {
...@@ -816,7 +835,7 @@ ...@@ -816,7 +835,7 @@
}; };
// => load gadget // => load gadget
that.addGadget = $.fn.addGadget = function (options, callback) { that.addGadget = $.fn.addGadget = function (options) {
var adressArray = window.location.href.split("?"); var adressArray = window.location.href.split("?");
// set parent // set parent
...@@ -840,8 +859,10 @@ ...@@ -840,8 +859,10 @@
}; };
} else { } else {
options.directory = { options.directory = {
"root": that.gadgetService ? that.gadgetService.root : window.location.href "root": that.gadgetService ?
} that.gadgetService.root :
window.location.href
};
} }
} }
// set offline // set offline
...@@ -867,18 +888,18 @@ ...@@ -867,18 +888,18 @@
priv.appendGadget(data, options); priv.appendGadget(data, options);
}, },
error: function (error, status, message) { error: function (error, status, message) {
console.log(error) console.log(error);
console.log(status) console.log(status);
console.log(message) console.log(message);
} }
}); });
} }
}; };
// => find gadgets inside a newly added gadget // => find gadgets inside a newly added gadget
that.findGadget = $.fn.findGadget = function () { that.findGadget = $.fn.findGadget = function (sentRoot) {
var root = root || this; var root = sentRoot || this,
var spec = {}; spec = {};
if (root[0].tagName === "IFRAME") { if (root[0].tagName === "IFRAME") {
// will not be possible in external iframe, because of cors! // will not be possible in external iframe, because of cors!
root = root[0].contentDocument || root[0].contentWindow.document; root = root[0].contentDocument || root[0].contentWindow.document;
...@@ -889,9 +910,9 @@ ...@@ -889,9 +910,9 @@
}; };
// => recursive call - find services inside newly added gadget // => recursive call - find services inside newly added gadget
that.findService = $.fn.findService = function () { that.findService = $.fn.findService = function (sentRoot) {
var root = root|| this; var root = sentRoot || this,
var spec = {}; spec = {};
if (root[0].tagName === "IFRAME") { if (root[0].tagName === "IFRAME") {
// will not be possible in external iframe, because of cors! // will not be possible in external iframe, because of cors!
root = root[0].contentDocument || root[0].contentWindow.document; root = root[0].contentDocument || root[0].contentWindow.document;
...@@ -903,11 +924,13 @@ ...@@ -903,11 +924,13 @@
// ================== ENTRY ============= // ================== ENTRY =============
// => start here // => start here
// should not use doc.ready, but otherwise cannot load reference body from <HEAD> // don't use doc.ready, but otherwise cannot load references to elements in
// body from <SCRIPT> in <HEAD>
$(document).ready(function() { $(document).ready(function() {
// prevent renderJs reloads from different URLs! // prevent renderJs reloads from different URLs!
// this does not solve the problem of re-requesting all dependencies with timestamp // this does not solve the problem of re-requesting dependencies
// when injecting elements into a page without iFrame // with ?timestamp=_123241231231 when injecting elements into a page
// without iFrame
if (window.renderJs === undefined) { if (window.renderJs === undefined) {
priv.initialize(); priv.initialize();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment