CBE Core Object Model | Cross-Browser.com

# CBE Core Object Model ## Implementing W3C DOM2 Interfaces ### The Idea When I started working on the second version of CBE, I began to rethink the interface. By that I mean the names of the functions and objects, and how they relate to each other. Most of the other API's I studied had proprietary interfaces. They had function names like getX(), setX(), etc. There's nothing wrong with this type of interface - in fact I really liked it. So I began to think about what to name my functions, but I didn't want to use the names someone else had already used. Well... I'm not really good at coming up with cool names ;) During this time, I was studying the W3C recommendations. I suddenly realized - all the names were there, already created for me! And not only that, but they provided a complete object model specification. I then decided that, somehow, my API should not only use the names from the W3C recommendations, but attempt also to actually implement their object model interfaces in cross-browser Javascript. CBE 4 is a partial implementation of some of the W3C DOM2 interfaces. This document discusses the CBE core object model. The CBE event model is discussed in another document. ### The Implementation Object The following is a very simple example of programming DHTML in a DOM1 environment. Listing 1
    window.onload = function() {
      var e1 = document.getElementById('E1');
      e1.style.left = 100 + 'px';
      e1.style.top = 100 + 'px';
      e1.style.visibility = 'visible';
    }
Now look at the following which uses CBE. It accomplishes the same task - positions an element at the point (100,100) and makes it visible. But this will work the same in all the different browsers CBE supports. And that's the whole purpose of CBE - to provide a programming interface as close as possible to the standard, while providing consistent, cross-browser semantics and rendering. Listing 2
    function windowOnload() {
      var e1 = document.getElementById('E1');
      e1.cbe.left(100);
      e1.cbe.top(100);
      e1.cbe.visibility('visible');
    }
I'm sure you see the differences between the two code listings. The window.onload Event Listing 1 directly hooks the window.onload event to initialize it's positioned element on the page. Listing 2 defines a function named windowOnload() to accomplish the same purpose. The actual window.onload event is hooked by the CBE system itself, and creates the CBE object model - then it calls windowOnload(). The CSSP Object In Listing 1 the CSSP object is named style. With CBE it is named cbe. Because CBE uses so many standard names, it must keep them within their own scope. Properties v/s Methods Listing 1 reads and writes properties of the CSSP object. With CBE you call methods of the CSSP object. Browser differences are rectified within the methods. Specifying Units In listing 1 you must specify the units. In CBE all numeric units are Pixels. CBE provides some shortcut methods. The following accomplishes the same as Listings 1 and 2, but is written the way I would normally program with CBE. Listing 3
    function windowOnload() {
      var e1 = cbeGetElementById('E1').cbe;
      e1.moveTo(100,100);
      e1.show();
    }
### CrossBrowserElement The CrossBrowserElement object is a partial implementation of the DOM2 Element interface. It is a subclass of CrossBrowserNode, and so inherits those properties and methods. CrossBrowserElement objects populate the CBE Object Tree. A CrossBrowserElement object is created for each DIV or SPAN with id!="" and added to it's associated Element object as a property named cbe. The window.onload event is received by a function in cbe_core.js. It calls the function cbeInitialize(), which creates the CBE object model. Consider the following HTML.
    <div id='E1' class='clsCBE'>This is e1</div>
Now notice the difference between accessing the native Element object and the CrossBrowserElement object, and then compare this with listing 3. Listing 4
    function windowOnload() {
      // ne is a reference to the native Element object
      var ne = document.getElementById('E1');
      /*
        e is a reference to the CrossBrowserElement object
        associated with the native Element object whose id is 'E1'
      */
      var e = ne.cbe;
      e.moveTo(100,100);
      e.show();
    }
### The CBE Object Tree The function cbeInitialize() connects all the CrossBrowserElement objects into a tree structure using property names from the DOM2 Node interface. This tree structure models the parent/child (nesting) relationships among the CrossBrowserElement objects. When cbeInitialize() has finished creating the object model, it calls windowOnload(), if you have defined it. The window.onunload event is also received by a CBE function. It first calls windowOnunload(), if you have defined it, then nulls the cbe property of each positioned Element. The following illustrates the tree structure that is created for the HTML in listing 5. Notice that there are two additional CrossBrowserElement objects in the tree. One is associated with the native window object, and the other is associated with the native document object. Their respective id's are the values of the variables window.idWindow and window.idDocument.
Listing 5
    <div id='P1' class='clsCBE'>

        <div id='P1C1' class='clsCBE'> </div>

        <div id='P1C2' class='clsCBE'> </div>

    </div>

    <div id='P2' class='clsCBE'>

        <div id='P2C1' class='clsCBE'> </div>

        <div id='P2C2' class='clsCBE'> </div>

    </div>
There are common terms used to describe the relationships between objects in a tree structure. In the descriptions below I'll refer to the tree built from listing 5. node - Each individual item in the tree. root - The first node of the tree. window.cbe is the root node of the CBE object tree. parent - The node one level up. P1 is the parent of P1C1 and P1C2. child - The node one level down. P1C1 and P1C2 are the children of P1. Sibling - Nodes on the same level. P1C1 and P1C2 are siblings (they have the same parent). Ancestor - Any of the nodes as you follow the connections up to the root. document.cbe is not the parent of P1C1, but is it's ancestor. Descendant - Any of the nodes as you follow the connections down. The opposite of ancestor. P1C1 is a descendant of window.cbe. ### CrossBrowserNode The CrossBrowserNode object is a partial implementation of the DOM2 Node interface. It's properties provide for the implementation of the CBE Object Tree. CrossBrowserNode Properties: childNodes firstChild lastChild nextSibling parentNode previousSibling In CBE, childNodes is an integer, and is simply the number of child nodes. The remaining properties point to CrossBrowserElement objects. With the CrossBrowserNode properties you can traverse (walk) the tree, that is, visit (apply a function to) each node in the tree (or sub-tree). I've also provided a function named cbeTraverseTree() which will perform a pre-order traversal of the entire tree (or sub-tree). If you need post-order traversal let me know and I'll provide that function. For the following example, imagine that the nodes P1 and P2 are containers for a dhtml window. Within them may be many different positioned elements, nested at different levels. When the user clicks anywhere within the container we want to raise the container's z-index, to make it come to the top of any other windows. The following function would be useful, and it makes use of the CrossBrowserNode properties and the tree structure. Listing 6
    function getTopContainer(oThis) {
      var ancestor = oThis;
      while (ancestor.id != window.idDocument) {
        ancestor = ancestor.parentNode;
      }
      return ancestor;
    }
### ClientSnifferJr There is one ClientSnifferJr object, named is. It is the client detection object, which is available immediately after cbe_core.js has loaded. With the is object you can determine which browser your page is currently running on. Listing 7
    function windowOnload() {
      var s = "Welcome ";
      if (is.opera) s += "Opera";
      else if (is.gecko) s += "Gecko";
      else if (is.nav) s += "Navigator";
      window.defaultStatus = s + " User!";
    }
See the object reference for a complete list of events, properties and methods for all the objects discussed in this document.