Bug 582023: making changes requested by Dao. Now iQ + Utils are ready for m-c with r=dao!
authorMichael Yoshitaka Erlewine <mitcho@mitcho.com>
Wed, 11 Aug 2010 13:06:49 -0400
changeset 50323 292c847cf3a0a4c7cfad7f930e9f0d877b731206
parent 50322 4e6f59ce5d1d4d107a41f57d9f1ea90be2b19304
child 50324 906a0b05656e3e44d2c8aaf276d85160175602e3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao
bugs582023
milestone2.0b4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 582023: making changes requested by Dao. Now iQ + Utils are ready for m-c with r=dao!
browser/base/content/tabview/iq.js
browser/base/content/tabview/modules/utils.jsm
--- a/browser/base/content/tabview/iq.js
+++ b/browser/base/content/tabview/iq.js
@@ -8,18 +8,17 @@
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is iq.js.
  *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  * Ian Gilman <ian@iangilman.com>
  * Aza Raskin <aza@mozilla.com>
  * Michael Yoshitaka Erlewine <mitcho@mitcho.com>
  *
@@ -119,17 +118,17 @@ let iQClass = function(selector, context
         if (ret) {
           if (Utils.isPlainObject(context)) {
             Utils.assert(false, 'does not support HTML creation with context');
           } else {
             selector = [doc.createElement(ret[1])];
           }
 
         } else {
-            Utils.assert(false, 'does not support complex HTML creation');
+          Utils.assert(false, 'does not support complex HTML creation');
         }
 
         return Utils.merge(this, selector);
 
       // HANDLE $("#id")
       } else {
         let elem = document.getElementById(match[2]);
 
@@ -205,20 +204,18 @@ iQClass.prototype = {
     }
     return this;
   },
 
   // ----------
   // Function: addClass
   // Adds the given class(es) to the receiver.
   addClass: function(value) {
-    if (typeof value != "string" || !value) {
-      Utils.assert(false, 'requires a valid string argument');
-      return null;
-    }
+    Utils.assertThrow(typeof value == "string" && value,
+                      'requires a valid string argument');
 
     let length = this.length;
     for (let i = 0; i < length; i++) {
       let elem = this[i];
       if (elem.nodeType === 1) {
         value.split(/\s+/).forEach(function(className) {
           elem.classList.add(className);
         });
@@ -523,67 +520,63 @@ iQClass.prototype = {
   //
   // Possible "options" properties:
   //   duration - how long to animate, in milliseconds
   //   easing - easing function to use. Possibilities include
   //     "tabviewBounce", "easeInQuad". Default is "ease".
   //   complete - function to call once the animation is done, takes nothing
   //     in, but "this" is set to the element that was animated.
   animate: function(css, options) {
-    try {
-      Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
+    Utils.assert(this.length == 1, 'does not yet support multi-objects (or null objects)');
 
-      if (!options)
-        options = {};
+    if (!options)
+      options = {};
 
-      let easings = {
-        tabviewBounce: "cubic-bezier(0.0, 0.63, .6, 1.0)", 
-        // TODO: change 1.0 above to 1.29 after bug 575672 is fixed
-        
-        easeInQuad: 'ease-in', // TODO: make it a real easeInQuad, or decide we don't care
-        fast: 'cubic-bezier(0.7,0,1,1)'
-      };
+    let easings = {
+      tabviewBounce: "cubic-bezier(0.0, 0.63, .6, 1.0)", 
+      // TODO: change 1.0 above to 1.29 after bug 575672 is fixed
+      
+      easeInQuad: 'ease-in', // TODO: make it a real easeInQuad, or decide we don't care
+      fast: 'cubic-bezier(0.7,0,1,1)'
+    };
+
+    let duration = (options.duration || 400);
+    let easing = (easings[options.easing] || 'ease');
 
-      let duration = (options.duration || 400);
-      let easing = (easings[options.easing] || 'ease');
+    // The latest versions of Firefox do not animate from a non-explicitly
+    // set css properties. So for each element to be animated, go through
+    // and explicitly define 'em.
+    let rupper = /([A-Z])/g;
+    this.each(function(elem) {
+      let cStyle = window.getComputedStyle(elem, null);
+      for (let prop in css) {
+        prop = prop.replace(rupper, "-$1").toLowerCase();
+        iQ(elem).css(prop, cStyle.getPropertyValue(prop));
+      }
+    });
 
-      // The latest versions of Firefox do not animate from a non-explicitly
-      // set css properties. So for each element to be animated, go through
-      // and explicitly define 'em.
-      let rupper = /([A-Z])/g;
-      this.each(function(elem) {
-        let cStyle = window.getComputedStyle(elem, null);
-        for (let prop in css) {
-          prop = prop.replace(rupper, "-$1").toLowerCase();
-          iQ(elem).css(prop, cStyle.getPropertyValue(prop));
-        }
+    this.css({
+      '-moz-transition-property': 'all', // TODO: just animate the properties we're changing
+      '-moz-transition-duration': (duration / 1000) + 's',
+      '-moz-transition-timing-function': easing
+    });
+
+    this.css(css);
+
+    let self = this;
+    setTimeout(function() {
+      self.css({
+        '-moz-transition-property': 'none',
+        '-moz-transition-duration': '',
+        '-moz-transition-timing-function': ''
       });
 
-      this.css({
-        '-moz-transition-property': 'all', // TODO: just animate the properties we're changing
-        '-moz-transition-duration': (duration / 1000) + 's',
-        '-moz-transition-timing-function': easing
-      });
-
-      this.css(css);
-
-      let self = this;
-      setTimeout(function() {
-        self.css({
-          '-moz-transition-property': 'none',
-          '-moz-transition-duration': '',
-          '-moz-transition-timing-function': ''
-        });
-
-        if (typeof options.complete == "function")
-          options.complete.apply(self);
-      }, duration);
-    } catch(e) {
-      Utils.log(e);
-    }
+      if (typeof options.complete == "function")
+        options.complete.apply(self);
+    }, duration);
 
     return this;
   },
 
   // ----------
   // Function: fadeOut
   // Animates the receiver to full transparency. Calls callback on completion.
   fadeOut: function(callback) {
@@ -634,25 +627,17 @@ iQClass.prototype = {
     return this;
   },
 
   // ----------
   // Function: bind
   // Binds the given function to the given event type. Also wraps the function
   // in a try/catch block that does a Utils.log on any errors.
   bind: function(type, func) {
-    Utils.assert(typeof func == "function", 'does not support eventData argument');
-
-    let handler = function(event) {
-      try {
-        return func.apply(this, [event]);
-      } catch(e) {
-        Utils.log(e);
-      }
-    };
+    let handler = function(event) func.apply(this, [event]);
 
     for (let i = 0; this[i] != null; i++) {
       let elem = this[i];
       if (!elem.iQEventData)
         elem.iQEventData = {};
 
       if (!elem.iQEventData[type])
         elem.iQEventData[type] = [];
--- a/browser/base/content/tabview/modules/utils.jsm
+++ b/browser/base/content/tabview/modules/utils.jsm
@@ -45,20 +45,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 // **********
 // Title: utils.js
 
 let EXPORTED_SYMBOLS = ["Point", "Rect", "Range", "Subscribable", "Utils"];
 
 // #########
-const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
-const Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 
 // ##########
 // Class: Point
 // A simple point.
 //
 // Constructor: Point
@@ -132,19 +130,19 @@ Rect.prototype = {
   // Gives you a new <Range> for the vertical dimension.
   get yRange() new Range(this.top, this.bottom),
 
   // ----------
   // Function: intersects
   // Returns true if this rectangle intersects the given <Rect>.
   intersects: function(rect) {
     return (rect.right > this.left &&
-           rect.left < this.right &&
-           rect.bottom > this.top &&
-           rect.top < this.bottom);
+            rect.left < this.right &&
+            rect.bottom > this.top &&
+            rect.top < this.bottom);
   },
 
   // ----------
   // Function: intersection
   // Returns a new <Rect> with the intersection of this rectangle and the give <Rect>,
   // or null if they don't intersect.
   intersection: function(rect) {
     var box = new Rect(Math.max(rect.left, this.left), Math.max(rect.top, this.top), 0, 0);
@@ -160,19 +158,19 @@ Rect.prototype = {
   // Function: contains
   // Returns a boolean denoting if the <Rect> is contained inside
   // of the bounding rect.
   //
   // Paramaters
   //  - A <Rect>
   contains: function(rect) {
     return (rect.left > this.left &&
-           rect.right < this.right &&
-           rect.top > this.top &&
-           rect.bottom < this.bottom);
+            rect.right < this.right &&
+            rect.top > this.top &&
+            rect.bottom < this.bottom);
   },
 
   // ----------
   // Function: center
   // Returns a new <Point> with the center location of this rectangle.
   center: function() {
     return new Point(this.left + (this.width / 2), this.top + (this.height / 2));
   },
@@ -233,19 +231,19 @@ Rect.prototype = {
     }
   },
 
   // ----------
   // Function: equals
   // Returns true if this rectangle is identical to the given <Rect>.
   equals: function(rect) {
     return (rect.left == this.left &&
-           rect.top == this.top &&
-           rect.width == this.width &&
-           rect.height == this.height);
+            rect.top == this.top &&
+            rect.width == this.width &&
+            rect.height == this.height);
   },
 
   // ----------
   // Function: union
   // Returns a new <Rect> with the union of this rectangle and the given <Rect>.
   union: function(a) {
     var newLeft = Math.min(a.left, this.left);
     var newTop = Math.min(a.top, this.top);
@@ -312,21 +310,21 @@ Range.prototype = {
 
   // ----------
   // Function: contains
   // Whether the <Range> contains the given <Range> or value or not.
   //
   // Paramaters
   //  - a number or <Range>
   contains: function(value) {
-    return Utils.isNumber(value) ?
-      value >= this.min && value <= this.max :
-      Utils.isRange(value) ?
-        (value.min <= this.max && this.min <= value.max) :
-        false;
+    if (Utils.isNumber(value))
+      return value >= this.min && value <= this.max;
+    if (Utils.isRange(value))
+      return value.min >= this.min && value.max <= this.max;
+    return false;
   },
 
   // ----------
   // Function: proportion
   // Maps the given value to the range [0,1], so that it returns 0 if the value is <= the min,
   // returns 1 if the value >= the max, and returns an interpolated "proportion" in (min, max).
   //
   // Paramaters
@@ -383,81 +381,87 @@ Subscribable.prototype = {
   // The given callback will be called when the Subscribable fires the given event.
   // The refObject is used to facilitate removal if necessary.
   addSubscriber: function(refObject, eventName, callback) {
     try {
       Utils.assertThrow(refObject, "refObject");
       Utils.assertThrow(typeof callback == "function", "callback must be a function");
       Utils.assertThrow(eventName && typeof eventName == "string",
           "eventName must be a non-empty string");
-
-      if (!this.subscribers)
-        this.subscribers = {};
-
-      if (!this.subscribers[eventName])
-        this.subscribers[eventName] = [];
-
-      var subs = this.subscribers[eventName];
-      var existing = subs.filter(function(element) {
-        return element.refObject == refObject;
-      });
-
-      if (existing.length) {
-        Utils.assert(existing.length == 1, 'should only ever be one');
-        existing[0].callback = callback;
-      } else {
-        subs.push({
-          refObject: refObject,
-          callback: callback
-        });
-      }
     } catch(e) {
       Utils.log(e);
+      return;
+    }
+
+    if (!this.subscribers)
+      this.subscribers = {};
+
+    if (!this.subscribers[eventName])
+      this.subscribers[eventName] = [];
+
+    var subs = this.subscribers[eventName];
+    var existing = subs.filter(function(element) {
+      return element.refObject == refObject;
+    });
+
+    if (existing.length) {
+      Utils.assert(existing.length == 1, 'should only ever be one');
+      existing[0].callback = callback;
+    } else {
+      subs.push({
+        refObject: refObject,
+        callback: callback
+      });
     }
   },
 
   // ----------
   // Function: removeSubscriber
   // Removes the callback associated with refObject for the given event.
   removeSubscriber: function(refObject, eventName) {
     try {
       Utils.assertThrow(refObject, "refObject");
       Utils.assertThrow(eventName && typeof eventName == "string",
           "eventName must be a non-empty string");
-
-      if (!this.subscribers || !this.subscribers[eventName])
-        return;
-
-      this.subscribers[eventName] = this.subscribers[eventName].filter(function(element) {
-        return element.refObject != refObject;
-      });
     } catch(e) {
       Utils.log(e);
+      return;
     }
+
+    if (!this.subscribers || !this.subscribers[eventName])
+      return;
+
+    this.subscribers[eventName] = this.subscribers[eventName].filter(function(element) {
+      return element.refObject != refObject;
+    });
   },
 
   // ----------
   // Function: _sendToSubscribers
   // Internal routine. Used by the Subscribable to fire events.
   _sendToSubscribers: function(eventName, eventInfo) {
     try {
       Utils.assertThrow(eventName && typeof eventName == "string",
           "eventName must be a non-empty string");
-
-      if (!this.subscribers || !this.subscribers[eventName])
-        return;
-
-      var self = this;
-      var subsCopy = this.subscribers[eventName].concat();
-      subsCopy.forEach(function(object) {
-        object.callback(self, eventInfo);
-      });
     } catch(e) {
       Utils.log(e);
+      return;
     }
+
+    if (!this.subscribers || !this.subscribers[eventName])
+      return;
+
+    var subsCopy = this.subscribers[eventName].concat();
+    subsCopy.forEach(function(object) {
+      try {
+        object.callback(this, eventInfo);
+      } catch(e) {
+        Utils.log(e);
+      }
+    }, this);
   }
 };
 
 // ##########
 // Class: Utils
 // Singelton with common utility functions.
 let Utils = {
   // ___ Logging
@@ -587,29 +591,29 @@ let Utils = {
     return typeof n == 'number' && !isNaN(n);
   },
 
   // ----------
   // Function: isRect
   // Returns true if the given object (r) looks like a <Rect>.
   isRect: function(r) {
     return (r &&
-           this.isNumber(r.left) &&
-           this.isNumber(r.top) &&
-           this.isNumber(r.width) &&
-           this.isNumber(r.height));
+            this.isNumber(r.left) &&
+            this.isNumber(r.top) &&
+            this.isNumber(r.width) &&
+            this.isNumber(r.height));
   },
 
   // ----------
   // Function: isRange
   // Returns true if the given object (r) looks like a <Range>.
   isRange: function(r) {
     return (r &&
-           this.isNumber(r.min) &&
-           this.isNumber(r.max));
+            this.isNumber(r.min) &&
+            this.isNumber(r.max));
   },
 
   // ----------
   // Function: isPoint
   // Returns true if the given object (p) looks like a <Point>.
   isPoint: function(p) {
     return (p && this.isNumber(p.x) && this.isNumber(p.y));
   },