incubator-xap-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mtu...@apache.org
Subject svn commit: r432327 - /incubator/xap/trunk/src/xap/bridges/basic/AbstractBlackBoxWidgetBridge.js
Date Thu, 17 Aug 2006 18:36:03 GMT
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 <code>xap.taghandling.AbstractTagImpl</code>
+ *  intended as an abstract<code> </code>superclass for the
+ *  other bridges.&nbsp; 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.
+ * <br/>
+ *
+ * @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
+ * <ol>
+ * <li>: Create or obtain the peer object
+ * <li>: Handle all the initial attributes
+ * <li>: Recursively parse the inititial children
+ * </ol>
+* Here we look at the layout rectangle (if any) as defined by the XAL-spec'd <code>{x,y,width,height}</code>
+ * parameters, and add this information to <code>this._creationProperties</code>
+ * for the subclasses to do with as they will.&nbsp; Then <code>createPeer</code>
+ * (see below) and attribute- and children-parsing routines called, but
+ * these latter two shouldn't need to be
+ * changed from their implementations in <code>xap.taghandling.AbstractTagImpl</code>.</li>
+ * @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 <code>typeof</code>
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 <code>processPeer</code>, since it now
+ *   calls <code>obtainPeer</code> to create or find our underlying widget.
+* <ol>
+  * <li><strong>Peer acquisition and layout</strong>: The core of
+ * the
+ * class is in the (now a bit archaicly named) <code>createPeer()</code>.
+ * <ol type="a">
+ * <li>It finds a peer using the method <code>obtainPeer</code>,
+ * whose implementation is left up to the implementing subclass. <br/>
+ * </li>
+ * <li>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:&nbsp; the parent provides the
+ * pane's "container" node where children will be inserted, and this
+ * bridge provides a node containing the whole button). <br/>
+ * </li>
+ *  
+ * <ol>
+ * (Note that the
+ * bridge will only get as much information as it needs from another
+ * bridge, an HTMLElement---it doesn't need to know <u>anything</u>
+ * 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. 
+ * </ol>
+ * <li>Alternately, a locator attribute in the XAL is queried
+ * via <code>getSpecifiedDisplayNode()</code>,
+ * and that i.d. used to
+ * find
+ * the parent node.</li>
+ * </ol>
+ *  </li>
+ * <li><strong>Event handling</strong>: 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 <code>fireEvent("onXXX")</code>,
+ * if it does not already exist---this means
+ * that subclasses that already implement an <code>onFoo</code> 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 <code>oneInstance</code>?);
+ * 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 <code>dojo.event.connect</code>.
+ * Finally, our own <code>_onCommandEvent</code> call is connected to
+ * whichever event the bridge class specifies
+ * with <code>getOnCommandEvent</code>, so a button can ask that <code>onClick</code>
+ * get this
+ * attention, but a calendar <code>onSetDate</code>.</li>
+ * <li><b>Glue and upgrading:&nbsp;</b>
+ * Finally, the
+ * peer is fixed to this bridge using <code>setPeer</code>,
+ * which both sets the <code>_peer</code> 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.&nbsp; 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.<br/>
+ * </li>
+ * <li><b>Attribute handling</b>:&nbsp;
+ * When a XAL attribute is processed, it triggers a call to <code>attributeSet()</code>;
+ * here lowest-common-denominator behavior dominates----for an attribute <code>bar</code>,
+ * we look for a setter <code>setFoo </code>on the peer, and if it
+ * exists call it.&nbsp; In the case of the namespace attribute <code>xmlns
+ * </code>and the event call <code>onCommand()</code> we do something
+ * smarter---apart from these exceptions, anything more interesting and
+ * widget-specific will have to be handled in subclasses.<br/>
+ * </li>
+ * </ol>
+ *   @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 <code>onCommand</code> event, here so that we can
hook that
+ * up to the peer event specified by <code>getPeerOnCommandEvent</code> 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 <code>onCommand</code>---it
+ *  should be a major event for the peer, like <code>onSelect</code>  for a selection
box,
+ *  or <code>onSliderMoved</code> 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 <code>fireEvent</code>
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, "<bridge>.onFoo" maps to "<peer>.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., <code>this</code> 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") ;
 }
 



Mime
View raw message