-// Copyright (c) 2009-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2009-2012 Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
try {
-Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("overlay", {
exports: ["overlay"],
require: ["util"]
-}, this);
+});
+
+lazyRequire("highlight", ["highlight"]);
var getAttr = function getAttr(elem, ns, name)
elem.hasAttributeNS(ns, name) ? elem.getAttributeNS(ns, name) : null;
util.addObserver(this);
this.overlays = {};
+ this.weakMap = WeakMap();
+
this.onWindowVisible = [];
},
},
getData: function getData(obj, key, constructor) {
- let { id } = this;
- if (!(id in obj && obj[id]))
- obj[id] = {};
+ if (!this.weakMap.has(obj))
+ try {
+ this.weakMap.set(obj, {});
+ }
+ catch (e if e instanceof TypeError) {
+ // util.dump("Bad WeakMap key: " + obj + " " + Components.stack.caller);
+ let { id } = this;
+
+ if (!(id in obj && obj[id]))
+ obj[id] = {};
+
+ var data = obj[id];
+ }
+
+ data = data || this.weakMap.get(obj);
if (arguments.length == 1)
- return obj[id];
+ return data;
- if (obj[id][key] === undefined)
+ if (data[key] === undefined)
if (constructor === undefined || callable(constructor))
- obj[id][key] = (constructor || Array)();
+ data[key] = (constructor || Array)();
else
- obj[id][key] = constructor;
+ data[key] = constructor;
- return obj[id][key];
+ return data[key];
},
setData: function setData(obj, key, val) {
- let { id } = this;
-
- if (!(id in obj))
- obj[id] = {};
+ let data = this.getData(obj);
- return obj[id][key] = val;
+ return data[key] = val;
},
overlayWindow: function (url, fn) {
_loadOverlay: function _loadOverlay(window, obj) {
let doc = window.document;
- let elems = this.getData(doc, "overlayElements");
- let attrs = this.getData(doc, "overlayAttributes");
+ let savedElems = this.getData(doc, "overlayElements");
+ let savedAttrs = this.getData(doc, "overlayAttributes");
function insert(key, fn) {
if (obj[key]) {
let iterator = Iterator(obj[key]);
- if (!isObject(obj[key]))
- iterator = ([elem.@id, elem.elements(), elem.@*::*.(function::name() != "id")] for each (elem in obj[key]));
+ if (isArray(obj[key])) {
+ iterator = ([elem[1].id, elem.slice(2), elem[1]]
+ for each (elem in obj[key]))
+ }
+
+ for (let [elem, xml, attrs] in iterator) {
+ if (elem = doc.getElementById(String(elem))) {
+ // Urgh. Hack.
+ let namespaces;
+ if (attrs && !isXML(attrs))
+ namespaces = iter([k.slice(6), DOM.fromJSON.namespaces[v] || v]
+ for ([k, v] in Iterator(attrs))
+ if (/^xmlns(?:$|:)/.test(k))).toObject();
+
+ let node;
+ if (isXML(xml))
+ node = DOM.fromXML(xml, doc, obj.objects);
+ else
+ node = DOM.fromJSON(xml, doc, obj.objects, namespaces);
- for (let [elem, xml, attr] in iterator) {
- if (elem = doc.getElementById(elem)) {
- let node = DOM.fromXML(xml, doc, obj.objects);
if (!(node instanceof Ci.nsIDOMDocumentFragment))
- elems.push(node);
+ savedElems.push(node);
else
for (let n in array.iterValues(node.childNodes))
- elems.push(n);
+ savedElems.push(n);
fn(elem, node);
- for each (let attr in attr || []) {
- let ns = attr.namespace(), name = attr.localName();
- attrs.push([elem, ns, name, getAttr(elem, ns, name), String(attr)]);
- if (attr.name() != "highlight")
- elem.setAttributeNS(ns, name, String(attr));
+
+ if (isXML(attrs))
+ // Evilness and such.
+ let (oldAttrs = attrs) {
+ attrs = (attr for each (attr in oldAttrs));
+ }
+
+ for (let attr in attrs || []) {
+ let [ns, localName] = DOM.parseNamespace(attr);
+ let name = attr;
+ let val = attrs[attr];
+
+ savedAttrs.push([elem, ns, name, getAttr(elem, ns, name), val]);
+ if (name === "highlight")
+ highlight.highlightNode(elem, val);
else
- highlight.highlightNode(elem, String(attr));
+ elem.setAttributeNS(ns || "", name, val);
}
}
}