]> git.donarmstrong.com Git - dactyl.git/blobdiff - common/modules/dom.jsm
Import 1.0 supporting Firefox up to 14.*
[dactyl.git] / common / modules / dom.jsm
index 981ec9c8a26d1cb3d332f928e3f88b1cc1e5db14..9f7f7e5f9a38bd831e456506876c0c688559688b 100644 (file)
@@ -10,6 +10,9 @@ defineModule("dom", {
     exports: ["$", "DOM", "NS", "XBL", "XHTML", "XUL"]
 }, this);
 
+this.lazyRequire("highlight", ["highlight"]);
+this.lazyRequire("template", ["template"]);
+
 var XBL = Namespace("xbl", "http://www.mozilla.org/xbl");
 var XHTML = Namespace("html", "http://www.w3.org/1999/xhtml");
 var XUL = Namespace("xul", "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@@ -55,12 +58,12 @@ var DOM = Class("DOM", {
             this[length++] = DOM.fromXML(val, context, this.nodes);
         else if (val instanceof Ci.nsIDOMNode || val instanceof Ci.nsIDOMWindow)
             this[length++] = val;
-        else if ("length" in val)
-            for (let i = 0; i < val.length; i++)
-                this[length++] = val[i];
         else if ("__iterator__" in val || isinstance(val, ["Iterator", "Generator"]))
             for (let elem in val)
                 this[length++] = elem;
+        else if ("length" in val)
+            for (let i = 0; i < val.length; i++)
+                this[length++] = val[i];
         else
             this[length++] = val;
 
@@ -191,11 +194,11 @@ var DOM = Class("DOM", {
         this.each(function (elem) {
             while(true) {
                 elem = fn.call(this, elem)
-                if (elem instanceof Ci.nsIDOMElement)
+                if (elem instanceof Ci.nsIDOMNode)
                     res[res.length++] = elem;
                 else if (elem && "length" in elem)
-                    for (let i = 0; i < tmp.length; i++)
-                        res[res.length++] = tmp[j];
+                    for (let i = 0; i < elem.length; i++)
+                        res[res.length++] = elem[j];
                 else
                     break;
             }
@@ -256,6 +259,9 @@ var DOM = Class("DOM", {
     get siblingsBefore() this.all(function (elem) elem.previousElementSibling),
     get siblingsAfter() this.all(function (elem) elem.nextElementSibling),
 
+    get allSiblingsBefore() this.all(function (elem) elem.previousSibling),
+    get allSiblingsAfter() this.all(function (elem) elem.nextSibling),
+
     get class() let (self = this) ({
         toString: function () self[0].className,
 
@@ -318,22 +324,26 @@ var DOM = Class("DOM", {
                this[0]                            ? this[0].getBoundingClientRect() : {},
 
     get viewport() {
-        if (this[0] instanceof Ci.nsIDOMWindow)
+        let node = this[0];
+        if (node instanceof Ci.nsIDOMDocument)
+            node = node.defaultView;
+
+        if (node instanceof Ci.nsIDOMWindow)
             return {
                 get width() this.right - this.left,
                 get height() this.bottom - this.top,
-                bottom: this[0].innerHeight,
-                right: this[0].innerWidth,
+                bottom: node.innerHeight,
+                right: node.innerWidth,
                 top: 0, left: 0
             };
 
         let r = this.rect;
         return {
-            width: this[0].clientWidth,
-            height: this[0].clientHeight,
-            top: r.top + this[0].clientTop,
+            width: node.clientWidth,
+            height: node.clientHeight,
+            top: r.top + node.clientTop,
             get bottom() this.top + this.height,
-            left: r.left + this[0].clientLeft,
+            left: r.left + node.clientLeft,
             get right() this.left + this.width
         }
     },
@@ -406,7 +416,7 @@ var DOM = Class("DOM", {
         return editor;
     },
 
-    get isEditable() !!this.editor,
+    get isEditable() !!this.editor || this[0] instanceof Ci.nsIDOMElement && this.style.MozUserModify == "read-write",
 
     get isInput() isinstance(this[0], [Ci.nsIDOMHTMLInputElement,
                                        Ci.nsIDOMHTMLTextAreaElement,
@@ -784,25 +794,44 @@ var DOM = Class("DOM", {
         else
             event = array.toObject([[event, listener]]);
 
-        for (let [k, v] in Iterator(event))
-            event[k] = util.wrapCallback(v, true);
+        for (let [evt, callback] in Iterator(event))
+            event[evt] = util.wrapCallback(callback, true);
 
         return this.each(function (elem) {
-            for (let [k, v] in Iterator(event))
-                elem.addEventListener(k, v, capture);
+            for (let [evt, callback] in Iterator(event))
+                elem.addEventListener(evt, callback, capture);
         });
     },
     unlisten: function unlisten(event, listener, capture) {
         if (isObject(event))
             capture = listener;
         else
-            event = array.toObject([[key, val]]);
+            event = array.toObject([[event, listener]]);
 
         return this.each(function (elem) {
             for (let [k, v] in Iterator(event))
                 elem.removeEventListener(k, v.wrapper || v, capture);
         });
     },
+    once: function once(event, listener, capture) {
+        if (isObject(event))
+            capture = listener;
+        else
+            event = array.toObject([[event, listener]]);
+
+        for (let pair in Iterator(event)) {
+            let [evt, callback] = pair;
+            event[evt] = util.wrapCallback(function wrapper(event) {
+                this.removeEventListener(evt, wrapper.wrapper, capture);
+                return callback.apply(this, arguments);
+            }, true);
+        }
+
+        return this.each(function (elem) {
+            for (let [k, v] in Iterator(event))
+                elem.addEventListener(k, v, capture);
+        });
+    },
 
     dispatch: function dispatch(event, params, extraProps) {
         this.canceled = false;
@@ -945,21 +974,30 @@ var DOM = Class("DOM", {
             //       want to refer to within dactyl's source code for
             //       comparisons like if (key == "<Esc>") { ... }
             this.keyTable = {
-                add: ["Plus", "Add"],
+                add: ["+", "Plus", "Add"],
+                back_quote: ["`"],
+                back_slash: ["\\"],
                 back_space: ["BS"],
+                comma: [","],
                 count: ["count"],
+                close_bracket: ["]"],
                 delete: ["Del"],
+                equals: ["="],
                 escape: ["Esc", "Escape"],
                 insert: ["Insert", "Ins"],
                 leader: ["Leader"],
                 left_shift: ["LT", "<"],
                 nop: ["Nop"],
+                open_bracket: ["["],
                 pass: ["Pass"],
+                period: ["."],
+                quote: ["'"],
                 return: ["Return", "CR", "Enter"],
                 right_shift: [">"],
+                semicolon: [";"],
                 slash: ["/"],
                 space: ["Space", " "],
-                subtract: ["Minus", "Subtract"]
+                subtract: ["-", "Minus", "Subtract"]
             };
 
             this.key_key = {};
@@ -1176,7 +1214,9 @@ var DOM = Class("DOM", {
                     if (event.keyCode in this.code_key) {
                         key = this.code_key[event.keyCode];
 
-                        if (event.shiftKey && (key.length > 1 || event.ctrlKey || event.altKey || event.metaKey) || event.dactylShift)
+                        if (event.shiftKey && (key.length > 1 || key.toUpperCase() == key.toLowerCase()
+                                               || event.ctrlKey || event.altKey || event.metaKey)
+                                || event.dactylShift)
                             modifier += "S-";
                         else if (!modifier && key.length === 1)
                             if (event.shiftKey)
@@ -1530,12 +1570,16 @@ var DOM = Class("DOM", {
                     null
                 );
 
-                return Object.create(result, {
-                    __iterator__: {
-                        value: asIterator ? function () { let elem; while ((elem = this.iterateNext())) yield elem; }
-                                          : function () { for (let i = 0; i < this.snapshotLength; i++) yield this.snapshotItem(i); }
-                    }
-                });
+                let res = {
+                    iterateNext: function () result.iterateNext(),
+                    get resultType() result.resultType,
+                    get snapshotLength() result.snapshotLength,
+                    snapshotItem: function (i) result.snapshotItem(i),
+                    __iterator__:
+                        asIterator ? function () { let elem; while ((elem = this.iterateNext())) yield elem; }
+                                   : function () { for (let i = 0; i < this.snapshotLength; i++) yield this.snapshotItem(i); }
+                };
+                return res;
             }
             catch (e) {
                 throw e.stack ? e : Error(e);