From xap-commits-return-292-apmail-incubator-xap-commits-archive=incubator.apache.org@incubator.apache.org Thu Aug 17 18:36:26 2006 Return-Path: Delivered-To: apmail-incubator-xap-commits-archive@locus.apache.org Received: (qmail 37503 invoked from network); 17 Aug 2006 18:36:25 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 17 Aug 2006 18:36:25 -0000 Received: (qmail 52374 invoked by uid 500); 17 Aug 2006 18:36:25 -0000 Delivered-To: apmail-incubator-xap-commits-archive@incubator.apache.org Received: (qmail 52359 invoked by uid 500); 17 Aug 2006 18:36:25 -0000 Mailing-List: contact xap-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: xap-dev@incubator.apache.org Delivered-To: mailing list xap-commits@incubator.apache.org Received: (qmail 52343 invoked by uid 99); 17 Aug 2006 18:36:25 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 17 Aug 2006 11:36:25 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 17 Aug 2006 11:36:24 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 38BAB1A981D; Thu, 17 Aug 2006 11:36:04 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r432327 - /incubator/xap/trunk/src/xap/bridges/basic/AbstractBlackBoxWidgetBridge.js Date: Thu, 17 Aug 2006 18:36:03 -0000 To: xap-commits@incubator.apache.org From: mturyn@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060817183604.38BAB1A981D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: mturyn Date: Thu Aug 17 11:36:03 2006 New Revision: 432327 URL: http://svn.apache.org/viewvc?rev=432327&view=rev Log: Improved the jsdoc. Modified: incubator/xap/trunk/src/xap/bridges/basic/AbstractBlackBoxWidgetBridge.js Modified: incubator/xap/trunk/src/xap/bridges/basic/AbstractBlackBoxWidgetBridge.js URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/xap/bridges/basic/AbstractBlackBoxWidgetBridge.js?rev=432327&r1=432326&r2=432327&view=diff ============================================================================== --- incubator/xap/trunk/src/xap/bridges/basic/AbstractBlackBoxWidgetBridge.js (original) +++ incubator/xap/trunk/src/xap/bridges/basic/AbstractBlackBoxWidgetBridge.js Thu Aug 17 11:36:03 2006 @@ -16,33 +16,51 @@ */ Xap.provide("xap.bridges.basic.AbstractBlackBoxWidgetBridge"); -// Auto-added---o.k.? -Xap.require("xap.util.Utils"); -// Auto-added---o.k.? +Xap.require("xap.util.Utils"); Xap.require("xap.util.Exception"); - Xap.require("xap.util.LogFactory") ; Xap.require("xap.taghandling.AbstractTagImpl") ; - /** - * @fileoverview +/** + * @fileoverview * - * A superclass for the bridges controlling a widget peer obeying a limited interface; treat it - * as an abstract superclass (note that it doesn't implement a couple of methods it requires). - */ + * + * A class of intended as an abstract superclass for other bridges. +**/ + + + + /* + * TO_DO: 1.) Find better names for the methods that return DOM nodes (to be used as parents and children), will + * need to create one (am currently using getDisplayDomNode() for parent and container, a bad idea.) + *.2.) Rename private methods with leading underscores "_". + * 3.) Maybe find a better name for this class; the "BlackBox" is there to make a point about avoiding + * making direct calls to peer methods from the bridge, but having been made it might be a bit much. +*/ /** * Creates a xap.bridges.basic.AbstractBlackBoxWidgetBridge. * - * - * @class xap.bridges.basic.AbstractBlackBoxWidgetBridge is the bridge between an XML element - * representing a control and a subclass of AbstractBlackBoxWidget. This class - * is typically not used directly but is extended by other classes - * for its subclasses. + * A subclass of xap.taghandling.AbstractTagImpl + * intended as an abstract superclass for the + * other bridges.  The goal was to create a class that maps out the + * behaviors needed by all bridges without fixing them in stone; to that + * end there are many calls to methods which are either not implemented + * here at all, or are implemented with lowest common denominator + * behaviors that might well need overriding or supplementing in + * subclasses. It is hoped (and in the case of Dojo, known) that + * a similar abstract class can implement toolkit-specific behaviors + * that will allow the actual widget bridges themselves to be relatively lightweight. + *
+ * + * @constructor * * @author mturyn + * @see xap.taghandling.AbstractTagImpl + * @see xap.session.ClientSession#createInitialDocument + * @see xap.bridges.dojo.DojoWidgetBridge */ xap.bridges.basic.AbstractBlackBoxWidgetBridge = function() { xap.taghandling.AbstractTagImpl.call( this ); @@ -57,10 +75,18 @@ /** * All bridges to should go through these steps: - * - * 1: Create or obtain the peer object - * 2: Handle all the initial attributes - * 3: Recursively parse the inititial children + *
    + *
  1. : Create or obtain the peer object + *
  2. : Handle all the initial attributes + *
  3. : Recursively parse the inititial children + *
+* Here we look at the layout rectangle (if any) as defined by the XAL-spec'd {x,y,width,height} + * parameters, and add this information to this._creationProperties + * for the subclasses to do with as they will.  Then createPeer + * (see below) and attribute- and children-parsing routines called, but + * these latter two shouldn't need to be + * changed from their implementations in xap.taghandling.AbstractTagImpl. + * @see xap.session.ClientSession#_createInitialDocument * **/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.init = function() { @@ -90,20 +116,118 @@ } } +/** + * @private + * @static + * Reserved word that will equal the result of applying the typeof operator + * on a function object. +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.FUNCTION="function" ; +/** + * @private + * @static + * String marking the beginning of an event method---not perfect, but a 90/10 rule applies. +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.ON="on" ; +/** + * @static + * Determines if an object, typically a member on another object, is a function. +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.s_IsFunction = function(aMember){ var typ = typeof aMember ; var eqq = (typ== xap.bridges.basic.AbstractBlackBoxWidgetBridge.FUNCTION) ; return eqq ; } - +/** + * @private + * @static + * List of the names of methods any bridge in this class' subtree should have. +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.interfaceMethods = - {obtainPeer:null,attributeSet:null,getEventTriggers:null,getDisplayDomNode:null,getRootDomNode:null} ; + {obtainPeer:null,attributeSet:null,findPeerEvents:null,getDisplayDomNode:null,getRootDomNode:null} ; +/** + * Actually now more like processPeer, since it now + * calls obtainPeer to create or find our underlying widget. +*
    + *
  1. Peer acquisition and layout: The core of + * the + * class is in the (now a bit archaicly named) createPeer(). + *
      + *
    1. It finds a peer using the method obtainPeer, + * whose implementation is left up to the implementing subclass.
      + *
    2. + *
    3. This tag's + * parent's handler is queried for an HTML DOM node within which to place + * a node provided by this bridge (example: the parent wrappers a + * SplitPane, this bridge controls a button:  the parent provides the + * pane's "container" node where children will be inserted, and this + * bridge provides a node containing the whole button).
      + *
    4. + * + *
        + * (Note that the + * bridge will only get as much information as it needs from another + * bridge, an HTMLElement---it doesn't need to know anything + * else about + * the parent bridge's peer, and in fact might well not know how to get + * a suitable HTML DOM node from that peer, which might be from whatever + * vendor or an HTML DOM + * node itself. + *
      + *
    5. Alternately, a locator attribute in the XAL is queried + * via getSpecifiedDisplayNode(), + * and that i.d. used to + * find + * the parent node.
    6. + *
    + *
  2. + *
  3. Event handling: The goal + * is to attach one of our events to each of the peer's events. To do this + * by default we indulge in reflection, looking for function members of + * the peer with names of the form "onXXX" + * and creating our own that just call fireEvent("onXXX"), + * if it does not already exist---this means + * that subclasses that already implement an onFoo will not + * have it supplanted by one of these auto-generated ones. + * Admittedly, this could fail or produce extraneous events (what if the + * peer had a method oneInstance?); + * but if this should be a problem for the subclass's peer, the subclass + * can override this. Each of our events is connected + * to its equivalent on the peer using dojo.event.connect. + * Finally, our own _onCommandEvent call is connected to + * whichever event the bridge class specifies + * with getOnCommandEvent, so a button can ask that onClick + * get this + * attention, but a calendar onSetDate.
  4. + *
  5. Glue and upgrading:  + * Finally, the + * peer is fixed to this bridge using setPeer, + * which both sets the _peer member and (in the superclass) + * records this bridge as its peer's handler, which can be used later on + * to look this bridge up by its peer (e.g., if we interact with a widget, + * we can see if it's one of the + * ones we're managing, and if so we then can probably do more things with + * it than otherwise.  In subclasses, this is also the point at which + * extra methods may be attached to the peer to make it easier for the + * handler to deal with it.
    + *
  6. + *
  7. Attribute handling:  + * When a XAL attribute is processed, it triggers a call to attributeSet(); + * here lowest-common-denominator behavior dominates----for an attribute bar, + * we look for a setter setFoo on the peer, and if it + * exists call it.  In the case of the namespace attribute xmlns + * and the event call onCommand() we do something + * smarter---apart from these exceptions, anything more interesting and + * widget-specific will have to be handled in subclasses.
    + *
  8. + *
+ * @throws xap.util.Exception if the peer is unobtainable, or if the bridge subclass + * is missing, or if the supposed parent XapElement or bridge is not one of those. +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.createPeer = function() { // Implemented by subclasses---here, we don't care how they get it: with a simple // constructor, via a database call, using a JSON-encoded object over the fibre, @@ -142,17 +266,10 @@ xap.bridges.basic.AbstractBlackBoxWidgetBridge.s_log.error("Bogus parent peer:" + parentPeer ); } else { - // The candy in the middle of the wrapper: - - // is this subclass instance "this" an appropriate bridge---does it fit our "interface"?: - // A bit of contractual programming---make sure this is a bridge of the sort we can use: - if(!this._peer){ throw new xap.util.Exception("Haven't obtained a source object to manage.") ; } - - for( var meth in xap.bridges.basic.AbstractBlackBoxWidgetBridge.interfaceMethods){ if(!this[meth] ){ throw new xap.util.Exception("Supposed bridge object does not have member \""+ meth+"\".") ; @@ -162,34 +279,49 @@ } } + // Connects (and if necessary, creates) the bridge events mirroring the peer's. this.autoAttachBridgeEventsToPeerEvents() ; + // Finds and sets the peer's location in the HTML DOM: this.setHtmlDomLocation(parentPeerDomNode) ; - - } } - //Default behaviour: +/** + * Default behaviour: is that the node used to attach this widget as a child of another one + * or of a DOM node is the same one that should be used as a container for child nodes or + * widgets. Lowest common denominator. + **/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.getDisplayDomNode = function(){ - return this.getRootDomNode() ; + return this.getRootDomNode() ; } - - +/** + * @private + * A wrapper for firing an onCommand event, here so that we can hook that + * up to the peer event specified by getPeerOnCommandEvent q.v.. + * @see getPeerOnCommandEvent +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype._onCommandEvent = function( event ) { this.fireEvent("onCommand"); } - +/** + * The name of the native peer event to attach to our onCommand---it + * should be a major event for the peer, like onSelect for a selection box, + * or onSliderMoved for a slider. +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.getPeerOnCommandEvent = function(){ return "onClick" ; } -// Closure to create a default event-handling function---is there still a problem -// (memory leak) with this in IE? +/** + * @private + * Closure to create a default event-handling function for one of the peer's---is there still a problem + * (memory leak) with this in IE? +**/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.getOnXFunction = function(str){ return function(){ return this.fireEvent(str) ; @@ -198,9 +330,10 @@ /** - * Default behavior: transfer all "onXXX" methods to the bridge: + * Default behavior: mirror all "onXXX" methods on the bridge using fireEvent calls + * ---we can change this in subclasses if we don't like it. **/ -xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.getEventTriggers = function () { +xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.findPeerEvents= function () { if(! this.eventTriggers ){ var triggerMap = new Object() ; // Let's transfer all the "onXXX" methods over to the bridge---first find @@ -214,13 +347,6 @@ // By default, ".onFoo" maps to ".onFoo", but this could // change, so allow for that: triggerMap[methodName] = { src: this._peer, methodName: methodName } ; - // Create the callback for this "on..." method, if we don't explicitly have it: - if( !this[methodName]){ - // This is the only way I could think of (that worked) to - // get the name of the event into the callback definition, so - // "onBlur" --> this.fireEvent("onBlur") - this[methodName] = this.getOnXFunction(methodName) ; - } } } this.eventTriggers = triggerMap ; @@ -228,12 +354,6 @@ return this.eventTriggers ; }; -/** - * Default behavior in this abstract superclass: the display dom node is the root dom node. -**/ -xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.getDisplayDomNode = function(){ - return this.getRootDomNode() ; -} /** * @return An HTML object (e.g., a DIV or a TD or...) which this widget can replace---this @@ -258,9 +378,10 @@ /** - * This is a default behaviour---subclasses should short-circuit this being called if they want to + * This is a default crude behaviour---look for a setter on the peer and use it, otherwise look for + * a field of the given name and return it. Subclasses should short-circuit this being called if they want to * do anything interesting (e.g. aButton.getText--> peer.getCaption) . - * @param attributeName{string} + * @param name{String} * @return object or primitive from the getter **/ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.getAttribute = function(name){ @@ -276,6 +397,8 @@ } /** + * @private + * @static * Memoiser to avoid the same string operation's repetition: **/ xap.bridges.basic.AbstractBlackBoxWidgetBridge._nameToSetterMap = new Object() ; @@ -342,16 +465,27 @@ xap.bridges.basic.AbstractBlackBoxWidgetBridge.prototype.autoAttachBridgeEventsToPeerEvents = function(){ // O.K., this is an object we can use as a bridge---go on: - var triggers = this.getEventTriggers() ; + var triggers = this.findPeerEvents() ; // We now have a hash table containing a set of strings (triggers) pointing to // objects, like "[Foobar.]onBaz"--->aFoobarInstance for(var aKey in triggers){ + var source = triggers[aKey].src ; var triggerPieces = triggers[aKey].methodName.split(".") ; // handles both "foo" and "Me.foo" var trigger = triggerPieces[triggerPieces.length - 1] ; + + // Create the callback for this "on..." method, if we don't explicitly have it: + if( !this[trigger]){ + // This is the only way I could think of (that worked) to + // get the name of the event into the callback definition, so + // "onBlur" --> this.fireEvent("onBlur") + this[trigger] = this.getOnXFunction(trigger) ; + } dojo.event.connect(source,trigger, this,trigger); } + + // Connect "onCommand" to a special event for the widget: dojo.event.connect(this.getPeer(),this.getPeerOnCommandEvent(),this,"_onCommandEvent") ; }