X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/c930e9176a5a85509c5b0230e2bff5c22a591432..92c2b89db26be16707f4a805d3303ab2531006e1:/docs/source/Observable.html?ds=inline diff --git a/docs/source/Observable.html b/docs/source/Observable.html index b8119a9f..2640fd6a 100644 --- a/docs/source/Observable.html +++ b/docs/source/Observable.html @@ -1,5 +1,6 @@ + The source code @@ -13,7 +14,7 @@ var EXTUTIL = Ext.util, ISOBJECT = Ext.isObject, TRUE = true, FALSE = false; -
/** +/** * @class Ext.util.Observable * Base class that provides a common interface for publishing events. Subclasses are expected to * to have a property "events" with all the events defined, and, optionally, a property "listeners" @@ -117,216 +118,223 @@ var combo = new Ext.form.ComboBox({ me.events = e || {}; }; -EXTUTIL.Observable.prototype = function(){ - var filterOptRe = /^(?:scope|delay|buffer|single)$/, toLower = function(s){ - return s.toLowerCase(); - }; - - return { -
/** - *

Fires the specified event with the passed parameters (minus the event name).

- *

An event may be set to bubble up an Observable parent hierarchy (See {@link Ext.Component#getBubbleTarget}) - * by calling {@link #enableBubble}.

- * @param {String} eventName The name of the event to fire. - * @param {Object...} args Variable number of parameters are passed to handlers. - * @return {Boolean} returns false if any of the handlers return false otherwise it returns true. - */ - - fireEvent : function(){ - var a = TOARRAY(arguments), - ename = toLower(a[0]), - me = this, - ret = TRUE, - ce = me.events[ename], - q, - c; - if (me.eventsSuspended === TRUE) { - if (q = me.suspendedEventsQueue) { - q.push(a); - } +EXTUTIL.Observable.prototype = { + // private + filterOptRe : /^(?:scope|delay|buffer|single)$/, + +
/** + *

Fires the specified event with the passed parameters (minus the event name).

+ *

An event may be set to bubble up an Observable parent hierarchy (See {@link Ext.Component#getBubbleTarget}) + * by calling {@link #enableBubble}.

+ * @param {String} eventName The name of the event to fire. + * @param {Object...} args Variable number of parameters are passed to handlers. + * @return {Boolean} returns false if any of the handlers return false otherwise it returns true. + */ + fireEvent : function(){ + var a = TOARRAY(arguments), + ename = a[0].toLowerCase(), + me = this, + ret = TRUE, + ce = me.events[ename], + q, + c; + if (me.eventsSuspended === TRUE) { + if (q = me.eventQueue) { + q.push(a); } - else if(ISOBJECT(ce) && ce.bubble){ - if(ce.fire.apply(ce, a.slice(1)) === FALSE) { - return FALSE; - } - c = me.getBubbleTarget && me.getBubbleTarget(); - if(c && c.enableBubble) { + } + else if(ISOBJECT(ce) && ce.bubble){ + if(ce.fire.apply(ce, a.slice(1)) === FALSE) { + return FALSE; + } + c = me.getBubbleTarget && me.getBubbleTarget(); + if(c && c.enableBubble) { + if(!c.events[ename] || !Ext.isObject(c.events[ename]) || !c.events[ename].bubble) { c.enableBubble(ename); - return c.fireEvent.apply(c, a); } + return c.fireEvent.apply(c, a); } - else { - if (ISOBJECT(ce)) { - a.shift(); - ret = ce.fire.apply(ce, a); - } + } + else { + if (ISOBJECT(ce)) { + a.shift(); + ret = ce.fire.apply(ce, a); } - return ret; - }, - -
/** - * Appends an event handler to this object. - * @param {String} eventName The name of the event to listen for. - * @param {Function} handler The method the event invokes. - * @param {Object} scope (optional) The scope (this reference) in which the handler function is executed. - * If omitted, defaults to the object which fired the event. - * @param {Object} options (optional) An object containing handler configuration. - * properties. This may contain any of the following properties:
- *

- * Combining Options
- * Using the options argument, it is possible to combine different types of listeners:
- *
- * A delayed, one-time listener. - *


-myDataView.on('click', this.onClick, this, {
-    single: true,
-    delay: 100
-});
- *

- * Attaching multiple handlers in 1 call
- * The method also allows for a single argument to be passed which is a config object containing properties - * which specify multiple handlers. - *

- *


-myGridPanel.on({
-    'click' : {
-        fn: this.onClick,
-        scope: this,
-        delay: 100
-    },
-    'mouseover' : {
-        fn: this.onMouseOver,
-        scope: this
+        }
+        return ret;
     },
-    'mouseout' : {
-        fn: this.onMouseOut,
-        scope: this
-    }
+
+    
/** + * Appends an event handler to this object. + * @param {String} eventName The name of the event to listen for. + * @param {Function} handler The method the event invokes. + * @param {Object} scope (optional) The scope (this reference) in which the handler function is executed. + * If omitted, defaults to the object which fired the event. + * @param {Object} options (optional) An object containing handler configuration. + * properties. This may contain any of the following properties:
+ *

+ * Combining Options
+ * Using the options argument, it is possible to combine different types of listeners:
+ *
+ * A delayed, one-time listener. + *


+myDataView.on('click', this.onClick, this, {
+single: true,
+delay: 100
 });
*

- * Or a shorthand syntax:
+ * Attaching multiple handlers in 1 call
+ * The method also allows for a single argument to be passed which is a config object containing properties + * which specify multiple handlers. + *

*


 myGridPanel.on({
-    'click' : this.onClick,
-    'mouseover' : this.onMouseOver,
-    'mouseout' : this.onMouseOut,
-     scope: this
+'click' : {
+    fn: this.onClick,
+    scope: this,
+    delay: 100
+},
+'mouseover' : {
+    fn: this.onMouseOver,
+    scope: this
+},
+'mouseout' : {
+    fn: this.onMouseOut,
+    scope: this
+}
 });
- */ - addListener : function(eventName, fn, scope, o){ - var me = this, - e, - oe, - isF, - ce; - if (ISOBJECT(eventName)) { - o = eventName; - for (e in o){ - oe = o[e]; - if (!filterOptRe.test(e)) { - me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o); - } - } - } else { - eventName = toLower(eventName); - ce = me.events[eventName] || TRUE; - if (typeof ce == "boolean") { - me.events[eventName] = ce = new EXTUTIL.Event(me, eventName); + *

+ * Or a shorthand syntax:
+ *


+myGridPanel.on({
+'click' : this.onClick,
+'mouseover' : this.onMouseOver,
+'mouseout' : this.onMouseOut,
+ scope: this
+});
+ */ + addListener : function(eventName, fn, scope, o){ + var me = this, + e, + oe, + isF, + ce; + if (ISOBJECT(eventName)) { + o = eventName; + for (e in o){ + oe = o[e]; + if (!me.filterOptRe.test(e)) { + me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o); } - ce.addListener(fn, scope, ISOBJECT(o) ? o : {}); } - }, - -
/** - * Removes an event handler. - * @param {String} eventName The type of event the handler was associated with. - * @param {Function} handler The handler to remove. This must be a reference to the function passed into the {@link #addListener} call. - * @param {Object} scope (optional) The scope originally specified for the handler. - */ - removeListener : function(eventName, fn, scope){ - var ce = this.events[toLower(eventName)]; - if (ISOBJECT(ce)) { - ce.removeListener(fn, scope); - } - }, - -
/** - * Removes all listeners for this object - */ - purgeListeners : function(){ - var events = this.events, - evt, - key; - for(key in events){ - evt = events[key]; - if(ISOBJECT(evt)){ - evt.clearListeners(); - } + } else { + eventName = eventName.toLowerCase(); + ce = me.events[eventName] || TRUE; + if (Ext.isBoolean(ce)) { + me.events[eventName] = ce = new EXTUTIL.Event(me, eventName); } - }, - -
/** - * Used to define events on this Observable - * @param {Object} object The object with the events defined - */ - addEvents : function(o){ - var me = this; - me.events = me.events || {}; - if (typeof o == 'string') { - EACH(arguments, function(a) { - me.events[a] = me.events[a] || TRUE; - }); - } else { - Ext.applyIf(me.events, o); + ce.addListener(fn, scope, ISOBJECT(o) ? o : {}); + } + }, + +
/** + * Removes an event handler. + * @param {String} eventName The type of event the handler was associated with. + * @param {Function} handler The handler to remove. This must be a reference to the function passed into the {@link #addListener} call. + * @param {Object} scope (optional) The scope originally specified for the handler. + */ + removeListener : function(eventName, fn, scope){ + var ce = this.events[eventName.toLowerCase()]; + if (ISOBJECT(ce)) { + ce.removeListener(fn, scope); + } + }, + +
/** + * Removes all listeners for this object + */ + purgeListeners : function(){ + var events = this.events, + evt, + key; + for(key in events){ + evt = events[key]; + if(ISOBJECT(evt)){ + evt.clearListeners(); } - }, - -
/** - * Checks to see if this object has any listeners for a specified event - * @param {String} eventName The name of the event to check for - * @return {Boolean} True if the event is being listened for, else false - */ - hasListener : function(eventName){ - var e = this.events[eventName]; - return ISOBJECT(e) && e.listeners.length > 0; - }, - -
/** - * Suspend the firing of all events. (see {@link #resumeEvents}) - * @param {Boolean} queueSuspended Pass as true to queue up suspended events to be fired - * after the {@link #resumeEvents} call instead of discarding all suspended events; - */ - suspendEvents : function(queueSuspended){ - this.eventsSuspended = TRUE; - if (queueSuspended){ - this.suspendedEventsQueue = []; + } + }, + +
/** + * Adds the specified events to the list of events which this Observable may fire. + * @param {Object|String} o Either an object with event names as properties with a value of true + * or the first event name string if multiple event names are being passed as separate parameters. + * @param {string} Optional. Event name if multiple event names are being passed as separate parameters. + * Usage:

+this.addEvents('storeloaded', 'storecleared');
+
+ */ + addEvents : function(o){ + var me = this; + me.events = me.events || {}; + if (Ext.isString(o)) { + var a = arguments, + i = a.length; + while(i--) { + me.events[a[i]] = me.events[a[i]] || TRUE; } - }, - -
/** - * Resume firing events. (see {@link #suspendEvents}) - * If events were suspended using the queueSuspended parameter, then all - * events fired during event suspension will be sent to any listeners now. - */ - resumeEvents : function(){ - var me = this; - me.eventsSuspended = !delete me.suspendedEventQueue; - EACH(me.suspendedEventsQueue, function(e) { - me.fireEvent.apply(me, e); - }); + } else { + Ext.applyIf(me.events, o); } + }, + +
/** + * Checks to see if this object has any listeners for a specified event + * @param {String} eventName The name of the event to check for + * @return {Boolean} True if the event is being listened for, else false + */ + hasListener : function(eventName){ + var e = this.events[eventName]; + return ISOBJECT(e) && e.listeners.length > 0; + }, + +
/** + * Suspend the firing of all events. (see {@link #resumeEvents}) + * @param {Boolean} queueSuspended Pass as true to queue up suspended events to be fired + * after the {@link #resumeEvents} call instead of discarding all suspended events; + */ + suspendEvents : function(queueSuspended){ + this.eventsSuspended = TRUE; + if(queueSuspended && !this.eventQueue){ + this.eventQueue = []; + } + }, + +
/** + * Resume firing events. (see {@link #suspendEvents}) + * If events were suspended using the queueSuspended parameter, then all + * events fired during event suspension will be sent to any listeners now. + */ + resumeEvents : function(){ + var me = this, + queued = me.eventQueue || []; + me.eventsSuspended = FALSE; + delete me.eventQueue; + EACH(queued, function(e) { + me.fireEvent.apply(me, e); + }); } -}(); +}; var OBSERVABLE = EXTUTIL.Observable.prototype;
/** @@ -365,26 +373,28 @@ function createTargeted(h, o, scope){ }; }; -function createBuffered(h, o, scope){ - var task = new EXTUTIL.DelayedTask(); +function createBuffered(h, o, l, scope){ + l.task = new EXTUTIL.DelayedTask(); return function(){ - task.delay(o.buffer, h, scope, TOARRAY(arguments)); + l.task.delay(o.buffer, h, scope, TOARRAY(arguments)); }; -} +}; function createSingle(h, e, fn, scope){ return function(){ e.removeListener(fn, scope); return h.apply(scope, arguments); }; -} +}; -function createDelayed(h, o, scope){ +function createDelayed(h, o, l, scope){ return function(){ - var args = TOARRAY(arguments); - (function(){ - h.apply(scope, args); - }).defer(o.delay || 10); + var task = new EXTUTIL.DelayedTask(); + if(!l.tasks) { + l.tasks = []; + } + l.tasks.push(task); + task.delay(o.delay || 10, h, scope, TOARRAY(arguments)); }; }; @@ -419,29 +429,33 @@ EXTUTIL.Event.prototype = { h = createTargeted(h, o, scope); } if(o.delay){ - h = createDelayed(h, o, scope); + h = createDelayed(h, o, l, scope); } if(o.single){ h = createSingle(h, this, fn, scope); } if(o.buffer){ - h = createBuffered(h, o, scope); + h = createBuffered(h, o, l, scope); } l.fireFn = h; return l; }, findListener : function(fn, scope){ - var s, ret = -1; - EACH(this.listeners, function(l, i) { - s = l.scope; - if(l.fn == fn && (s == scope || s == this.obj)){ - ret = i; - return FALSE; + var list = this.listeners, + i = list.length, + l, + s; + while(i--) { + l = list[i]; + if(l) { + s = l.scope; + if(l.fn == fn && (s == scope || s == this.obj)){ + return i; + } } - }, - this); - return ret; + } + return -1; }, isListening : function(fn, scope){ @@ -450,35 +464,61 @@ EXTUTIL.Event.prototype = { removeListener : function(fn, scope){ var index, + l, + k, me = this, ret = FALSE; if((index = me.findListener(fn, scope)) != -1){ if (me.firing) { me.listeners = me.listeners.slice(0); } + l = me.listeners[index]; + if(l.task) { + l.task.cancel(); + delete l.task; + } + k = l.tasks && l.tasks.length; + if(k) { + while(k--) { + l.tasks[k].cancel(); + } + delete l.tasks; + } me.listeners.splice(index, 1); ret = TRUE; } return ret; }, + // Iterate to stop any buffered/delayed events clearListeners : function(){ - this.listeners = []; + var me = this, + l = me.listeners, + i = l.length; + while(i--) { + me.removeListener(l[i].fn, l[i].scope); + } }, fire : function(){ var me = this, args = TOARRAY(arguments), - ret = TRUE; + listeners = me.listeners, + len = listeners.length, + i = 0, + l; - EACH(me.listeners, function(l) { + if(len > 0){ me.firing = TRUE; - if (l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) { - return ret = me.firing = FALSE; + for (; i < len; i++) { + l = listeners[i]; + if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) { + return (me.firing = FALSE); + } } - }); + } me.firing = FALSE; - return ret; + return TRUE; } }; })();