myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Werner Punz <werner.p...@gmail.com>
Subject Ann: MyFaces _Runtime.js and how to use it
Date Fri, 30 Jul 2010 11:48:41 GMT
Ok a third mail finally exposing our internal features.
Short introduction:

By designing our javascripts it was up for discussion whether we should 
use an existing lib or rolling our own. The + side of an existing lib 
would be already existing code, the downside, you drag along a lot of 
code which will never be used.
But on the other hand I did not want the pure lets do only the spec 
approach but I wanted to get something solid a base for other complibs 
also to be used sort of as shared core which easily can be extended and 
merged into existing libraries.

For maintainance reasons I always opted for a pure oo approach (although 
the scripts in 2.0.0 were not entirely there) with a beak binding 
between the layers.

Also I wanted to have a clear boundary between api and impl.

Have in mind I hate reinventing the wheels, so I took the liberty to rip 
out foreign code wherever it suited (we have some dojo code in some 
parts came from j4fry, also some small part is from YUI)
But sometimes it is better to reinvent the wheels a little bit to 
prevent a lot of useless code to be dragged in.

One of the cornerstones of all this which was late introduced was the 
_Runtime.js. The _Runtime.js is a small file which is the base for all
scripts.

It provides following functionality:

Core Patterns:
  Namespaceing
  Inheritance
  Singletons
  Delegation

Dom Core functionality:
  Global Evaluation of scripts
  Dynamic script loading via xhr get
  Dynamic scoping of functions via hitch
  Advanced Exists checking of elements
  Browser Detection


Everything else in our scripts is based upon this functionality.

I will give a few examples:

Namespacing:
var _RT = myfaces._impl.core._Runtime

_RT.reserveNamespace("myfaces.hello.world")

after that a global namespace map under
myfaces.hello.world should be present

_RT.reserveNamespace("myfaces.hello.world", "myhello")

after that a global namespace map under
myfaces.hello.world should be present
with myhello being assigned to it as value


_RT.fetchNamespace("myfaces.hello.world")

resolves the namespace in a speed optimized manner and returns its value

Inheritance:

http://www.pastebin.org/432772


This is an example, the inheritance is pretty much the same as dojo, the 
main differences come later.

One thing, the super call must be performed via
this._callSuper('<functionName>', hello1, hello2);

I might introduce a real inherited without the function name later.
Multiple inheritance is not implemented for now, it was not necessary 
for what we are doing and would have only introduced more code.


Delegation:

myfaces._impl.core._Runtime.singletonDelegateObj("myfaces._impl._util._Lang", 
myfaces._impl.core._Runtime, {
     fetchNamespace : function(namespace) {
         if (!namespace || !this.isString(namespace)) {
             throw Error("_Lang.fetchNamespace namespace must be of type 
String");
         }
         return this._callDelegate("fetchNamespace", namespace);
     },
});

That produces a new singleton which delegates from runtime.
Without producing a singleton you could use following:

Also as you can see the delegation methods are added automatically if 
you want to overwrite a certain behavior then use _callDelegate.
(like it is done here by adding additional type checking)

myfaces._impl.core._Runtime.delegateObj("myfaces._impl._util._Lang", 
myfaces._impl.core._Runtime, {

...
});

Besides that there is some nifty stuff like browser detection
this is straight from dojo with _RT.browser.isIE carrying a number if it 
is IE etc... (you can look up the details in the code)

Hitch also from dojo. With it you can enforce a certain scope on a 
function passed down, no matter what the runtime system downs with the 
function afterwards.

Usage _RT.hitch(newScope, function() { this.hello(); });
this pushes the internal this of the anonymous function to newScope.

A classical addOnLoadWrapper

_RT.addOnLoad(window, function() {alert("loaded");});
_RT.addOnLoad(document.body, function() {alert("loaded");});

etc... pretty self explanatory

loadScript loads and evals a script:

 
myfaces._impl.core._Runtime.loadScript("#{resource['org.apache.myfaces.core.impl.util:_Lang.js']}",

null, null, "UTF-8");

There are other smaller things in there which I have not yet listed, and 
some of the code might change in detail, but not too much anymore, I 
will try to keep the _Runtime from now on as stable as possible, I do 
not want to have too much in there anymore to keep it small.




Werner


Mime
View raw message