Observable-more.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:8k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!  * Ext JS Library 3.1.0  * Copyright(c) 2006-2009 Ext JS, LLC  * licensing@extjs.com  * http://www.extjs.com/license  */ /**
  2.  * @class Ext.util.Observable
  3.  */
  4. Ext.apply(Ext.util.Observable.prototype, function(){
  5.     // this is considered experimental (along with beforeMethod, afterMethod, removeMethodListener?)
  6.     // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
  7.     // private
  8.     function getMethodEvent(method){
  9.         var e = (this.methodEvents = this.methodEvents ||
  10.         {})[method], returnValue, v, cancel, obj = this;
  11.         if (!e) {
  12.             this.methodEvents[method] = e = {};
  13.             e.originalFn = this[method];
  14.             e.methodName = method;
  15.             e.before = [];
  16.             e.after = [];
  17.             var makeCall = function(fn, scope, args){
  18.                 if (!Ext.isEmpty(v = fn.apply(scope || obj, args))) {
  19.                     if (Ext.isObject(v)) {
  20.                         returnValue = !Ext.isEmpty(v.returnValue) ? v.returnValue : v;
  21.                         cancel = !!v.cancel;
  22.                     }
  23.                     else
  24.                         if (v === false) {
  25.                             cancel = true;
  26.                         }
  27.                         else {
  28.                             returnValue = v;
  29.                         }
  30.                 }
  31.             };
  32.             this[method] = function(){
  33.                 var args = Ext.toArray(arguments);
  34.                 returnValue = v = undefined;
  35.                 cancel = false;
  36.                 Ext.each(e.before, function(b){
  37.                     makeCall(b.fn, b.scope, args);
  38.                     if (cancel) {
  39.                         return returnValue;
  40.                     }
  41.                 });
  42.                 if (!Ext.isEmpty(v = e.originalFn.apply(obj, args))) {
  43.                     returnValue = v;
  44.                 }
  45.                 Ext.each(e.after, function(a){
  46.                     makeCall(a.fn, a.scope, args);
  47.                     if (cancel) {
  48.                         return returnValue;
  49.                     }
  50.                 });
  51.                 return returnValue;
  52.             };
  53.         }
  54.         return e;
  55.     }
  56.     return {
  57.         // these are considered experimental
  58.         // allows for easier interceptor and sequences, including cancelling and overwriting the return value of the call
  59.         // adds an 'interceptor' called before the original method
  60.         beforeMethod : function(method, fn, scope){
  61.             getMethodEvent.call(this, method).before.push({
  62.                 fn: fn,
  63.                 scope: scope
  64.             });
  65.         },
  66.         // adds a 'sequence' called after the original method
  67.         afterMethod : function(method, fn, scope){
  68.             getMethodEvent.call(this, method).after.push({
  69.                 fn: fn,
  70.                 scope: scope
  71.             });
  72.         },
  73.         removeMethodListener: function(method, fn, scope){
  74.             var e = getMethodEvent.call(this, method), found = false;
  75.             Ext.each(e.before, function(b, i, arr){
  76.                 if (b.fn == fn && b.scope == scope) {
  77.                     arr.splice(i, 1);
  78.                     found = true;
  79.                     return false;
  80.                 }
  81.             });
  82.             if (!found) {
  83.                 Ext.each(e.after, function(a, i, arr){
  84.                     if (a.fn == fn && a.scope == scope) {
  85.                         arr.splice(i, 1);
  86.                         return false;
  87.                     }
  88.                 });
  89.             }
  90.         },
  91.         /**
  92.          * Relays selected events from the specified Observable as if the events were fired by <tt><b>this</b></tt>.
  93.          * @param {Object} o The Observable whose events this object is to relay.
  94.          * @param {Array} events Array of event names to relay.
  95.          */
  96.         relayEvents : function(o, events){
  97.             var me = this;
  98.             function createHandler(ename){
  99.                 return function(){
  100.                     return me.fireEvent.apply(me, [ename].concat(Ext.toArray(arguments)));
  101.                 };
  102.             }
  103.             Ext.each(events, function(ename){
  104.                 me.events[ename] = me.events[ename] || true;
  105.                 o.on(ename, createHandler(ename), me);
  106.             });
  107.         },
  108.         /**
  109.          * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling
  110.          * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>
  111.          * <p>This is commonly used by Ext.Components to bubble events to owner Containers. See {@link Ext.Component.getBubbleTarget}. The default
  112.          * implementation in Ext.Component returns the Component's immediate owner. But if a known target is required, this can be overridden to
  113.          * access the required target more quickly.</p>
  114.          * <p>Example:</p><pre><code>
  115. Ext.override(Ext.form.Field, {
  116.     //  Add functionality to Field&#39;s initComponent to enable the change event to bubble
  117.     initComponent : Ext.form.Field.prototype.initComponent.createSequence(function() {
  118.         this.enableBubble('change');
  119.     }),
  120.     //  We know that we want Field&#39;s events to bubble directly to the FormPanel.
  121.     getBubbleTarget : function() {
  122.         if (!this.formPanel) {
  123.             this.formPanel = this.findParentByType('form');
  124.         }
  125.         return this.formPanel;
  126.     }
  127. });
  128. var myForm = new Ext.formPanel({
  129.     title: 'User Details',
  130.     items: [{
  131.         ...
  132.     }],
  133.     listeners: {
  134.         change: function() {
  135.             // Title goes red if form has been modified.
  136.             myForm.header.setStyle('color', 'red');
  137.         }
  138.     }
  139. });
  140. </code></pre>
  141.          * @param {String/Array} events The event name to bubble, or an Array of event names.
  142.          */
  143.         enableBubble : function(events){
  144.             var me = this;
  145.             if(!Ext.isEmpty(events)){
  146.                 events = Ext.isArray(events) ? events : Ext.toArray(arguments);
  147.                 Ext.each(events, function(ename){
  148.                     ename = ename.toLowerCase();
  149.                     var ce = me.events[ename] || true;
  150.                     if (Ext.isBoolean(ce)) {
  151.                         ce = new Ext.util.Event(me, ename);
  152.                         me.events[ename] = ce;
  153.                     }
  154.                     ce.bubble = true;
  155.                 });
  156.             }
  157.         }
  158.     };
  159. }());
  160. /**
  161.  * Starts capture on the specified Observable. All events will be passed
  162.  * to the supplied function with the event name + standard signature of the event
  163.  * <b>before</b> the event is fired. If the supplied function returns false,
  164.  * the event will not fire.
  165.  * @param {Observable} o The Observable to capture events from.
  166.  * @param {Function} fn The function to call when an event is fired.
  167.  * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Observable firing the event.
  168.  * @static
  169.  */
  170. Ext.util.Observable.capture = function(o, fn, scope){
  171.     o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
  172. };
  173. /**
  174.  * Sets observability on the passed class constructor.<p>
  175.  * <p>This makes any event fired on any instance of the passed class also fire a single event through
  176.  * the <i>class</i> allowing for central handling of events on many instances at once.</p>
  177.  * <p>Usage:</p><pre><code>
  178. Ext.util.Observable.observeClass(Ext.data.Connection);
  179. Ext.data.Connection.on('beforerequest', function(con, options) {
  180.     console.log('Ajax request made to ' + options.url);
  181. });</code></pre>
  182.  * @param {Function} c The class constructor to make observable.
  183.  * @param {Object} listeners An object containing a series of listeners to add. See {@link #addListener}. 
  184.  * @static
  185.  */
  186. Ext.util.Observable.observeClass = function(c, listeners){
  187.     if(c){
  188.       if(!c.fireEvent){
  189.           Ext.apply(c, new Ext.util.Observable());
  190.           Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
  191.       }
  192.       if(Ext.isObject(listeners)){
  193.           c.on(listeners);
  194.       }
  195.       return c;
  196.    }
  197. };