diff --git a/app/views/layouts/chat.rhtml b/app/views/layouts/chat.rhtml index 5c186b2..511f45b 100644 --- a/app/views/layouts/chat.rhtml +++ b/app/views/layouts/chat.rhtml @@ -5,7 +5,7 @@ - <%= javascript_include_tag 'jquery-latest', 'jquery.noconflict', 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.scrollabletab', 'strophejs-1.0.1/strophe', 'application', 'chat', 'jquery.emoticon', '/designs/icons/pidgin/emoticons.js', :cache => 'cache-chat' %> + <%= javascript_include_tag 'jquery-latest', 'jquery.noconflict', 'jquery-ui-1.8.2.custom.min', 'jquery.scrollTo', 'jquery.scrollabletab', 'strophejs-1.0.1/strophe', 'jquery.emoticon', '/designs/icons/pidgin/emoticons.js', 'ba-linkify', 'application', 'chat', :cache => 'cache-chat' %> <%= stylesheet_link_tag noosfero_stylesheets, :cache => 'cache' %> <%= stylesheet_link_tag icon_theme_stylesheet_path %> <%= stylesheet_link_tag theme_stylesheet_path %> diff --git a/public/designs/icons/pidgin/emoticons.js b/public/designs/icons/pidgin/emoticons.js index bea2c90..662d943 100644 --- a/public/designs/icons/pidgin/emoticons.js +++ b/public/designs/icons/pidgin/emoticons.js @@ -1,5 +1,5 @@ /* Copyright (c) 2010 Colivre - www.colivre.coop.br -/* Copyright (c) 2009 Marak Squires - www.maraksquires.com + Copyright (c) 2009 Marak Squires - www.maraksquires.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation @@ -24,93 +24,128 @@ OTHER DEALINGS IN THE SOFTWARE. */ var emoticons = { - "image_path": '/designs/icons/pidgin/pidgin/emotes/default/', - "emoticon": { - "::smile": { - "image": "mean.png", - "emotes": { - ":-)": "", - ":)": "", - ":]": "", - "=]": "", - "=)": "" - } - }, - "::bigSmile": { - "image": "excited.png", - "emotes": { - ":D": "", - "=D": "", - ":-D": "", - "XD": "", - "BD": "" - } - }, - "::shock": { - "image": "shocked.png", - "emotes": { - ":O": "", - ":0": "", - "=O": "", - ":-0": "", - ":-O": "" - - } - }, - "::frown": { - "image": "sad.png", - "emotes": { - ":-(": "", - "=(": "", - ":[": "", - ":<": "", - "=[": "", - ":(": "", - ":-\\": "" - } - }, - "::tongue": { - "image": "tongue.png", - "emotes": { - ":P": "", - "=P": "", - "XP": "", - } - }, - "::bored": { - "image": "thinking.png", - "emotes": { - "=I": "", - ":/": "", - ":-\\": "", - ":|": "" - } - }, - "::wink": { - "image": "wink.png", - "emotes": { - ";-)": "", - ";)": "", - ";]": "" - } - }, - "::love": { - "image": "rose.png", - "emotes": { - "<3": "", - "<3": "", - "S2": "", - ":3": "" - } - } - , - "::confused": { - "image": "confused.png", - "emotes": { - ":S": "", - "=S": "", - ":\?": "" - } - } - } + "image_path": '/designs/icons/pidgin/pidgin/emotes/default/', + "emoticon": { + "::smile": { + "image": "mean.png", + "emotes": { + ":-)": "", + ":)": "", + ":]": "", + "=]": "", + "=)": "" + } + }, + "::bigSmile": { + "image": "excited.png", + "emotes": { + ":D": "", + "=D": "", + ":-D": "" + } + }, + "::shock": { + "image": "shocked.png", + "emotes": { + ":O": "", + ":0": "", + "=O": "", + ":-0": "", + ":-O": "" + } + }, + "::frown": { + "image": "sad.png", + "emotes": { + ":-(": "", + "=(": "", + ":[": "", + ":<": "", + "=[": "", + ":(": "", + ":-\\": "" + } + }, + "::tongue": { + "image": "tongue.png", + "emotes": { + ":P": "", + ":-P": "", + "=P": "" + } + }, + "::bored": { + "image": "thinking.png", + "emotes": { + "=I": "", + ":/": "", + ":-\\": "", + ":|": "" + } + }, + "::wink": { + "image": "wink.png", + "emotes": { + ";-)": "", + ";)": "", + ";]": "" + } + }, + "::love": { + "image": "in_love.png", + "emotes": { + "<3": "", + "<333": "" + } + }, + "::confused": { + "image": "confused.png", + "emotes": { + ":S": "", + "=S": "", + ":\?": "" + } + }, + "::crying": { + "image": "crying.png", + "emotes": { + ":'(": "", + ";*(": "" + } + }, + "::kiss": { + "image": "kiss.png", + "emotes": { + ":-*": "", + ":*": "" + } + }, + "::evil": { + "image": "devil.png", + "emotes": { + ">:)": "", + ">;)": "", + ">:-)": "" + } + }, + "::nolove": { + "image": "love-over.png", + "emotes": { + "3": "" + } + }, + "::praise": { + "image": "victory.png", + "emotes": { + "\\o/": "" + } + }, + "::angel": { + "image": "angel.png", + "emotes": { + "O:-)": "", + "O:)": "" + } + } + } }; diff --git a/public/javascripts/ba-linkify.js b/public/javascripts/ba-linkify.js new file mode 100644 index 0000000..81dae5f --- /dev/null +++ b/public/javascripts/ba-linkify.js @@ -0,0 +1,214 @@ +/*! + * JavaScript Linkify - v0.3 - 6/27/2009 + * http://benalman.com/projects/javascript-linkify/ + * + * Copyright (c) 2009 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + * + * Some regexps adapted from http://userscripts.org/scripts/review/7122 + */ + +// Script: JavaScript Linkify: Process links in text! +// +// *Version: 0.3, Last updated: 6/27/2009* +// +// Project Home - http://benalman.com/projects/javascript-linkify/ +// GitHub - http://github.com/cowboy/javascript-linkify/ +// Source - http://github.com/cowboy/javascript-linkify/raw/master/ba-linkify.js +// (Minified) - http://github.com/cowboy/javascript-linkify/raw/master/ba-linkify.min.js (2.8kb) +// +// About: License +// +// Copyright (c) 2009 "Cowboy" Ben Alman, +// Dual licensed under the MIT and GPL licenses. +// http://benalman.com/about/license/ +// +// About: Examples +// +// This working example, complete with fully commented code, illustrates one way +// in which this code can be used. +// +// Linkify - http://benalman.com/code/projects/javascript-linkify/examples/linkify/ +// +// About: Support and Testing +// +// Information about what browsers this code has been tested in. +// +// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, Chrome, Opera 9.6-10. +// +// About: Release History +// +// 0.3 - (6/27/2009) Initial release + +// Function: linkify +// +// Turn text into linkified html. +// +// Usage: +// +// > var html = linkify( text [, options ] ); +// +// Arguments: +// +// text - (String) Non-HTML text containing links to be parsed. +// options - (Object) An optional object containing linkify parse options. +// +// Options: +// +// callback (Function) - If specified, this will be called once for each link- +// or non-link-chunk with two arguments, text and href. If the chunk is +// non-link, href will be omitted. If unspecified, the default linkification +// callback is used. +// punct_regexp (RegExp) - A RegExp that will be used to trim trailing +// punctuation from links, instead of the default. If set to null, trailing +// punctuation will not be trimmed. +// +// Returns: +// +// (String) An HTML string containing links. + +window.linkify = (function(){ + var + SCHEME = "[a-z\\d.-]+://", + IPV4 = "(?:(?:[0-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.){3}(?:[0-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])", + HOSTNAME = "(?:(?:[^\\s!@#$%^&*()_=+[\\]{}\\\\|;:'\",.<>/?]+)\\.)+", + TLD = "(?:ac|ad|aero|ae|af|ag|ai|al|am|an|ao|aq|arpa|ar|asia|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|biz|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|cat|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|coop|com|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|info|int|in|io|iq|ir|is|it|je|jm|jobs|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mobi|mo|mp|mq|mr|ms|mt|museum|mu|mv|mw|mx|my|mz|name|na|nc|net|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|pro|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|travel|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xn--0zwm56d|xn--11b5bs3a9aj6g|xn--80akhbyknj4f|xn--9t4b11yi5a|xn--deba0ad|xn--g6w251d|xn--hgbk6aj7f53bba|xn--hlcj6aya9esc7a|xn--jxalpdlp|xn--kgbechtv|xn--zckzah|ye|yt|yu|za|zm|zw)", + HOST_OR_IP = "(?:" + HOSTNAME + TLD + "|" + IPV4 + ")", + PATH = "(?:[;/][^#?<>\\s]*)?", + QUERY_FRAG = "(?:\\?[^#<>\\s]*)?(?:#[^<>\\s]*)?", + URI1 = "\\b" + SCHEME + "[^<>\\s]+", + URI2 = "\\b" + HOST_OR_IP + PATH + QUERY_FRAG + "(?!\\w)", + + MAILTO = "mailto:", + EMAIL = "(?:" + MAILTO + ")?[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@" + HOST_OR_IP + QUERY_FRAG + "(?!\\w)", + + URI_RE = new RegExp( "(?:" + URI1 + "|" + URI2 + "|" + EMAIL + ")", "ig" ), + SCHEME_RE = new RegExp( "^" + SCHEME, "i" ), + + quotes = { + "'": "`", + '>': '<', + ')': '(', + ']': '[', + '}': '{', + '»': '«', + '›': '‹' + }, + + default_options = { + callback: function( text, href ) { + return href ? '' + text + '' : text; + }, + punct_regexp: /(?:[!?.,:;'"]|(?:&|&)(?:lt|gt|quot|apos|raquo|laquo|rsaquo|lsaquo);)$/ + }; + + return function( txt, options ) { + options = options || {}; + + // Temp variables. + var arr, + i, + link, + href, + + // Output HTML. + html = '', + + // Store text / link parts, in order, for re-combination. + parts = [], + + // Used for keeping track of indices in the text. + idx_prev, + idx_last, + idx, + link_last, + + // Used for trimming trailing punctuation and quotes from links. + matches_begin, + matches_end, + quote_begin, + quote_end; + + // Initialize options. + for ( i in default_options ) { + if ( options[ i ] === undefined ) { + options[ i ] = default_options[ i ]; + } + } + + // Find links. + while ( arr = URI_RE.exec( txt ) ) { + + link = arr[0]; + idx_last = URI_RE.lastIndex; + idx = idx_last - link.length; + + // Not a link if preceded by certain characters. + if ( /[\/:]/.test( txt.charAt( idx - 1 ) ) ) { + continue; + } + + // Trim trailing punctuation. + do { + // If no changes are made, we don't want to loop forever! + link_last = link; + + quote_end = link.substr( -1 ) + quote_begin = quotes[ quote_end ]; + + // Ending quote character? + if ( quote_begin ) { + matches_begin = link.match( new RegExp( '\\' + quote_begin + '(?!$)', 'g' ) ); + matches_end = link.match( new RegExp( '\\' + quote_end, 'g' ) ); + + // If quotes are unbalanced, remove trailing quote character. + if ( ( matches_begin ? matches_begin.length : 0 ) < ( matches_end ? matches_end.length : 0 ) ) { + link = link.substr( 0, link.length - 1 ); + idx_last--; + } + } + + // Ending non-quote punctuation character? + if ( options.punct_regexp ) { + link = link.replace( options.punct_regexp, function(a){ + idx_last -= a.length; + return ''; + }); + } + } while ( link.length && link !== link_last ); + + href = link; + + // Add appropriate protocol to naked links. + if ( !SCHEME_RE.test( href ) ) { + href = ( href.indexOf( '@' ) !== -1 ? ( !href.indexOf( MAILTO ) ? '' : MAILTO ) + : !href.indexOf( 'irc.' ) ? 'irc://' + : !href.indexOf( 'ftp.' ) ? 'ftp://' + : 'http://' ) + + href; + } + + // Push preceding non-link text onto the array. + if ( idx_prev != idx ) { + parts.push([ txt.slice( idx_prev, idx ) ]); + idx_prev = idx_last; + } + + // Push massaged link onto the array + parts.push([ link, href ]); + }; + + // Push remaining non-link text onto the array. + parts.push([ txt.substr( idx_prev ) ]); + + // Process the array items. + for ( i = 0; i < parts.length; i++ ) { + html += options.callback.apply( window, parts[i] ); + } + + // In case of catastrophic failure, return the original text; + return html || txt; + }; + +})(); \ No newline at end of file diff --git a/public/javascripts/chat.js b/public/javascripts/chat.js index 8973942..b6ca10d 100644 --- a/public/javascripts/chat.js +++ b/public/javascripts/chat.js @@ -50,11 +50,21 @@ jQuery(function($) { $('#' + jid_id).parent('li').remove(); }, + render_body_message: function(body) { + body = $().emoticon(body); + body = linkify(body, { + callback: function(text, href) { + return href ? '' + text + '' : text; + } + }); + return body; + }, + show_message: function (jid, body, who) { jid_id = Jabber.jid_to_id(jid); if (body) { var tab_id = '#' + Jabber.tab_prefix + jid_id; - body = $().emoticon(body); + body = Jabber.render_body_message(body); if ($(tab_id).find('.message').length > 0 && $(tab_id).find('.message:last').hasClass(who)) { $(tab_id).find('.history').find('.message:last').append('
' + body + '
'); } @@ -75,7 +85,7 @@ jQuery(function($) { .replace('%{avatar_url}', '/chat/avatar/' + identifier); $('#' + Jabber.tab_prefix + jid_id).find('.history').append(message_html); } - $(tab_id).find('.history').scrollTo('100%'); + $(tab_id).find('.history').scrollTo({top:'100%', left:'0%'}); if (who === "other" && $(tab_id).find('.history:visible').length == 0) { count_unread_messages(jid_id); } @@ -361,7 +371,7 @@ jQuery(function($) { // TODO notify window close }, show: function(event, ui) { - $(ui.panel).find('.history').scrollTo('100%'); + $(ui.panel).find('.history').scrollTo({top:'100%', left:'0%'}); $(ui.panel).find('textarea').focus(); var jid_id = ui.panel.id.replace('conversation-', ''); count_unread_messages(jid_id, true); diff --git a/public/javascripts/jquery.emoticon.js b/public/javascripts/jquery.emoticon.js index e6cac41..ab007f7 100644 --- a/public/javascripts/jquery.emoticon.js +++ b/public/javascripts/jquery.emoticon.js @@ -44,8 +44,8 @@ RegExp.escape = function(text) { for( var a in emoticons.emoticon ) { emoticon = emoticons.emoticon[a]; for( var emote in emoticon.emotes ) { - emote = RegExp.escape(emote); - newText = newText.replace( new RegExp( emote, 'gi' ), '