Some updates to templating and some styles for the contact display.
authorJames Burke <jrburke@mozillamessaging.com>
Thu, 10 Jun 2010 21:31:50 -0700
changeset 1774 e3f8049f4fc9d6078d89ae6157adb92d745d6785
parent 1773 8514627ef0f2391560fb09081eb460b51109f638
child 1775 19641d6b8ff454124e6865613f25414ef8150f86
push id977
push userjrburke@gmail.com
push dateFri, 11 Jun 2010 04:31:56 +0000
Some updates to templating and some styles for the contact display.
client/api/contacts.css
client/api/contacts.html
client/api/scripts/blade/jig.js
client/api/scripts/rdapi.js
--- a/client/api/contacts.css
+++ b/client/api/contacts.css
@@ -158,16 +158,47 @@ body,ul,li {
     text-decoration: none;
     color: black;
 }
 
 #identityDisplay ul {
     list-style: none;
 }
 
+.contactDetail {
+    padding: 10px;
+}
+
+.contactPhoto {
+    width: 60px;
+    height: 60px;
+    vertical-align: middle;
+    margin-right: 10px;
+    border: 1px solid #ADAAAD;
+}
+
+.contactDetail .name {
+    font-weight: bold;
+}
+
+.contactDetail .mblListItem {
+    width: 100%;
+}
+
+.contactDetail .idType {
+    text-align: right;
+    padding: 0 5px;
+    color: #0B5199;
+    font-size: smaller;
+}
+
+.contactDetail .idValue {
+    padding: 0 5px;
+}
+
 .scrollbar {
     position: absolute;
     z-index: 10;
     width: 1px;
     height: 1px;
     border-width: 3px;
     -webkit-border-image: url(i/scrollbar.png) 3;
 }
@@ -176,8 +207,161 @@ body,ul,li {
     bottom: 1px;
     left: 1px;
 }
 
 .scrollbar.vertical {
     top: 1px;
     right: 1px;
 }
+
+
+.mblRoundRectList {
+    margin: 7px 0 16px;
+    padding: 0px;
+    border: 1px solid #ADAAAD;
+    -webkit-border-radius: 8px;
+    -moz-border-radius: 8px;
+    background-color: white;
+}
+
+.mblListItem {
+    list-style-type: none;
+    height: 43px;
+    border-bottom: 1px solid #ADAAAD;
+    line-height: 43px;
+    font-weight: bold;
+    position: relative;
+    color: black;
+}
+
+.mblListItem.mblVariableHeight {
+    line-height: normal;
+    height: auto;
+    padding: 11px 6px 10px 6px;
+}
+
+.mblItemSelected {
+    background-color: #048BF4;
+    background: -webkit-gradient(linear, left top, left bottom, from(#048BF4), to(#005CE5));
+}
+
+.mblRoundRectList .mblListItem:first-child {
+    -webkit-border-top-left-radius: 8px;
+    -webkit-border-top-right-radius: 8px;
+    -moz-border-radius-topleft: 8px;
+    -moz-border-radius-topright: 8px;
+}
+
+.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;
+}
+
+
+/* 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;
+ 
+	display: -moz-box;
+	-moz-box-orient: horizontal;
+	-moz-box-align: stretch;
+ 
+	display: box;
+	box-orient: horizontal;
+	box-align: stretch;
+}
+ 
+.hbox > * {
+	-webkit-box-flex: 0;
+	-moz-box-flex: 0;
+	box-flex: 0;
+	display: block;
+}
+ 
+.vbox {
+	display: -webkit-box;
+	-webkit-box-orient: vertical;
+	-webkit-box-align: stretch;
+ 
+	display: -moz-box;
+	-moz-box-orient: vertical;
+	-moz-box-align: stretch;
+ 
+	display: box;
+	box-orient: vertical;
+	box-align: stretch;
+}
+ 
+.vbox > * {
+	-webkit-box-flex: 0;
+	-moz-box-flex: 0;
+	box-flex: 0;
+	display: block;
+}
+ 
+.spacer {
+	-webkit-box-flex: 1;
+	-moz-box-flex: 1;
+	box-flex: 1;
+}
+ 
+.reverse {
+	-webkit-box-direction: reverse;
+	-moz-box-direction: reverse;
+	box-direction: reverse;
+}
+ 
+.boxFlex0 {
+	-webkit-box-flex: 0;
+	-moz-box-flex: 0;
+	box-flex: 0;
+}
+ 
+.boxFlex1, .boxFlex {
+	-webkit-box-flex: 1;
+	-moz-box-flex: 1;
+	box-flex: 1;
+}
+ 
+.boxFlex2 {
+	-webkit-box-flex: 2;
+	-moz-box-flex: 2;
+	box-flex: 2;
+}
+ 
+.boxGroup1 {
+	-webkit-box-flex-group: 1;
+	-moz-box-flex-group: 1;
+	box-flex-group: 1;
+}
+ 
+.boxGroup2 {
+	-webkit-box-flex-group: 2;
+	-moz-box-flex-group: 2;
+	box-flex-group: 2;
+}
+ 
+.start {
+	-webkit-box-pack: start;
+	-moz-box-pack: start;
+	box-pack: start;
+}
+ 
+.end {
+	-webkit-box-pack: end;
+	-moz-box-pack: end;
+	box-pack: end;
+}
+ 
+.center {
+	-webkit-box-pack: center;
+	-moz-box-pack: center;
+	box-pack: center;
+}
+/* END hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
--- a/client/api/contacts.html
+++ b/client/api/contacts.html
@@ -15,16 +15,32 @@
         /*
          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;
 
+            //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) {
+                                url = identity.image;
+                                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');
@@ -143,27 +159,25 @@
                     <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="">
             </div>
         </div>
     </div>
 
-    <div class="template" data-id="contactDetail">
-        {displayName}
+    <div class="template contactDetail" data-id="contactDetail">
+        <img class="contactPhoto" src="{getPhotoUrl(_)}"> <span class="name">{displayName}</span>
         <ul>
             {identities [}
                 <li>
-                    {image [}
-                        <img src="{}">
-                    {]}
-                    {name}
-                    <ul>
-                        {nickname [} <li>Nickname: {}</li> {]}
+                    <ul class="mblRoundRectList">
+                        {. type rd_key[1][0]}
+                        {. value rd_key[1][1]}
+                        <li class="mblListItem hbox"><span class="idType boxFlex">{type}</span><span class="idValue boxFlex">{value}</span></li>
                     </ul>
                 </li>
             {]}
         </ul>
     </div>
 
 </body>
 </html>
--- a/client/api/scripts/blade/jig.js
+++ b/client/api/scripts/blade/jig.js
@@ -22,25 +22,27 @@ require.def("blade/jig", ["blade/object"
     //Fix unit test: something is wrong with it, says it passes, but
     //with attachData change, the string is actually different now.
     //TODO: for attachData, only generate a new ID when the data value changes,
     //and similarly, only attach the data one time per data value.
     //TODO: ALLOW && AND || in the getobject values?
 
     var jig, commands,
         ostring = Object.prototype.toString,
+        decode = typeof decodeURIComponent === "undefined" ? function () {} : decodeURIComponent,
         startToken = '{',
         endToken = '}',
         rawHtmlToken = '^',
         argSeparator = ' ',
         //First character in an action cannot be something that
         //could be the start of a regular JS property name,
         //or an array indice indicator, [, or the HTML raw output
         //indicator, ^.
         propertyRegExp = /[_\[\^\w]/,
+        defaultArg = '_',
         startTagRegExp = /<\s*\w+/,
         templateCache = {},
         defaultFuncs = {},
         attachData = true,
         dataIdCounter = 0,
         dataRegistry = {};
 
     function isArray(it) {
@@ -59,22 +61,31 @@ require.def("blade/jig", ["blade/object"
         return value ? parseInt(value, 10) : 0;
     }
 
     function getObject(name, data, options) {
         var brackRegExp = /\[([\w0-9\.'":]+)\]/,
             part = name,
             parent = data,
             match, pre, prop, obj, startIndex, endIndex, indices, result,
-            parenStart, parenEnd, func;
+            parenStart, parenEnd, func, funcName;
+
+        //If asking for the default arg it means giving back the current data.
+        if (name === defaultArg) {
+            return data;
+        }
 
         //First check for function call. Function must be globally visible.
         if ((parenStart = name.indexOf('(')) !== -1) {
             parenEnd = name.lastIndexOf(')');
-            func = options.funcs[name.substring(0, parenStart)];
+            funcName = name.substring(0, parenStart);
+            func = options.funcs[funcName];
+            if (!func) {
+                throw new Error('Cannot find function named: ' + funcName + ' for ' + name);
+            }
             return func(getObject(name.substring(parenStart + 1, parenEnd), data, options));
         }
 
         //Now handle regular object references, which could have [] notation.
         while ((match = brackRegExp.exec(part))) {
             prop = match[1].replace(/['"]/g, "");
             pre = part.substring(0, match.index);
 
@@ -202,16 +213,20 @@ require.def("blade/jig", ["blade/object"
             } else {
                 //Command Match!
 
                 //Increment start past the match.
                 start = index + match[0].length;
 
                 //Pull out the command
                 tag = text.substring(index + options.startToken.length, index + match[0].length - options.endToken.length).trim();
+
+                //decode in case the value was in an URL field, like an  href or an img src attribute
+                tag = decode(tag);
+
                 command = tag.charAt(0);
 
                 if (command && !options.propertyRegExp.test(command)) {
                     //Have a template command
                     tag = tag.substring(1).trim();
                 } else {
                     command = '_default_';
                     //Command could contain just the raw HTML indicator.
@@ -240,20 +255,21 @@ require.def("blade/jig", ["blade/object"
                     start += children.templateEnd;
                 } else if (command === ']') {
                     //End of a block. End this recursion, let the parent know
                     //the place where parsing stopped.
                     compiled.templateEnd = start;
                     return compiled;
                 }
 
-                //If this defines a template, save it off
+                //If this defines a template, save it off,
+                //if a comment (starts with /), then ignore it.
                 if (command === '+') {
                     options.templates[args[0]] = children;
-                } else {
+                } else if (command !== '/') {
                     compiled.push({
                         action: options.commands[command].action,
                         useRawHtml: useRawHtml,
                         args: args,
                         children: children
                     });
                 }
             }
--- a/client/api/scripts/rdapi.js
+++ b/client/api/scripts/rdapi.js
@@ -3,16 +3,17 @@
 "use strict";
 
 require.def('rdapi', ['jquery', 'blade/object', 'blade/jig'], function ($, object, jig) {
 
     var rdapi,
         idCounter = 0,
         templateRegistry = {},
         idRegistry = {},
+        jigFunctions = {},
         config = {
             baseUrl: '../',
             apiPath: '_api/',
             saveTemplateData: true
         };
 
     function getHtml(node) {
         var temp = document.createElement('div'),
@@ -50,17 +51,17 @@ require.def('rdapi', ['jquery', 'blade/o
             options = {
                 template: getHtml(options)
             };
         } else if (options.templateId) {
             options.template = templateRegistry[options.templateId].template;
         }
 
         //Add in functions to use in templating
-        var funcs = options.funcs || (options.funcs = {});
+        var funcs = options.funcs || (options.funcs = object.create(jigFunctions));
         object.mixin(funcs, {
             'rdapi.identity': rdapi.identity,
             //TODO: make the date thing better.
             'prettyDate': function (seconds) {
                 return (new Date(seconds * 1000)).toString();
             },
             htmlBody: function (text) {
                 return jig.htmlEscape(text).replace(/\n/g, '<br>');
@@ -214,16 +215,20 @@ require.def('rdapi', ['jquery', 'blade/o
         }
     };
 
 
     rdapi.config = function (cfg) {
         object.mixin(config, cfg, true);
     };
 
+    rdapi.addJigFunctions = function (obj) {
+        object.mixin(jigFunctions, obj);
+    };
+
     rdapi.data = function (id) {
         return jig.data(id);
     };
 
     rdapi.identity = function (id) {
         return idRegistry[id.toString()] || {};
     };