Pulling out card navigation as a separate module, adding more styles for conversation summaries
authorJames Burke <jrburke@mozillamessaging.com>
Mon, 14 Jun 2010 23:11:50 -0700
changeset 1778 f759fb23d8abf31dedec8984894618ae0c8b2c3e
parent 1777 f021ce6347b633773fb31d320c66197a6d3efaac
child 1779 5f8b0ff1ef822d412f73d26a4479d8c5fe5ad1bf
push id981
push userjrburke@gmail.com
push dateTue, 15 Jun 2010 06:12:07 +0000
Pulling out card navigation as a separate module, adding more styles for conversation summaries
client/api/contacts.css
client/api/contacts.html
client/api/i/favicon.ico
client/api/i/gray-arrow.png
client/api/i/mailIcon.png
client/api/i/twitterIcon.png
client/api/scripts/cards.js
client/api/scripts/templates/cardsHeader.html
--- a/client/api/contacts.css
+++ b/client/api/contacts.css
@@ -39,17 +39,16 @@ ul {
     overflow: hidden;
     white-space: nowrap;
     text-overflow: ellipsis;
 }
 
 
 #back {
     position: absolute;
-    display: none;
     top: 0px;
     left: 0px;
 }
 
 /* Heading Arrow Button */
 .mblArrowButtonHead {
     position: absolute;
     top: 10px;
@@ -130,37 +129,37 @@ ul {
 }
 
 #contactsCard {
     position: relative;
     z-index: 1;
     overflow: scroll;
 }
 
-#contactList {
+.maxWidthList {
     width: 100%;
     list-style: none;
     padding: 0;
     margin: 0;
     background-color: white;
 }
 
-#contactList li {
+.maxWidthList li {
     position: relative;
     width: 100%;
     height: 43px;
     padding-left: 8px;
     list-style-type: none;
     border-bottom: 1px solid #ADAAAD;
     line-height: 43px;
     font-weight: bold;
     color: black;
 }
 
-#contactList li a {
+.maxWidthList li a {
     display: block;
     width: 100%;
     height: 100%;
     text-decoration: none;
     color: black;
 }
 
 #identityDisplay ul {
@@ -198,20 +197,16 @@ ul {
     color: #0B5199;
     font-size: smaller;
 }
 
 .contactDetail .idValue {
     padding: 0 5px;
 }
 
-#contactConversations {
-    margin: 10px;
-}
-
 .scrollbar {
     position: absolute;
     z-index: 10;
     width: 1px;
     height: 1px;
     border-width: 3px;
     -webkit-border-image: url(i/scrollbar.png) 3;
 }
@@ -268,16 +263,49 @@ ul {
 .mblRoundRectList .mblListItem:last-child {
     border-bottom-width: 0px;
     -webkit-border-bottom-left-radius: 8px;
     -webkit-border-bottom-right-radius: 8px;
     -moz-border-radius-bottomleft: 8px;
     -moz-border-radius-bottomright: 8px;
 }
 
+.maxWidthList li.conv {
+    line-height: normal;
+    padding: 8px 0 0 20px;
+    background: transparent url(i/mailIcon.png) center left no-repeat;
+}
+
+.maxWidthList li.twitter {
+    background: transparent url(i/twitterIcon.png) center left no-repeat;
+    padding-left: 20px;
+}
+
+.maxWidthList li.conv .summary {
+    height: auto;
+}
+
+.maxWidthList li .bodyPreview {
+    display: block;
+    font-weight: normal;
+    font-size: smaller;
+}
+
+li .mblArrow {
+    position: absolute;
+    top: 16px;
+    right: 30px;
+    width: 9px;
+    height: 13px;
+    font-size: 1px;
+    border-width: 3px 3px 0px 0px;
+    border-color: #808080;
+    border-style: none;
+    background-image: url(i/gray-arrow.png);
+}
 
 /* START hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
 /* hbox and vbox classes */
  
 .hbox {
 	display: -webkit-box;
 	-webkit-box-orient: horizontal;
 	-webkit-box-align: stretch;
--- a/client/api/contacts.html
+++ b/client/api/contacts.html
@@ -1,29 +1,35 @@
 <!DOCTYPE html>
 <html>
 <head>
     <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
     <meta name="apple-mobile-web-app-capable" content="yes" />
     <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
     <title>Contact Listing</title>
+    <link REL="SHORTCUT ICON" HREF="i/favicon.ico">
     <link type="text/css" rel="stylesheet" href="contacts.css">
 
     <script src="scripts/requireplugins-jquery-1.4.2.js" charset="utf-8"></script>
     <script>
-        "use strict";
+        'use strict';
         /*global require: false, console: false */
 
         /*
          To detect orientation changes in Android:
          http://stackoverflow.com/questions/1649086/detect-rotation-of-android-phone-in-the-browser-with-javascript
         */
 
-        require(["jquery", "rdapi", "blade/jig", "json2", "iscroll-min"], function ($, rdapi, jig) {
-            var scroller, display, cards, cardList, back, header;
+        require(['jquery', 'rdapi', 'cards', 'blade/jig', 'json2', 'iscroll-min'],
+        function ($,        rdapi,   cards,   jig) {
+
+            var scroller, display, cardList, back, header;
+
+            //Initialize the card setup
+            cards('#display');
 
             //Set up extra template functions.
             rdapi.addJigFunctions({
                 getPhotoUrl: function (contact) {
                     var i, identity, url = 'i/face.png';
                     if (contact.identities) {
                         for (i = 0; (identity = contact.identities[i]); i++) {
                             if (identity.image) {
@@ -31,73 +37,24 @@
                                 break;
                             }
                         }
                     }
                     return url;
                 }
             });
 
-            function adjustCardSizes() {
-                var cardWidth = display.outerWidth(),
-                    cardList = $('.card'),
-                    totalWidth = cardWidth * cardList.length,
-                    height = window.innerHeight - header.outerHeight();
-
-                //Set height
-                display.css('height', height + 'px');
-
-                //Set widths and heights of cards. Need to set the heights
-                //explicitly so any card using iscroll will get updated correctly.
-                cards.css({
-                    width: totalWidth + 'px',
-                    height: height + 'px'
-                });
-
-                cardList.css({
-                    width: cardWidth + 'px',
-                    height: height + 'px'
-                });
-            }
-
             $(function () {
                 //setup for the iscroll thing
                 if ('ontouchmove' in document) {
                     document.addEventListener('touchmove', function(e){ e.preventDefault(); }, false);
                     scroller = new iScroll('contactList');
                 }
-                display = $('#display');
-                cards = $('#cards');
-                back = $('#back');
-                header = $('#header');
-
-                adjustCardSizes();
-
-                //Set the title based on the first card.
-                var title = $('.card')[0].getAttribute('title');
-                $('#headerText').html(title);
-
-                back.click(function (evt) {
-                    var left = parseInt(cards.css('left'), 10) + display.outerWidth();
-
-                    cards.css({
-                        left: left + 'px'
-                    });
-                    if (!left) {
-                        back.css('display', 'none');
-                    }
-                });
             });
 
-            //Detect orientation changes and size the card container size accordingly.
-            if ('onorientationchange' in window) {
-                window.addEventListener('orientationchange', adjustCardSizes, false);
-            }
-            window.addEventListener('resize', adjustCardSizes, false);
-
             $('body')
             .delegate('a.person', 'click', function (evt) {
                 evt.preventDefault();
                 var contact = rdapi.data(evt.target.parentNode.getAttribute('data-blade-jig'));
                 rdapi('_design/raindrop!content!all/_view/identities_by_contact', {
                     data: {
                         startkey: JSON.stringify([contact.id[1]]),
                         endkey: JSON.stringify([contact.id[1], {}])
@@ -129,20 +86,17 @@
                                 if (identities.length) {
                                     contact.identities = identities;
                                 }
                                 html = jig(options.template, contact, options);
 
                                 $('#identityDisplay').html(html);
 
                                 //Scroll the cards.
-                                cards.css({
-                                    left: '-' + display.outerWidth() + 'px'
-                                });
-                                back.css('display', 'block');
+                                cards.forward();
                             }
                         });
                     }
                 });
             })
             .delegate('.conversationButton', 'click', function (evt) {
                 var contact = rdapi.data($(evt.target).parents('.contactDetail')[0].getAttribute('data-blade-jig'));
                 rdapi('inflow/conversations/contact', {
@@ -152,54 +106,42 @@
                         message_limit: 3
                     },
                     contentType: '',
                     templateId: 'conversations',
                     emptyTemplateId: 'conversationsEmpty',
                     containerNode: document.getElementById('contactConversations'),
                     onTemplateDone: function () {
                         //Move the conversation card into view.
-                        cards.css({
-                            left: '-' + (2 * display.outerWidth()) + 'px'
-                        });
-
-                        setTimeout(function () {
-                            $('#headerText').html(document.getElementById('contactInfo').innerHTML);
-                        }, 300);
+                        cards.forward(document.getElementById('contactInfo').innerHTML);
                     }
                 });
             });
         });
     </script>
 </head>
 <body>
-    <div id="header">
-        <div id="back">
-            <div class="mblArrowButtonHead"></div>
-            <div class="mblArrowButtonBody mblArrowButtonText">Back</div>
-            <div class="mblArrowButtonNeck"></div>
-        </div>
-        <span id="headerText"></span>
-    </div>
-
+    <!-- UI Cards, some structure mandated by cards.js -->
     <div id="display">
         <div id="cards">
             <div id="contactsCard" class="card" title="Contacts">
-                <ul id="contactList" class="contacts templateContainer">
+                <ul id="contactList" class="contacts maxWidthList templateContainer">
+                    <!-- Template that loads all contacts ans shows a list of the by name -->
                     <li class="template" data-api="inflow/contacts/by_name"><a class="person" href="#{id[1]}">{displayName}</a></li>
                 </ul>
             </div>
             <div id="identityDisplay" class="card card2" title="Info">
             </div>
-            <div id="conversations" class="card card3" title="Conversations">
-                <ul id="contactConversations" class="mblRoundRectList"></ul>
+            <div id="conversations" class="card card3">
+                <ul id="contactConversations" class="maxWidthList"></ul>
             </div>
         </div>
     </div>
 
+    <!-- Template for showing contact details -->
     <div class="template contactDetail" data-id="contactDetail">
         <div id="contactInfo">
             <img class="contactPhoto" src="{getPhotoUrl(_)}"> <span class="contactDisplayName">{displayName}</span>
         </div>
         <ul>
             {identities [}
                 <li>
                     <ul class="mblRoundRectList">
@@ -208,24 +150,26 @@
                         <li class="mblListItem identity hbox"><span class="idType boxFlex">{type}</span><span class="idValue boxFlex">{value}</span></li>
                     </ul>
                 </li>
             {]}
         </ul>
         <ul class="mblRoundRectList">
             <!-- Interesting, for the delegate on this li to work in Mobile Safari,
                  need to put an onclick on here. -->
-            <li class="mblListItem conversationButton" onclick="return;">Show Recent Conversations</li>
+            <li class="mblListItem conversationButton" onclick="return;">Show Recent Conversations<div class="mblArrow"></div></li>
         </ul>
     </div>
 
-    <li class="template conversation mblListItem" data-id="conversations">
-        {subject [} {} {]}
-        {!subject [}
-            {messages[0].schemas['rd.msg.body'].body_preview}
-        {]}
+    <!-- Template for showing conversation summaries -->
+    <li class="template summary {id[0]}" data-id="conversations">
+        <span class="subject">{subject}</span>
+        <span class="bodyPreview">{messages[0].schemas['rd.msg.body'].body_preview}</span>
+        <div class="mblArrow"></div>
     </li>
 
+    <!-- Template for when contact has no conversations available. -->
     <li class="template conversation" data-id="conversationsEmpty">
         No conversations for this contact.
     </li>
+
 </body>
 </html>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d87e726befb69fe50108319c92cf8f7d5f1924e8
GIT binary patch
literal 1150
zc$}q_OG^S#6vuDSMg<Y0wi&gE!dFhUDe7amDW@dp3$%0R`webfv>2jA3lVYQS|waa
zuC$d~S3dEv5EVS#dm72B69k>%H#6M(|IHjOcZQG+dgye7mVrEO60$?@4k<buA#|3V
z3Ax@RYXtxs47FOltJmvK{{qV{yaisb_qp5cPW}SRuKI~Y;sxZYR%_sNK7b&cgJ3(y
zdp5QxIm`L+cwAz0wc00`j8-u0?sKp)HpfcND*B@1p7Zt$KUat2?pHq+i=l6|3QO(*
z_biLqhQ6HT{Ae_azS%^3H>|%Oeap8mXE{F{4$J<DV*iZW8xj3TB(mm*LLu~zk4)>m
z(`Ois7Wnw6pf6`RKNt+6e|d3*Jy^^qcol4CxTfWD8AhWK`f`@@{eHhRpU<J+?<>;l
z^?>djm`<nQ^Z8yC_MbGH%`meJ^V;n;R4Nt7X0uQz6u@q`2UmTM$0JQ96U;8t>2#pc
zXh5k{f_y#?E|;sQQmM9AeYe{!jmKkXHk%x+RtxI&I`)#uWZtz}?bfQx2m}IeY;A_a
sA;(}a!1pJU$#?qQDY^_%6rXarTrrhOair7fBI`|~(I~p?5AYwp0A|q1FaQ7m
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c93d17f5e8826e4caaa59410f44992f587e9965c
GIT binary patch
literal 920
zc%17D@N?(olHy`uVBq!ia0vp^oFFy_Gm!MTx5WfVv6p!Iy0YJ56626i(p>F!9;Bwg
zBeIx*fm;ZK886+f`@_J%%n;xc;`*QAe?vn9!zdU9BNBw~dnW^=7)yfuf*Bm1-ADs+
z<UCy*Ln>}1CnO}Kq%<(Nxk*f(=%ThtLXK^ctU)y+-#P}%Hz_NRg0y?O`njxgN@xNA
DJ-#WD
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a131e19612f401c0827a8b93632e0ee6999e7353
GIT binary patch
literal 350
zc$@)V0iphhP)<h;3K|Lk000e1NJLTq000sI000sQ1^@s6R?d!B00009a7bBm000XU
z000XU0RWnu7ytkP5J^NqR5%gMQZWj`KoInTzX$<8Af(e$KcKyxgw#I4G}dA*wqj+i
zU1Dc#p`{R#!paXMaaP@9xdc(L$iZayX6NSi?xKpKX#8VX|1cqs`WZF(Xtr$!$cKQ-
zTvf!KhDxa@Ns>U;wGqfE1Y_VT1!f+{ap*Ws&*T-q8agU0%j#!Y<|4MhPfW3#W5Y$B
z=i4+*55$))8-h6mH`IK&(8veSt$~R7k`Wakm?3n55wHSyY|w27lNL5RGD%V1k>n}&
z-tckE6A{?pY#I<xqq3t{Nq?6xXk&H(_L?;kX>>Pga_YfsCkZpxuf_#>J<h+0_@5N%
wWJkR2Q)jH<sI{ezSn+GD>gZRGr@nqh54Yk=*r#9@umAu607*qoM6N<$f`^=v$p8QV
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5647d78d62e1439ea4deb3dbf95c89205ea0bc9b
GIT binary patch
literal 385
zc$@)&0e=38P)<h;3K|Lk000e1NJLTq000sI000sQ1^@s6R?d!B00009a7bBm000XU
z000XU0RWnu7ytkPGf6~2R5%gMQ%jD5Kop$rxM1m)Um`bfZor(txq;&e#v6>Bz<2_g
z6Bti09>E(x0)#DF2p_A+bb?81G-2UOUg)k@uXtTFqU*Z1F+z?ZLXFoGn&^(^IL;jS
zQV4Nu+xCF<F3YkFxvT-(qBcVYX_|(_h0bitveqDNNf<;7?hg15u&KhOlpjfwoU}ro
z=S{1s`U9Dh-HI~`N8|$HE3FVaDOQ%{0VJRM8&Lq~bfIK}jub^vfw6yewE@Q70RF86
z{Mg{Fanm#>!!U}vuIKP#f&2t%HfYi<V~BVx^hdL8dyn-OfoB2(yyL5#+0$Rhel!?{
zeetLe4OSxTxiZ@{P2P<?(!VG8FA@$pS3;`bx~`8)_l>=eq@gN8;6a|}u>#anE2N6g
fJYVmp9c`iuf(&{C9e%Wx00000NkvXXu0mjfIxnI$
new file mode 100644
--- /dev/null
+++ b/client/api/scripts/cards.js
@@ -0,0 +1,99 @@
+/*jslint */
+/*global require: false, window: false */
+'use strict';
+
+require.def('cards', ['jquery', 'text!templates/cardsHeader.html'], function ($, headerTemplate) {
+    var header, display, back, nlCards,
+        cardPosition = 0,
+        headerText = '',
+        cardTitles = [];
+
+    function adjustCardSizes() {
+        var cardWidth = display.outerWidth(),
+            cardList = $('.card'),
+            totalWidth = cardWidth * cardList.length,
+            height = window.innerHeight - header.outerHeight();
+
+        //Set height
+        display.css('height', height + 'px');
+
+        //Set widths and heights of cards. Need to set the heights
+        //explicitly so any card using iscroll will get updated correctly.
+        nlCards.css({
+            width: totalWidth + 'px',
+            height: height + 'px'
+        });
+
+        cardList.css({
+            width: cardWidth + 'px',
+            height: height + 'px'
+        });
+
+        //Reset the scroll correctly.
+        cards.scroll();
+    }
+
+    function cards(nl, title) {
+        nl = nl.jquery ? nl : $(nl);
+
+        $(function () {
+            //Insert the header before the cards
+            header = $(headerTemplate).insertBefore(nl);
+            headerText = $('#headerText');
+
+            back = $('#back');
+            back.css('display', 'none');
+            back.click(cards.back);
+
+            display = nl;
+            nlCards = display.find('#cards');
+
+            adjustCardSizes();
+            cards.setTitle(title);
+
+            //Detect orientation changes and size the card container size accordingly.
+            if ('onorientationchange' in window) {
+                window.addEventListener('orientationchange', adjustCardSizes, false);
+            }
+            window.addEventListener('resize', adjustCardSizes, false);
+
+        });
+    }
+
+    cards.back = function () {
+        cardPosition -= 1;
+        if (cardPosition < 0) {
+            cardPosition = 0;
+        }
+        cards.scroll();
+    };
+
+    cards.forward = function (title) {
+        cardPosition += 1;
+        cards.scroll(title);
+    };
+
+    cards.scroll = function (title) {
+        if (title) {
+            cardTitles[cardPosition] = title;
+        }
+
+        cards.setTitle(title);
+
+        var left = display.outerWidth() * cardPosition;
+
+        nlCards.css({
+            left: '-' + left + 'px'
+        });
+
+        //Hide/Show back button as appropriate
+        back.css('display', !cardPosition ? 'none' : '');
+    };
+
+    cards.setTitle = function (title) {
+        title = title || cardTitles[cardPosition] || nlCards.find('.card').eq(cardPosition).attr('title') || '';
+        headerText.html(title);
+    };
+
+    return cards;
+});
new file mode 100644
--- /dev/null
+++ b/client/api/scripts/templates/cardsHeader.html
@@ -0,0 +1,8 @@
+<div id="header">
+    <div id="back">
+        <div class="mblArrowButtonHead"></div>
+        <div class="mblArrowButtonBody mblArrowButtonText">Back</div>
+        <div class="mblArrowButtonNeck"></div>
+    </div>
+    <span id="headerText"></span>
+</div>