From 02a4212494e1d42f50d8fb1c8daede32ae9cb744 Mon Sep 17 00:00:00 2001 From: Zaran Date: Thu, 12 May 2011 01:37:39 +0200 Subject: * Split the js code and css code into several files for easier coding (they will be minified and concatenated in deployment anyway) * Add a light tooltip jquery plugin. Simple tooltip test on roster contacts * Some css changes (WIP) * Some documentation cleanup in js --- webclient/index.html | 6 +- webclient/lib/alias.js | 144 ++++--------------------------- webclient/lib/jquery.tabs.js | 121 ++++++++++++++++++++++++++ webclient/lib/jquery.tipTip.js | 191 +++++++++++++++++++++++++++++++++++++++++ webclient/style/alias.css | 89 +++---------------- webclient/style/tabs.css | 66 ++++++++++++++ webclient/style/tipTip.css | 125 +++++++++++++++++++++++++++ 7 files changed, 538 insertions(+), 204 deletions(-) create mode 100644 webclient/lib/jquery.tabs.js create mode 100644 webclient/lib/jquery.tipTip.js create mode 100644 webclient/style/tabs.css create mode 100644 webclient/style/tipTip.css diff --git a/webclient/index.html b/webclient/index.html index 777e907..745c4ff 100644 --- a/webclient/index.html +++ b/webclient/index.html @@ -7,11 +7,15 @@ Alias - + + + + + diff --git a/webclient/lib/alias.js b/webclient/lib/alias.js index bae01cc..521b492 100644 --- a/webclient/lib/alias.js +++ b/webclient/lib/alias.js @@ -28,7 +28,7 @@ var Alias = { /** * Return the status of a contact * @param {jQuery} contact The contact - * @return {Int} The status' number + * @return {Number} The status' number * @see Alias.Status */ getPresence: function(contact) { @@ -117,8 +117,20 @@ var Alias = { } else $('#roster ul').append(contact); + + // init tooltip + contact.tipTip({ + content: "", + defaultPosition: "right", + keepAlive: true + }); }, + /** + * Update the roster when receiving a presence stanza + * @param {XMLElement} presence The presence stanza + * @returns {Boolean} + */ onPresence: function(presence) { var who = $(presence).attr('from'); var type = $(presence).attr('type'); @@ -150,7 +162,7 @@ var Alias = { /** * Rebuild the contact list when receiving a roster iq - * @param iq + * @param {XMLElement} iq * @return {Boolean} */ onRoster: function(iq) { @@ -175,7 +187,6 @@ var Alias = { /** * Called when the status of Strophe's connection changes. * This function is passed to the Strophe's connect function - * * @param {Int} status The new status */ onStatusChanged: function(status) { @@ -195,7 +206,9 @@ var Alias = { }, /** - * Alias initialization after connection + * Initialization after connection + * + * Set the interface and the handlers */ onConnect: function() { Alias.getRoster(); @@ -305,129 +318,6 @@ var Alias = { }; -/** - * Light jQuery tab plugin - * - * the html structure is: - * - *
- * - *
- * Content 1 - *
- *
- */ -(function( $ ){ - - var methods = { - - /** - * Initialise the general tab area - * @return this (to preserve chainability) - */ - init: function() { - var tabs = this; - this.find('ul.tabbar li').bind('click.tabs', function(event){ - event.preventDefault(); - tabs.tabs('select',$(this).find('a').attr('href')); - }); - this.data('tabs',{}); - return this; - }, - - /** - * Select a tab - * @param {String} id The tab id with # - * @return this - */ - select: function(id) { - var selectedId = this.data('tabs').selected; - - if ( selectedId == id) { - return this; - } - - this.find('ul.tabbar li a[href="' + selectedId + '"]').parent().removeClass('selected'); - this.find('ul.tabbar li a[href="' + id + '"]').parent().addClass('selected'); - $(selectedId).hide(); - $(id).show(); - this.data('tabs').selected = id; - return this; - }, - - /** - * Add a tab - * @param {String} name The tab Title - * @param {String} id The tab id without # - * @pram {Bool} remove Wether the tab should be closable - * return this - */ - add: function(name, id, remove) { - var tabs = this; - var li = $('
  • ' + name +'
  • '); - - if ( remove ) { - li.append(''); - li.find('.tab-close').bind('click', function() { - tabs.tabs('remove', '#'+id); - }); - } - - li.bind('click.tabs',function(event){ - event.preventDefault(); - tabs.tabs('select',$(this).find('a').attr('href')); - }); - $(this).find('ul.tabbar').append(li); - $(this).append('
    '); - return this; - }, - - /** - * Test if a tab exists - * @param {String} id The tab id with # - * @return {Bool} - */ - exist: function(id) { - return (this.find('ul.tabbar li a[href="' + id + '"]').length != 0); - }, - - /** - * Remove a tab - * @param {String} id The tab id with # - * @return this - */ - remove: function(id) { - this.find('ul.tabbar li a[href="' + id + '"]').parent().remove(); - $(id).remove(); - - if (this.data('tabs').selected == id) { - var first = this.find('ul.tabbar li:first a').attr('href'); - this.tabs('select', first); - } - } - }; - - /* - * Register the 'tabs' method to the jQuery objects - * the first argument of this method is the submethod - * you want to call - */ - $.fn.tabs = function(method) { - if ( methods[method] ) { - return methods[method].apply(this, Array.prototype.slice - .call(arguments, 1)); - } else if ( typeof method === 'object' || !method ) { - return methods.init.apply(this, arguments); - } else { - $.error('Method ' + method + ' does not exist on jQuery.tabs'); - } - }; - -})(jQuery); - - function log(msg, color) { $('#log').append($('
    ').css('background-color', color).text(msg)); } diff --git a/webclient/lib/jquery.tabs.js b/webclient/lib/jquery.tabs.js new file mode 100644 index 0000000..7898afa --- /dev/null +++ b/webclient/lib/jquery.tabs.js @@ -0,0 +1,121 @@ +/** + * Light jQuery tab plugin + * + * the html structure is: + * + *
    + * + *
    + * Content 1 + *
    + *
    + */ +(function( $ ){ + + var methods = { + + /** + * Initialise the general tab area + * @return this (to preserve chainability) + */ + init: function() { + var tabs = this; + this.find('ul.tabbar li').bind('click.tabs', function(event){ + event.preventDefault(); + tabs.tabs('select',$(this).find('a').attr('href')); + }); + this.data('tabs',{}); + return this; + }, + + /** + * Select a tab + * @param {String} id The tab id with # + * @return this + */ + select: function(id) { + var selectedId = this.data('tabs').selected; + + if ( selectedId == id) { + return this; + } + + this.find('ul.tabbar li a[href="' + selectedId + '"]').parent().removeClass('selected'); + this.find('ul.tabbar li a[href="' + id + '"]').parent().addClass('selected'); + $(selectedId).hide(); + $(id).show(); + this.data('tabs').selected = id; + return this; + }, + + /** + * Add a tab + * @param {String} name The tab Title + * @param {String} id The tab id without # + * @pram {Bool} remove Wether the tab should be closable + * return this + */ + add: function(name, id, remove) { + var tabs = this; + var li = $('
  • ' + name +'
  • '); + + if ( remove ) { + li.append(''); + li.find('.tab-close').bind('click', function() { + tabs.tabs('remove', '#'+id); + }); + } + + li.bind('click.tabs',function(event){ + event.preventDefault(); + tabs.tabs('select',$(this).find('a').attr('href')); + }); + $(this).find('ul.tabbar').append(li); + $(this).append('
    '); + return this; + }, + + /** + * Test if a tab exists + * @param {String} id The tab id with # + * @return {Bool} + */ + exist: function(id) { + return (this.find('ul.tabbar li a[href="' + id + '"]').length != 0); + }, + + /** + * Remove a tab + * @param {String} id The tab id with # + * @return this + */ + remove: function(id) { + this.find('ul.tabbar li a[href="' + id + '"]').parent().remove(); + $(id).remove(); + + if (this.data('tabs').selected == id) { + var first = this.find('ul.tabbar li:first a').attr('href'); + this.tabs('select', first); + } + } + }; + + /* + * Register the 'tabs' method to the jQuery objects + * the first argument of this method is the submethod + * you want to call + */ + $.fn.tabs = function(method) { + if ( methods[method] ) { + return methods[method].apply(this, Array.prototype.slice + .call(arguments, 1)); + } else if ( typeof method === 'object' || !method ) { + return methods.init.apply(this, arguments); + } else { + $.error('Method ' + method + ' does not exist on jQuery.tabs'); + } + }; + +})(jQuery); \ No newline at end of file diff --git a/webclient/lib/jquery.tipTip.js b/webclient/lib/jquery.tipTip.js new file mode 100644 index 0000000..7eacf35 --- /dev/null +++ b/webclient/lib/jquery.tipTip.js @@ -0,0 +1,191 @@ + /* + * TipTip + * Copyright 2010 Drew Wilson + * www.drewwilson.com + * code.drewwilson.com/entry/tiptip-jquery-plugin + * + * Version 1.3 - Updated: Mar. 23, 2010 + * + * This Plug-In will create a custom tooltip to replace the default + * browser tooltip. It is extremely lightweight and very smart in + * that it detects the edges of the browser window and will make sure + * the tooltip stays within the current window size. As a result the + * tooltip will adjust itself to be displayed above, below, to the left + * or to the right depending on what is necessary to stay within the + * browser window. It is completely customizable as well via CSS. + * + * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function($){ + $.fn.tipTip = function(options) { + var defaults = { + activation: "hover", + keepAlive: false, + maxWidth: "200px", + edgeOffset: 3, + defaultPosition: "bottom", + delay: 400, + fadeIn: 200, + fadeOut: 200, + attribute: "title", + content: false, // HTML or String to fill TipTIp with + enter: function(){}, + exit: function(){} + }; + var opts = $.extend(defaults, options); + + // Setup tip tip elements and render them to the DOM + if($("#tiptip_holder").length <= 0){ + var tiptip_holder = $('
    '); + var tiptip_content = $('
    '); + var tiptip_arrow = $('
    '); + $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('
    '))); + } else { + var tiptip_holder = $("#tiptip_holder"); + var tiptip_content = $("#tiptip_content"); + var tiptip_arrow = $("#tiptip_arrow"); + } + + return this.each(function(){ + var org_elem = $(this); + if(opts.content){ + var org_title = opts.content; + } else { + var org_title = org_elem.attr(opts.attribute); + } + if(org_title != ""){ + if(!opts.content){ + org_elem.removeAttr(opts.attribute); //remove original Attribute + } + var timeout = false; + + if(opts.activation == "hover"){ + org_elem.hover(function(){ + active_tiptip(); + }, function(){ + if(!opts.keepAlive){ + deactive_tiptip(); + } + }); + if(opts.keepAlive){ + tiptip_holder.hover(function(){}, function(){ + deactive_tiptip(); + }); + } + } else if(opts.activation == "focus"){ + org_elem.focus(function(){ + active_tiptip(); + }).blur(function(){ + deactive_tiptip(); + }); + } else if(opts.activation == "click"){ + org_elem.click(function(){ + active_tiptip(); + return false; + }).hover(function(){},function(){ + if(!opts.keepAlive){ + deactive_tiptip(); + } + }); + if(opts.keepAlive){ + tiptip_holder.hover(function(){}, function(){ + deactive_tiptip(); + }); + } + } + + function active_tiptip(){ + opts.enter.call(this); + tiptip_content.html(org_title); + tiptip_holder.hide().removeAttr("class").css("margin","0"); + tiptip_arrow.removeAttr("style"); + + var top = parseInt(org_elem.offset()['top']); + var left = parseInt(org_elem.offset()['left']); + var org_width = parseInt(org_elem.outerWidth()); + var org_height = parseInt(org_elem.outerHeight()); + var tip_w = tiptip_holder.outerWidth(); + var tip_h = tiptip_holder.outerHeight(); + var w_compare = Math.round((org_width - tip_w) / 2); + var h_compare = Math.round((org_height - tip_h) / 2); + var marg_left = Math.round(left + w_compare); + var marg_top = Math.round(top + org_height + opts.edgeOffset); + var t_class = ""; + var arrow_top = ""; + var arrow_left = Math.round(tip_w - 12) / 2; + + if(opts.defaultPosition == "bottom"){ + t_class = "_bottom"; + } else if(opts.defaultPosition == "top"){ + t_class = "_top"; + } else if(opts.defaultPosition == "left"){ + t_class = "_left"; + } else if(opts.defaultPosition == "right"){ + t_class = "_right"; + } + + var right_compare = (w_compare + left) < parseInt($(window).scrollLeft()); + var left_compare = (tip_w + left) > parseInt($(window).width()); + + if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){ + t_class = "_right"; + arrow_top = Math.round(tip_h - 13) / 2; + arrow_left = -12; + marg_left = Math.round(left + org_width + opts.edgeOffset); + marg_top = Math.round(top + h_compare); + } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){ + t_class = "_left"; + arrow_top = Math.round(tip_h - 13) / 2; + arrow_left = Math.round(tip_w); + marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5)); + marg_top = Math.round(top + h_compare); + } + + var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop()); + var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0; + + if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){ + if(t_class == "_top" || t_class == "_bottom"){ + t_class = "_top"; + } else { + t_class = t_class+"_top"; + } + arrow_top = tip_h; + marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset)); + } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){ + if(t_class == "_top" || t_class == "_bottom"){ + t_class = "_bottom"; + } else { + t_class = t_class+"_bottom"; + } + arrow_top = -12; + marg_top = Math.round(top + org_height + opts.edgeOffset); + } + + if(t_class == "_right_top" || t_class == "_left_top"){ + marg_top = marg_top + 5; + } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){ + marg_top = marg_top - 5; + } + if(t_class == "_left_top" || t_class == "_left_bottom"){ + marg_left = marg_left + 5; + } + tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"}); + tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class); + + if (timeout){ clearTimeout(timeout); } + timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay); + } + + function deactive_tiptip(){ + opts.exit.call(this); + if (timeout){ clearTimeout(timeout); } + tiptip_holder.fadeOut(opts.fadeOut); + } + } + }); + } +})(jQuery); \ No newline at end of file diff --git a/webclient/style/alias.css b/webclient/style/alias.css index 9e96f88..c3945ba 100644 --- a/webclient/style/alias.css +++ b/webclient/style/alias.css @@ -155,8 +155,8 @@ input #header { margin: 0px; - margin-bottom: 15px; - background-image: -moz-linear-gradient(top center, white, #AEB2B1); + margin-bottom: 0px; + background-image: -moz-linear-gradient(top center, #F4F4F4, #C1C1C1); background: -webkit-gradient(linear, left top, left bottom, from(#F6F6F6), to(#D9D9D9)); border-bottom: 1px solid #CDCDCD; box-shadow: 0px 5px 10px #434343; @@ -176,11 +176,10 @@ input #left { margin: 0px; - margin-right: 2%; float: left; - width: 20%; + width: 22%; background-color: white; - height: 88%; + height: 95%; display: none; } @@ -188,7 +187,7 @@ input { float: left; width: 78%; - height: 88%; + height: 95%; display: none; background-color: white; padding: 0px; @@ -199,74 +198,6 @@ input padding: 0px; } -ul.tabbar{ - background-color: #E9E9E9; - border-bottom: 1px solid #9C9C9C; - border-top: 1px solid white; - padding: 0px; - margin: 0px; - list-style-type: none; - height: 45px; -} - -ul.tabbar > li{ - background-color: #B6B6B6; - padding: 10px; - padding-right: 5px; - margin: 0px; - margin-left: 0.5em; - height: 20px; - float: left; - display: block; - margin-top: 4px; -} - -ul.tabbar > li.selected{ - border-bottom: 1px solid white; - border-left: 1px solid #9C9C9C; - border-top: 1px solid #9C9C9C; - border-right: 1px solid #9C9C9C; - background-color: white; -} - -ul.tabbar > li:hover{ - background-color: #3058A3; - color: white; - cursor: pointer; -} - -ul.tabbar > li > span.tab-close{ - display: block; - width: 15px; - height: 15px; - float: right; - margin-left: 5px; - margin-top: 2px; - background-image: url("images/cross.png"); -} - -ul.tabbar > li:hover > span.tab-close{ - background-image: url("images/cross2.png"); -} - -ul.tabbar > li > a{ - color: inherit; -} - -ul.tabbar > li > a:hover{ - text-decoration: none; -} - -ul.tabbar > li > a:focus{ - border: none; -} - -.tab{ - padding: 10px; - height: 100%; - display: none; -} - .chat-messages{ height: 80%; width: 100%; @@ -317,7 +248,7 @@ ul.tabbar > li > a:focus{ .roster-contact { - -moz-transition-property: background-color, box-shadow; + -moz-transition-property: background-color; -moz-transition-duration: 0.5s; -webkit-transition-property: background-color; -webkit-transition-duration: 1s; @@ -331,7 +262,6 @@ ul.tabbar > li > a:focus{ .roster-contact:hover { background-color: #E5E9EE; - box-shadow: 5px 0px 5px #888; } .roster-name @@ -349,6 +279,13 @@ ul.tabbar > li > a:focus{ background-color: #E3E3E3; } +#tiptip_holder ul +{ + padding: 0; + margin: 0; + margin-left:10px; +} + #status { margin: 0px; diff --git a/webclient/style/tabs.css b/webclient/style/tabs.css new file mode 100644 index 0000000..2d12003 --- /dev/null +++ b/webclient/style/tabs.css @@ -0,0 +1,66 @@ +ul.tabbar{ + background-color: #E9E9E9; + border-bottom: 1px solid #9C9C9C; + border-top: 1px solid white; + padding: 0px; + margin: 0px; + list-style-type: none; + height: 35px; +} + +ul.tabbar > li{ + background-color: #B6B6B6; + padding: 5px; + margin: 0px; + margin-left: 0.5em; + height: 20px; + float: left; + display: block; + margin-top: 4px; +} + +ul.tabbar > li.selected{ + border-bottom: 1px solid white; + border-left: 1px solid #9C9C9C; + border-top: 1px solid #9C9C9C; + border-right: 1px solid #9C9C9C; + background-color: white; +} + +ul.tabbar > li:hover{ + background-color: #3058A3; + color: white; + cursor: pointer; +} + +ul.tabbar > li > span.tab-close{ + display: block; + width: 15px; + height: 15px; + float: right; + margin-left: 5px; + margin-top: 2px; + background-image: url("images/cross.png"); +} + +ul.tabbar > li:hover > span.tab-close{ + background-image: url("images/cross2.png"); +} + +ul.tabbar > li > a{ + color: inherit; +} + +ul.tabbar > li > a:hover{ + text-decoration: none; +} + +ul.tabbar > li > a:focus{ + border: none; +} + +.tab{ + padding: 10px; + height: 100%; + display: none; +} diff --git a/webclient/style/tipTip.css b/webclient/style/tipTip.css new file mode 100644 index 0000000..70411d6 --- /dev/null +++ b/webclient/style/tipTip.css @@ -0,0 +1,125 @@ +/* TipTip CSS - Version 1.2 */ + +/** structure + +
    +
    +
    +
    +
    +
    +
    + +*/ + +#tiptip_holder { + display: none; + position: absolute; + top: 0; + left: 0; + z-index: 99999; +} + +#tiptip_holder.tip_top { + padding-bottom: 5px; +} + +#tiptip_holder.tip_bottom { + padding-top: 5px; +} + +#tiptip_holder.tip_right { + padding-left: 5px; +} + +#tiptip_holder.tip_left { + padding-right: 5px; +} + +#tiptip_content { + font-size: 11px; + color: #fff; + text-shadow: 0 0 2px #000; + padding: 4px 8px; + border: 1px solid rgba(255,255,255,0.25); + background-color: rgb(25,25,25); + background-color: rgba(25,25,25,0.92); + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(transparent), to(#000)); + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + box-shadow: 0 0 3px #555; + -webkit-box-shadow: 0 0 3px #555; + -moz-box-shadow: 0 0 3px #555; +} + +#tiptip_arrow, #tiptip_arrow_inner { + position: absolute; + border-color: transparent; + border-style: solid; + border-width: 6px; + height: 0; + width: 0; +} + +#tiptip_holder.tip_top #tiptip_arrow { + border-top-color: #fff; + border-top-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_bottom #tiptip_arrow { + border-bottom-color: #fff; + border-bottom-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_right #tiptip_arrow { + border-right-color: #fff; + border-right-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_left #tiptip_arrow { + border-left-color: #fff; + border-left-color: rgba(255,255,255,0.35); +} + +#tiptip_holder.tip_top #tiptip_arrow_inner { + margin-top: -7px; + margin-left: -6px; + border-top-color: rgb(25,25,25); + border-top-color: rgba(25,25,25,0.92); +} + +#tiptip_holder.tip_bottom #tiptip_arrow_inner { + margin-top: -5px; + margin-left: -6px; + border-bottom-color: rgb(25,25,25); + border-bottom-color: rgba(25,25,25,0.92); +} + +#tiptip_holder.tip_right #tiptip_arrow_inner { + margin-top: -6px; + margin-left: -5px; + border-right-color: rgb(25,25,25); + border-right-color: rgba(25,25,25,0.92); +} + +#tiptip_holder.tip_left #tiptip_arrow_inner { + margin-top: -6px; + margin-left: -7px; + border-left-color: rgb(25,25,25); + border-left-color: rgba(25,25,25,0.92); +} + +/* Webkit Hacks */ +@media screen and (-webkit-min-device-pixel-ratio:0) { + #tiptip_content { + padding: 4px 8px 5px 8px; + background-color: rgba(45,45,45,0.88); + } + #tiptip_holder.tip_bottom #tiptip_arrow_inner { + border-bottom-color: rgba(45,45,45,0.88); + } + #tiptip_holder.tip_top #tiptip_arrow_inner { + border-top-color: rgba(20,20,20,0.92); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2