conversation view has action, yo.
authorAndrew Sutherland <asutherland@asutherland.org>
Tue, 13 Jan 2009 04:06:59 -0800
changeset 17 5a832fd81f4173a9cdb61dd2b274ea43b407a981
parent 16 608d65fc4ff224d3c60dc30e0f07bdeb8bdb8e98
child 18 6fd418a119c2359f5542ea91a204eae7d706b266
push id1
push userroot
push dateWed, 08 Apr 2009 01:46:05 +0000
conversation view has action, yo.
client/conversation.xhtml
client/conversation.xml
--- a/client/conversation.xhtml
+++ b/client/conversation.xhtml
@@ -1,20 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" id="html">
 <head>
   <title>Junius</title>
   <script src="/_utils/script/json2.js"></script>
   <script src="/_utils/script/jquery.js?1.2.6"></script>
   <script src="jquery.couch.js"></script>
   <script src="xbl-src.js"></script>
   <script src="md5.js"></script>
   <link rel="stylesheet" href="bindings.css" type="text/css"></link>
-  <link rel="stylesheet" href="conversation.css" type="text/css"></link>
   <script src="cloda.js"></script>
   <script src="cloda-completers.js"></script>
   <script src="utils.js"></script>
   <script type="text/javascript" charset="utf-8"><![CDATA[
     $(function() {
       window.setTimeout(funkyInit, 1000);
     });
     function funkyInit() {
--- a/client/conversation.xml
+++ b/client/conversation.xml
@@ -56,21 +56,25 @@
 .threader ul { font-size: small; margin: 0em; padding: 0em;
                border-left: 0.3em solid transparent; }
 .threader ul.selected { border-color: #cee1ef; }
 
       ]]></xbl:style>
     </xbl:resources>
     <xbl:implementation><![CDATA[
       ({
+        getToolboxNode: function() {
+          return this.shadowTree.getElementById("toolbox");
+        },
         conversation: null,
         setConversation: function(aConversation) {
           this.conversation = aConversation;
           this.expandedMessageIds = {};
-          this.selectedMessage = null;
+          this.selectedMessageBinding = null;
+          this.selectedThreadBinding = null;
 
           this.shadowTree.getElementById("subject").textContent =
             this.conversation.subject;
 
           var threadRoot = this.shadowTree.getElementById("threadroot");
           var topnodes = this.conversation.threadMessages();
           console.log("top nodes", topnodes);
           for (var iTopNode = 0; iTopNode < topnodes.length; iTopNode++) {
@@ -96,29 +100,50 @@
           // -- layout stuff that probably should not go here but rather in
           //  the bind event or what not
           this.positionFixedElements();
           var dis = this;
           $(window).resize(function() { dis.positionFixedElements(); });
         },
         addMessageNode: function(aMessage) {
           var messagesRoot = this.shadowTree.getElementById("messages");
-          var messageNode = $("<div/>").appendTo(messagesRoot)[0];
+          var messageNode = $("<div/>").attr("id", "msg" + aMessage._id)
+                                       .appendTo(messagesRoot)[0];
           ElementXBL.prototype.addBinding.call(messageNode,
                                                "conversation.xml#conv-message");
           console.log("setMessage with", aMessage);
           messageNode.setMessage(aMessage);
 
           if (aMessage._children) {
             for (var iChild = 0; iChild < aMessage._children.length; iChild++) {
               var childMessage = aMessage._children[iChild];
               this.addMessageNode(childMessage);
             }
           }
         },
+        selectMessage: function(aMessage) {
+          var binding = document.getElementById("msg" + aMessage._id);
+          // okay, maybe we don't really need to get the inner binding, because
+          //  this is ugly (and I think we were careful in the next func...)
+          this.selectMessageBinding(
+            binding.xblImplementations[binding.xblImplementations.length-1]);
+        },
+        selectMessageBinding: function(aInnerMessage) {
+          var message = aInnerMessage.getMessage();
+
+          aInnerMessage.expand();
+          aInnerMessage.ensureVisible();
+          this.selectedMessageBinding = aInnerMessage;
+
+          if (this.selectedThreadBinding)
+            this.selectedThreadBinding.unselect();
+          this.selectedThreadBinding =
+            document.getElementById("thread" + message._id);
+          this.selectedThreadBinding.select();
+        },
         expand: function(aMessages) {
 
         },
         positionFixedElements: function() {
           var toolboxNode = this.shadowTree.getElementById("toolbox");
           $(toolboxNode).width($(this.boundElement).width());
           var top = $(toolboxNode).height() + 10;
           var threaderNode = this.shadowTree.getElementById("threader");
@@ -187,18 +212,18 @@
         },
         unselect: function() {
           $(this.boundElement).removeClass("selected")
                               .parent().removeClass("selected");
         }
       })
     ]]></xbl:implementation>
     <xbl:handlers>
-      <xbl:handler event="click"><![CDATA[
-
+      <xbl:handler event="click" phase="bubble" propagate="stop"><![CDATA[
+        $("#conversation-reader")[0].selectMessage(this.message);
       ]]></xbl:handler>
     </xbl:handlers>
   </xbl:binding>
 
   <!-- Message in a Conversation -->
     <xbl:binding id="conv-message">
     <xbl:template>
       <div class="header">
@@ -223,17 +248,17 @@
           </div>
         </div>
       </div>
       <div class="body">
         <div id="attachments-list" class="attachments-list">
           <div>attachments</div>
           <ul id="attachment_ul"></ul>
         </div>
-        <div id="iframe" class="content"></div>
+        <pre id="iframe" class="content"></pre>
         <div class="attachments-area"></div>
         <div class="actions">
           <button>reply all | v</button>
           <button>forward</button>
           <button>other actions | v</button>
         </div>
       </div>
     </xbl:template>
@@ -302,16 +327,19 @@
 :bound-element.expanded .header .headers .details .snippet { visibility: hidden; }
 :bound-element.expanded .header .headers .details .toggle { display: inline; }
 
       ]]></xbl:style>
     </xbl:resources>
     <xbl:implementation><![CDATA[
       ({
         message: null,
+        getMessage: function() {
+          return this.message;
+        },
         setMessage: function(aMessage) {
           this.message = aMessage;
 
           this.shadowTree.getElementById("date").textContent =
             makeTimestampFriendly(this.message.timestamp);
           this.shadowTree.getElementById("sender").textContent =
             this.message.from.name;
 
@@ -327,20 +355,40 @@
         },
         select: function() {
           $(this.boundElement).addClass("selected")
                               .parent().addClass("selected");
         },
         unselect: function() {
           $(this.boundElement).removeClass("selected")
                               .parent().removeClass("selected");
+        },
+        expand: function() {
+          $(this.boundElement).addClass("expanded");
+          this.expanded = true;
+        },
+        ensureVisible: function() {
+          // delay for offsets to be correct (maybe only needed for iframes?)
+          var dis = this;
+          window.setTimeout(function() {
+            var convReader = document.getElementById("conversation-reader");
+            var toolbox = convReader.getToolboxNode();
+            // XXX constant...
+            var targetOffset = $(dis.boundElement).offset().top - $(toolbox).height() - 10;
+            // XXX really?
+            $(document.getElementById('html')).animate(
+              { scrollTop: targetOffset }, "fast");
+            $(dis.boundElement).animate(
+                { backgroundColor: "#ffffcc" }, { queue: true, duration: 500 })
+              .animate({ backgroundColor: "#ffffff" }, 500);
+          }, 200);
         }
       })
     ]]></xbl:implementation>
     <xbl:handlers>
-      <xbl:handler event="click"><![CDATA[
-
+      <xbl:handler event="click" phase="bubble" default-action="cancel"><![CDATA[
+        $("#conversation-reader")[0].selectMessageBinding(this);
       ]]></xbl:handler>
     </xbl:handlers>
   </xbl:binding>
 
 
 </xbl:xbl>