dojox/lang/observable.js

  • Provides:

    • dojox.lang.observable
  • dojox.lang.observable

    • type
      Function
    • parameters:
      • wrapped: (typeof Object)
        The object to be wrapped and monitored for property access and modification
      • onRead: (typeof function)
        See dojox.lang.makeObservable.onRead
      • onWrite: (typeof function)
        See dojox.lang.makeObservable.onWrite
      • onInvoke: (typeof function)
        See dojox.lang.makeObservable.onInvoke
    • source: [view]
       return dojox.lang.makeObservable(onRead,onWrite,onInvoke)(wrapped);
    • summary
      Creates a wrapper object, which can be observed. The wrapper object
      is a proxy to the wrapped object. If you will be making multiple wrapper
      objects with the same set of listeners, it is recommended that you
      use makeObservable, as it is more memory efficient.
  • dojox.lang.makeObservable

    • type
      Function
    • parameters:
      • onRead: (typeof function)
        This is called whenever one of the wrapper objects created
        from the constructor has a property that is accessed. onRead
        will be called with two arguments, the first being the wrapped object,
        and the second is the name of property that is being accessed.
        The value that onRead returns will be used as the value returned
        by the property access
      • onWrite: (typeof function)
        This is called whenever one of the wrapper objects created
        from the constructor has a property that is modified. onWrite
        will be called with three arguments, the first being the wrapped object,
        the second is the name of property that is being modified, and the
        third is the value that is being set on the property.
      • onInvoke: (typeof function)
        This is called when a method on the object is invoked. The first
        argument is the wrapper object, the second is the original wrapped object,
        the third is the method name, and the fourth is the arguments.
      • hiddenFunctions: (typeof Object)
        allows you to define functions that should be delegated
        but may not be enumerable on the wrapped objects, so they must be
        explicitly included
    • source: [view]
       hiddenFunctions = hiddenFunctions || {};
       onInvoke = onInvoke || function(scope,obj,method,args){
        // default implementation for onInvoke, just passes the call through
        return obj[method].apply(scope,args);
       };
       function makeInvoker(scope,wrapped,i){
        return function(){
         // this is function used for all methods in the wrapper object
         return onInvoke(scope,wrapped,i,arguments);
        };
       }

       
       if(dojox.lang.lettableWin){ // create the vb class
        var factory = dojox.lang.makeObservable;
        factory.inc = (factory.inc || 0) + 1;
        // create globals for the getters and setters so they can be accessed from the vbscript
        var getName = "gettable_"+factory.inc;
        dojox.lang.lettableWin[getName] = onRead;
        var setName = "settable_"+factory.inc;
        dojox.lang.lettableWin[setName] = onWrite;
        var cache = {};
        return function(wrapped){
         if(wrapped.__observable){ // if it already has an observable, use that
          return wrapped.__observable;
         }
         if(wrapped.data__){
          throw new Error("Can wrap an object that is already wrapped");
         }
         // create the class
         var props = [], i, l;
         for(i in hiddenFunctions){
          props.push(i);
         }
         var vbReservedWords = {type:1,event:1};
         // find the unique signature for the class so we can reuse it if possible
         for(i in wrapped){
          if(i.match(/^[a-zA-Z][\w\$_]*$/) && !(i in hiddenFunctions) && !(i in vbReservedWords)){ //can only do properties with valid vb names/tokens and primitive values
           props.push(i);
          }
         }
         var signature = props.join(",");
         var prop,clazz = cache[signature];
         if(!clazz){
          var tname = "dj_lettable_"+(factory.inc++);
          var gtname = tname+"_dj_getter";
          var cParts = [
           "Class "+tname,
           " Public data__" // this our reference to the original object
          ];
          for(i=0, l=props.length; i     prop = props[i];
           var type = typeof wrapped[prop];
           if(type == 'function' || hiddenFunctions[prop]){ // functions must go in regular properties for delegation:/
            cParts.push(" Public " + prop);
           }else if(type != 'object'){ // the getters/setters can only be applied to primitives
            cParts.push(
             " Public Property Let "+prop+"(val)",
             "  Call "+setName+"(me.data__,\""+prop+"\",val)",
             " End Property",
             " Public Property Get "+prop,
             "  "+prop+" = "+getName+"(me.data__,\""+prop+"\")",
             " End Property");
           }
          }
          cParts.push("End Class");
          cParts.push(
           "Function "+gtname+"()",
           " Dim tmp",
           " Set tmp = New "+tname,
           " Set "+gtname+" = tmp",
           "End Function");
          dojox.lang.lettableWin.vbEval(cParts.join("\n"));

           
          // Put the new class in the cache
          cache[signature] = clazz = function(){
           return dojox.lang.lettableWin.construct(gtname); // the class can't be accessed, only called, so we have to wrap it with a function
          };
         }
         console.log("starting5");
         var newObj = clazz();
         newObj.data__ = wrapped;
         console.log("starting6");
         try {
          wrapped.__observable = newObj;
         } catch(e){ // some objects are not expando
         }
         for(i = 0, l = props.length; i < l; i++){
          prop = props[i];
          try {
          var val = wrapped[prop];
          }
          catch(e){
           console.log("error ",prop,e);
          }
          if(typeof val == 'function' || hiddenFunctions[prop]){ // we can make a delegate function here
           newObj[prop] = makeInvoker(newObj,wrapped,prop);
          }
         }
         return newObj;
        };
       }else{
        return function(wrapped){ // do it with getters and setters
         if(wrapped.__observable){ // if it already has an observable, use that
          return wrapped.__observable;
         }
         var newObj = wrapped instanceof Array ? [] : {};
         newObj.data__ = wrapped;
         for(var i in wrapped){
          if(i.charAt(0) != '_'){
           if(typeof wrapped[i] == 'function'){
            newObj[i] = makeInvoker(newObj,wrapped,i); // TODO: setup getters and setters so we can detect when this changes
           }else if(typeof wrapped[i] != 'object'){
            (function(i){
             newObj.__defineGetter__(i,function(){
              return onRead(wrapped,i);
             });
             newObj.__defineSetter__(i,function(value){
              return onWrite(wrapped,i,value);
             });
            })(i);
           }
          }
         }
         for(i in hiddenFunctions){
          newObj[i] = makeInvoker(newObj,wrapped,i);
         }
         wrapped.__observable = newObj;
         return newObj;
        };
       }
    • summary
      Creates and returns an observable creator function. All the objects that
      are created with the returned constructor will use the provided onRead and
      onWrite listeners.
      The created constructor should be called with a single argument,
      the object that will be wrapped to be observed. The constructor will
      return the wrapper object.
    • returns
      the class can't be accessed, only called, so we have to wrap it with a function|do it with getters and setters
    • example
      The following could be used to create a wrapper that would
      prevent functions from being accessed on an object:
      
      	function onRead(obj,prop){
      		return typeof obj[prop] == 'function' ? null : obj[prop];
      	}
      	var observable = dojox.lang.makeObservable(onRead,onWrite);
      	var obj = {foo:1,bar:function(){}};
      	obj = observable(obj);
      	obj.foo -> 1
      	obj.bar -> null
  • frame

    • summary
  • frame.style.display

    • summary
  • doc

    • summary
  • dojox.lang.lettableWin

    • summary
  • dojox.lang.ReadOnlyProxy

    • summary
  • dojox.lang

    • type
      Object
    • summary
  • dojox

    • type
      Object
    • summary