Archetype.engine

Archetype Engine Abstraction Layer

Archetype needs a base library (or a set of base libraries) to work on, and we call this library: Archetype?s engine. Archetype provide an abstraction layer between Archetype?s core and the engine used. With it, we can write a wrapper to any JavaScript library which implements the required functionalities

To work with this abstraction layer, we had to define an abstract engine API in order to implement it with wrapper on each engine (today Prototype and jQuery). As Archetype started only on top of Prototype, this abstraction layer is very close to Prototype's API but not exactly the same and very smaller.

As somes methods are directly mapped on Prototype's ones, you will see lots of paraphrasing with Prototype's documentation.

There are three kinds of mapping we describe in detail in this page:

  • DOM element selector : JavaScript library used DOM element selectors, we choose $$ as abstract function to be able to use it with all engines.
  • JavaScript objects extensions : symbolized with "$" functions used to extend standard objects ($E for DOM elements, $A for Arrays, $H for HashMaps)
  • Archetype.engine methods : high level methods needed by Archetype, currently it used for Ajax requests and events.

You can find the abstract engine definition in the framework files in Archetype/engine/abstractEngine.js

DOM element selector

DOM selection is the core features of JavaScript libraries for working with the page. All works approximatly the same way: a CSS selection notation which return a list of extended DOM elements. Archetype just wrap this features behind the $$ function:

			
$$("div.myClass #myId span")
//-> return an array of DOM elements which match CSS selector "div.myClass #myId span"
			

You can find more details on Prototype's an jQuery's documentations: Prototype's $$ function definition and jQuery's Selectors specifications .

Object extensions: $E for DOM elements

First extension used is for DOM elements. It's base of most JavaScript library. It's not strongly used by the Archetype's core which don't modify document body (only the head) but it's used by components, specially by the graphical components features.

			
/*DOM element example:*/ var myDomElement = document.body;
$E(myDomElement); //-> myDomElementExtended
			

Extend the dom element add this methods:

  • setStyle(/*HashMap{String,String}*/ styles) : Set styles defined in the HashMap (key for the property name, value for the property value) to the element.
  • update(/*String*/ content) : Update element content (innerHTML) with the parameter.
  • observe(/*String*/ eventType, /*function*/ callback) : listen the eventType event on the element and fire callback when occured.
  • stopObserving(/*String*/ eventType, /*function*/ callback) : stop listening eventType event on the element with this callback (beware of the strict equality to match callbacks).

We wrap DOM element extension of each library we used as engine. The list above is methods for which we check compatibility and syntax with all engines but if you have chosen your engine, you can use all other methods that the engine you use offer.

One simple example to illustrate DOM elements extension:

			
/*DOM element example:*/ var myDomElement = document.body;
var myDomElementExtended = $E(myDomElement);
myDomElementExtended.update("Hello World"); //replace body content with "Hello World"
myDomElementExtended.setStyle({ //set style of the body
	color: "red",
	background-color: "blue"
});
			

Object extensions: $A for Arrays

We works a lot with large set of useful methods for enumerations originated from Prototype (implemented by jQuery enumerable plugin for the jQuery wrapper). So we add them in our Arrays extension:

  • each(/*function*/ iterator) : The iterator function you pass will be called with two parameters: the current element in the iteration, the numerical index, starting at zero.
  • collect(/*function*/ iterator) : Returns the results of applying the iterator to each element.
  • findAll(/*function*/ iterator) : Returns all the elements for which the iterator returned true.
  • include(/*Object*/ object) : Determines whether a given object is in the Array or not.
  • invoke(/*function*/ methodName, [, /*Object*/ arg...]) : Invokes the same method, with the same arguments, for all items in a collection. Returns the results of the method calls.
  • reject(/*function*/ iterator) : Returns all the elements for which the iterator returned false.
  • without(/*Object*/ value...) : Produces a new version of the array that does not contain any of the specified values.
			
/*Array example:*/ var myArray = ["foo", "bar"];
var myArrayExtended = $A(myArray);
myArrayExtended.include("foo"); //-> true
myArrayExtended.include("fooo"); //-> false
myArrayExtended.collect(function(element) {
	return element + "toto";
}); //-> $A(["foototo", "bartoto"])
			

Object extensions: $H for HashMaps

HashMap can be thought of as an associative array, binding unique keys to values. There is no guarantee on a consistent order its of elements when iterating. Because of the nature of JavaScript programming language, every object is in fact a hash

beware : As for Prototype 1.6, extended HashMap is not usable by the simple accessor to a property:

			
/*HashMap example:*/ var myHashMap = {key1: "foo", key2: "bar"};
var myExtendedHashMap = $H(myHashMap);
myHashMap.key1; //-> "foo"
myHashMap["key1"]; //-> "foo"
myExtendedHashMap.key1; //-> undefined
myExtendedHashMap["key1"]; //-> undefined
myExtendedHashMap.get("key1"); //-> "foo"

//setters works the same way:
myExtendedHashMap.key1 = "toto"; //-> is useless (but generate any error)
myExtendedHashMap.set("key1", "toto"); //-> is the right syntax
			

The HashMap extension implements all these methods:

  • each(/*function*/ iterator) : The iterator function you pass will be called with two parameters: the current pair in the iteration (a pair is a simple HashMap with keys "key" and "value"), the numerical index, starting at zero.
  • set(/*String*/ key, /*Object*/ value) : Sets the HashMap?s key property to value and returns value.
  • get(/*String*/ key) : Returns the value of the HashMap?s key property.
  • keys() : Provides an Array of keys for the HashMap.
  • values() : Collect the values of the HashMap and returns them in an Array.
  • clone() : Returns a clone of HashMap.
  • merge(/*HashMap*/ otherHashMap) : Merges otherHashMap to HashMap and returns the result of that merge.
  • toObject() : Returns a cloned, vanilla object..
  • update(/*HashMaps*/ addition) : Adds addition's keys in the original HashMap. The original HashMap will be modified.
			
/*HashMap example:*/ var myHashMap = {key1: "foo", key2: "bar"};
var myExtendedHashMap = $H(myHashMap);
myArrayExtended.get("key1"); //-> "foo"
myArrayExtended.set("key1", "toto");
myArrayExtended.keys(); //-> $A(["key1", "key2"])
myArrayExtended.merge({key3: "foobar"}); //-> $H({key1: "toto", key2: "bar", key3: "foobar"})
			

Archetype.engine methods

Some high level methods are referenced in the Archetype.engine HashMap:

  • fire(/*String*/ type, /*Object*/ data) : Fire a global type event with data in parameter.
  • observe(/*String*/ type, /*function*/ callback) : Listen global type event and launch callback when occured.
  • stopObserving(/*String*/ type, /*Function*/ callback) : Stop listening global type event with callback.
  • ajax(/*String*/ url, /*boolean*/ asynchronous, /*function*/ success, /*function*/ error) : Launch an Ajax request on url in asynchronous mode. Success callback is used (with response content in parameter) if request succed and error callback if request failed.