diff --git a/src/drivers/webextension/_locales/en/messages.json b/src/drivers/webextension/_locales/en/messages.json index 3edc49047..94a1db7d8 100644 --- a/src/drivers/webextension/_locales/en/messages.json +++ b/src/drivers/webextension/_locales/en/messages.json @@ -18,7 +18,7 @@ "categoryName6": { "message": "Ecommerce" }, "categoryName7": { "message": "Photo Galleries" }, "categoryName8": { "message": "Wikis" }, - "categoryName9": { "message": "Hostin Panels" }, + "categoryName9": { "message": "Hosting Panels" }, "categoryName10": { "message": "Analytics" }, "categoryName11": { "message": "Blog" }, "categoryName12": { "message": "JavaScript Framework" }, diff --git a/src/drivers/webextension/js/i18n.js b/src/drivers/webextension/js/i18n.js index c5ea110e3..6921c0f0f 100644 --- a/src/drivers/webextension/js/i18n.js +++ b/src/drivers/webextension/js/i18n.js @@ -4,6 +4,6 @@ document.addEventListener('DOMContentLoaded', function() { var nodes = document.querySelectorAll('[data-i18n]'); nodes.forEach(function(node) { - node.innerHTML = browser.i18n.getMessage(node.dataset.i18n); + node.childNodes[0].nodeValue = browser.i18n.getMessage(node.dataset.i18n); }); }); diff --git a/src/drivers/webextension/js/jsontodom.js b/src/drivers/webextension/js/jsontodom.js new file mode 100644 index 000000000..d77df83f8 --- /dev/null +++ b/src/drivers/webextension/js/jsontodom.js @@ -0,0 +1,63 @@ +jsonToDOM.namespaces = { + html: "http://www.w3.org/1999/xhtml", + xul: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" +}; + +jsonToDOM.defaultNamespace = jsonToDOM.namespaces.html; + +function jsonToDOM(jsonTemplate, doc, nodes) { + function namespace(name) { + var reElemNameParts = /^(?:(.*):)?(.*)$/.exec(name); + return { namespace: jsonToDOM.namespaces[reElemNameParts[1]], shortName: reElemNameParts[2] }; + } + + // Note that 'elemNameOrArray' is: either the full element name (eg. [html:]div) or an array of elements in JSON notation + function tag(elemNameOrArray, elemAttr) { + // Array of elements? Parse each one... + if (Array.isArray(elemNameOrArray)) { + var frag = doc.createDocumentFragment(); + Array.forEach(arguments, function(thisElem) { + frag.appendChild(tag.apply(null, thisElem)); + }); + return frag; + } + + // Single element? Parse element namespace prefix (if none exists, default to defaultNamespace), and create element + var elemNs = namespace(elemNameOrArray); + var elem = doc.createElementNS(elemNs.namespace || jsonToDOM.defaultNamespace, elemNs.shortName); + + // Set element's attributes and/or callback functions (eg. onclick) + for (var key in elemAttr) { + var val = elemAttr[key]; + if (nodes && key == "key") { + nodes[val] = elem; + continue; + } + + var attrNs = namespace(key); + if (typeof val == "function") { + // Special case for function attributes; don't just add them as 'on...' attributes, but as events, using addEventListener + elem.addEventListener(key.replace(/^on/, ""), val, false); + } + else { + // Note that the default namespace for XML attributes is, and should be, blank (ie. they're not in any namespace) + elem.setAttributeNS(attrNs.namespace || "", attrNs.shortName, val); + } + } + + // Create and append this element's children + var childElems = Array.slice(arguments, 2); + childElems.forEach(function(childElem) { + if (childElem != null) { + elem.appendChild( + childElem instanceof doc.defaultView.Node ? childElem : + Array.isArray(childElem) ? tag.apply(null, childElem) : + doc.createTextNode(childElem)); + } + }); + + return elem; + } + + return tag.apply(null, jsonTemplate); +} diff --git a/src/drivers/webextension/js/popup.js b/src/drivers/webextension/js/popup.js index eb760d34c..88fcf6eb8 100644 --- a/src/drivers/webextension/js/popup.js +++ b/src/drivers/webextension/js/popup.js @@ -9,7 +9,9 @@ if ( /complete|interacrive|loaded/.test(document.readyState) ) { popup.displayApps(response) } else { - document.addEventListener('DOMContentLoaded', function() { popup.displayApps(response) }); + document.addEventListener('DOMContentLoaded', function() { + popup.displayApps(response) + }); } }); }; @@ -26,45 +28,80 @@ displayApps: function(response) { var appName, confidence, version, - detectedApps = document.querySelector('#detected-apps'); - html = ''; + detectedApps = document.querySelector('#detected-apps'), + categories = [], + json = []; if ( response.tabCache && response.tabCache.count > 0 ) { for ( appName in response.tabCache.appsDetected ) { confidence = response.tabCache.appsDetected[appName].confidenceTotal; version = response.tabCache.appsDetected[appName].version; - html += - '