internal/external issues have at least been made consistent, but we need to understand what the actual XBL2 spec intent is and try and match that, dealing with the cross-platform limitations...
authorAndrew Sutherland <asutherland@asutherland.org>
Sun, 11 Jan 2009 07:45:24 -0800
changeset 5 66f9fe7b2df5025c5c439a4469b3ad08baf07b01
parent 4 bf188e8e220c8da301e6c55af5bbfaa0a1bc31d8
child 6 d9d6be88da9347b14703f293eecc5c4b631c2c8d
push id1
push userroot
push dateWed, 08 Apr 2009 01:46:05 +0000
internal/external issues have at least been made consistent, but we need to understand what the actual XBL2 spec intent is and try and match that, dealing with the cross-platform limitations...
client/autocomplete.xml
client/bubbles.xml
client/index.xhtml
client/messages.xml
client/xbl-src.js
--- a/client/autocomplete.xml
+++ b/client/autocomplete.xml
@@ -69,32 +69,35 @@
           if (this.selectedIndex != null)
             $(children[this.selectedIndex]).removeClass(this.SELECTED_CLASS);
           this.selectedIndex = aDesiredIndex;
           if (this.selectedIndex != null)
             $(children[this.selectedIndex]).addClass(this.SELECTED_CLASS);
         },
         /* ===== Action ===== */
         actionListener: null,
+        addActionListener: function(aActionListener) {
+          this.actionListener = aActionListener;
+        },
         actOnSelected: function() {
           console.log("Taking action on index", this.selectedIndex);
           if (this.selectedIndex != null) {
             var selected = this._resultDiv.childNodes[this.selectedIndex];
             if (this.actionListener != null)
               this.actionListener(selected);
             else
               console.log("Warning! There was no action listener!", this, this.actionListener);
           }
           console.log("Actiong taking done!");
         },
         
         /* ===== House-keeping ==== */
         xblBindingAttached: function () {
           console.log("autocompleter binding and what not", this);
-          this._entry = this.boundElement.getElementById("entry");
+          this._entry = this.shadowTree.getElementById("entry");
           this._resultDiv = $("<div/>").hide().css("position", "absolute")
                              .addClass("auco_results")
                              .appendTo(document.body)[0];
           console.log("done binding");
         },
       })
     ]]></xbl:implementation>
     <xbl:handlers>
@@ -142,17 +145,21 @@
           height: 32;
           float: left;
         }
       ]]></xbl:style>
     </xbl:resources>
     <xbl:implementation><![CDATA[
       ({
         type: "contact",
+        getType: function() { return this.type; },
         contact: null,
+        getContact: function() {
+          return this.contact;
+        },
         setContact: function(aContact) {
           this._contact = aContact;
           console.log("setContact", this);
           this._nName.textContent = this._contact.name;
           var bestEmail = null;
           var emailText = this._contact.identities.map(function (identity) {
             if (identity.kind == "email")
               bestEmail = identity.value;
@@ -165,19 +172,19 @@
               ".jpg?r=pg&d=identicon&s=32");
             // XXX soon, let's point at the gravatar
             // XXX later, let's use a pic if it exists, or gravatar push if it
             //  doesn't.  (or maybe have a daemon that takes care of it?)
           }
         },
         xblBindingAttached: function () {
           console.log("attaching contact result");
-          this.boundElement._nPicture = this.boundElement.getElementById("picture");
-          this.boundElement._nName = this.boundElement.getElementById("name");
-          this.boundElement._nEmails = this.boundElement.getElementById("emails");
+          this._nPicture = this.shadowTree.getElementById("picture");
+          this._nName = this.shadowTree.getElementById("name");
+          this._nEmails = this.shadowTree.getElementById("emails");
           console.log("done attaching contact result");
         },
       })
     ]]></xbl:implementation>
     <xbl:handlers>
     </xbl:handlers>
   </xbl:binding>
 
--- a/client/bubbles.xml
+++ b/client/bubbles.xml
@@ -13,21 +13,18 @@
         _nConstraints: null,
         addContact: function(aContact) {
           var node = $("<div/>").addClass("bubble")[0];
           ElementXBL.prototype.addBinding.call(node, "bubbles.xml#constraint-contact");
           node.setContact(aContact);
           $(this._nConstraints).append(node);
           console.log("Contact", aContact, "added");
         },
-        init: function() {
-          this._nConstraints = this.getElementById("holder");
-        },
         xblBindingAttached: function () {
-          this.boundElement.init();
+          this._nConstraints = this.shadowTree.getElementById("holder");
         },
       })
     ]]></xbl:implementation>
     <xbl:handlers>
       <xbl:handler event="click"><![CDATA[
       ]]></xbl:handler>
     </xbl:handlers>
   </xbl:binding>
@@ -46,24 +43,24 @@
       ]]></xbl:style>
     </xbl:resources>
     <xbl:implementation><![CDATA[
       ({
         contact: null,
         setContact: function(aContact) {
           this.contact = aContact;
           console.log("setContact", this);
-          this.getElementById("name").textContent = this.contact.name;
+          this.shadowTree.getElementById("name").textContent = this.contact.name;
           var bestEmail = null;
           var emailText = this.contact.identities.forEach(function (identity) {
             if (identity.kind == "email")
               bestEmail = identity.value;
           });
           if (bestEmail) {
-            this.getElementById("picture").setAttribute("src",
+            this.shadowTree.getElementById("picture").setAttribute("src",
               "http://www.gravatar.com/avatar/" + hex_md5(bestEmail) +
               ".jpg?r=pg&d=identicon&s=18");
           }
         },
       })
     ]]></xbl:implementation>
   </xbl:binding>
 </xbl:xbl>
--- a/client/index.xhtml
+++ b/client/index.xhtml
@@ -17,23 +17,23 @@
   <script type="text/javascript" charset="utf-8"><![CDATA[
     function funkyInit() {
       var autocompleter = document.getElementById("autocomplete");
       console.log("autocompleter", autocompleter);
       autocompleter.addCompleter(ContactCompleter);
       console.log("contact completer registered");
       
       var constraints = document.getElementById("constraints");
-      autocompleter.actionListener = function (item) {
+      autocompleter.addActionListener(function (item) {
         console.log("!!!Action Listener!!!", item);
-        if (item.type == "contact")
-          constraints.addContact(item.contact);
+        if (item.getType() == "contact")
+          constraints.addContact(item.getContact());
         else
           return;
-      };
+      });
       console.log("constrainer registered");
     }
 
     $(function() {
       window.setTimeout(funkyInit, 1000);
       //DocumentXBL.prototype.loadBindingDocument.call(document, "messages.xml");
       /*
       var dbMessages = $.couch.db("messages");
--- a/client/messages.xml
+++ b/client/messages.xml
@@ -9,18 +9,18 @@
         <span id="subject"></span><br/>
         <pre id="body"></pre>
       </div>
     </xbl:template>
     <xbl:implementation><![CDATA[
       ({
         setMessage: function(aMessage) {
           this._message = aMessage;
-          this.getElementById("subject").textContent = this._message.headers.Subject;
-          this.getElementById("body").textContent = this._message.bodyPart.data;
+          this.shadowTree.getElementById("subject").textContent = this._message.headers.Subject;
+          this.shadowTree.getElementById("body").textContent = this._message.bodyPart.data;
         },
       })
     ]]></xbl:implementation>
     <xbl:handlers>
       <xbl:handler event="click"><![CDATA[
       
       ]]></xbl:handler>
     </xbl:handlers>
--- a/client/xbl-src.js
+++ b/client/xbl-src.js
@@ -1439,22 +1439,40 @@ cElementXBL.prototype.addBinding	= funct
 	//
 	sDocumentUri	= fResolveUri(sDocumentUri, document.location.href);
 
 	// 0) Get Binding (synchronously)
 	var cBinding	= cXBLLanguage.getBinding(sDocumentUri);
 	if (!cBinding)
 		return;
 
+    // The oBinding is roughly the internal object, whereas 'this' gets to be
+    //  the external object.
 	var oBinding	= new cBinding;
 
 	// 3) Attach implementation
+    function bind(func) {
+      return function() {
+        func.apply(oBinding, arguments);
+      };
+    }
+
 	for (var sMember in oBinding)
-		if (sMember.indexOf("xbl") != 0)
-			this[sMember]	= oBinding[sMember];
+		if (sMember.indexOf("xbl") != 0) {
+            // All functions need to be wrapped to dispatch so that they are
+            //  calling the method on the inner object, otherwise things get
+            //  in a mess 'this'-wise.
+            if (typeof(oBinding[sMember]) == "function") {
+                this[sMember] = bind(oBinding[sMember]);
+            }
+            // ugh, and for now, don't copy any values across, but this really
+            //  would like to be approximated by getter/setters that proxy...
+            //else
+			//    this[sMember]	= oBinding[sMember];
+        }
 
 //	oBinding.$unique	= "xbl" + '-' + window.Math.floor(window.Math.random()*100000000);
 
 	// 1) Create shadowTree
 	if (cBinding.template) {
 		var oShadowContent	= fCreateTemplate(cBinding),
 			aShadowAnchors	= oShadowContent.getElementsByTagName("strike"),	// live collection
 			nShadowAnchor	= 0,