Skip to content

Instantly share code, notes, and snippets.

@garyharan
Forked from cheeaun/plugin.privateChat.js
Created December 16, 2009 04:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save garyharan/257574 to your computer and use it in GitHub Desktop.
Save garyharan/257574 to your computer and use it in GitHub Desktop.
// https://cheeaun.talkerapp.com/plugins/82
// jQuery.nano template engine
// http://github.com/trix/nano
(function(c){c.nano=function(d,e){return d.replace(/\{([\w\.]*)}/g,function(a,f){a=f.split(".");var b=e[a.shift()];c.each(a,function(){b=b[this]});return b})}})(jQuery);
var vendorStyles = function(str){
var s = str.split('-');
if (s.length == 4 && s[0] == 'border'){
var value = s[3].split(':')[1];
return str + '-webkit-' + str + '-moz-border-radius-' + s[1] + s[2] + ':' + value + ';';
}
return str + '-moz-' + str + '-webkit-' + str;
};
var $style = $('<style>'
+ '.talkerapp-private-chat-pane{'
+ 'position: fixed; bottom: 0; right: 10px; width: 240px; height: 20em; background-color: #fff; z-index: 100;'
+ vendorStyles('box-shadow: 0 0 10px #666;')
+ vendorStyles('border-top-left-radius: 3px;')
+ vendorStyles('border-top-right-radius: 3px;')
+ '}'
+ '.talkerapp-private-chat-pane.collapsed{'
+ 'height: 24px;'
+ '}'
+ '.talkerapp-private-chat-head{'
+ 'height: 24px; line-height: 24px; font-weight: bold; padding: 0 .5em; color: #fff; background-color: #4091BF; cursor: pointer;'
+ vendorStyles('border-top-left-radius: 3px;')
+ vendorStyles('border-top-right-radius: 3px;')
+ '}'
+ '.talkerapp-private-chat-pane.new-msg .talkerapp-private-chat-head{'
+ 'background-color: #EF9E2D;'
+ '}'
+ '.talkerapp-private-chat-pane .talkerapp-private-chat-head .close{'
+ 'width: 16px; height: 16px; text-align: center; line-height: 16px; position: absolute; top: 4px; right: 4px;'
+ 'color: #fff; text-decoration: none;'
+ vendorStyles('border-radius: 3px;')
+ '}'
+ '.talkerapp-private-chat-pane .talkerapp-private-chat-head .close:hover{'
+ 'background-color: rgba(0,0,0,.2)'
+ '}'
+ '.talkerapp-private-chat-body{'
+ 'position: absolute; top: 24px; left: 0; bottom: 0; right: 0; overflow: hidden;'
+ '}'
+ '.talkerapp-private-chat-body ol{'
+ 'margin: 0; padding: 0; list-style: none; position: absolute; top: 0; left: 0; bottom: 48px; width: 100%; overflow: auto;'
+ '}'
+ '.talkerapp-private-chat-body ol li{'
+ 'margin: 0; padding: 0 .5em; list-style: none; display: block; font-size: .9em; line-height: 1.5em;'
+ '}'
+ '.talkerapp-private-chat-body ol li .talker{'
+ 'font-weight: bold; float: left; margin-right: .5em;'
+ '}'
+ '.talkerapp-private-chat-body ol li.indent{'
+ 'padding-left: 1.5em;'
+ '}'
+ '.talkerapp-private-chat-body ol li.divider{'
+ 'padding: 0; line-height: 0; height: 0; border-top: 1px dotted #ccc; margin: 0 .5em;'
+ '}'
+ '.talkerapp-private-chat-msgbox{'
+ 'position: absolute; left: 0; bottom: 0; right: 0; overflow: hidden; height: 48px;'
+ '}'
+ '.talkerapp-private-chat-msgbox textarea{'
+ 'position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; resize: none;'
+ '}'
+ '.message.me.private{display: none;}'
+ '</style>');
$('head').append($style);
var chatItemHTML = '<li>'
+ '<div class="talker">{talkerNick}:</div>'
+ '<div class="msg">{talkerMsg}</div>'
+ '</li>';
var chatItemHTML2 = '<li class="indent">'
+ '<div class="msg">{talkerMsg}</div>'
+ '</li>';
var chatPaneHTML = '<div class="talkerapp-private-chat-pane" data-talker="{talkerID}">'
+ '<div class="talkerapp-private-chat-head">{talkerID} <a href="#" class="close">&#215;</a></div>'
+ '<div class="talkerapp-private-chat-body">'
+ '<ol class="talkerapp-private-chat-list">'
+ '</ol>'
+ '<div class="talkerapp-private-chat-msgbox">'
+ '<textarea></textarea>'
+ '</div>'
+ '</div>'
+ '</div>';
var chatDividerHTML = '<li class="divider"></li>';
var talkers = [];
var me = Talker.currentUser.name;
var paneWidth = 240;
var paneSpace = 10;
var url_expression = /(https?:\/\/|www\.)[^\s<]*/gi;
var protocol_expression = /^(http|https|ftp|ftps|ssh|irc|mms|file|about|mailto|xmpp):\/\//;
var formatMsg = function(msg){
if (!msg) return;
return msg.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(url_expression, function(l){
return '<a href="'
+ (!l.match(protocol_expression) ? 'http://' : '') + l
+ '" target="_blank">' + l + '</a>';
});
};
var insertMsg = function(id, talker, msg){
if (id == me) return; // don't talk to yourself, ok?
var inTalkers = ($.inArray(id, talkers) != -1);
var pos = talkers.length;
if (!inTalkers){
talkers.push(id);
var html = $.nano(chatPaneHTML, {
talkerID: id
});
$('body').append(html);
}
var pane = $('.talkerapp-private-chat-pane[data-talker=' + id + ']');
if (!inTalkers) pane.css('right', paneSpace+(paneSpace+paneWidth)*pos);
if (pane.hasClass('collapsed')){
pane.addClass('new-msg');
} else {
pane.find('.talkerapp-private-chat-msgbox textarea').focus();
}
if (!msg) return;
var lastTalker = pane.data('lastTalker');
var html = $.nano((lastTalker != talker) ? chatItemHTML : chatItemHTML2, {
talkerNick: talker,
talkerMsg: formatMsg(msg)
});
pane.find('ol').append(html);
pane.data('lastTalker', talker);
// scroll to bottom
var body = pane.find('.talkerapp-private-chat-body ol')[0];
body.scrollTop = body.scrollHeight;
};
// Received private messages
plugin.onMessageReceived = function(e){
if (!e || !e.private || e.type != 'message') return;
var talker = e.user.name;
var msg = e.content;
insertMsg(talker, talker, msg);
return false;
};
// Send private messages
plugin.onMessageSent = function(e){
if (!e || e.type != 'command' || e.command != 'msg' || !e.args || e.args.length <= 1) return;
var args = e.args.slice();
var talker = args[0].replace(/^@/, '');
args.shift();
var msg = args.join(' ');
insertMsg(talker, me, msg);
return false;
}
var offline = false;
var disableTextareas = function(){
var users = _.map(Talker.getRoomUsers(), function(user){
return user.name;
});
var offUsers = [];
for (var i=0, l=talkers.length; i<l; i++){
if ($.inArray(talkers[i], users) == -1) offUsers.push(talkers[i]);
}
var panes = $('.talkerapp-private-chat-pane');
panes.find('textarea').removeAttr('disabled');
for (var j=0, l=offUsers.length; j<l; j++){
panes.filter('[data-talker=' + offUsers[j] + ']').find('textarea').attr('disabled', true);
}
};
plugin.onOpen = function(){
offline = false;
disableTextareas();
};
plugin.onClose = function(){
offline = true;
}
plugin.onJoin = plugin.onLeave = disableTextareas;
$('.talkerapp-private-chat-head').live('click', function(){
var pane = $(this).parent('.talkerapp-private-chat-pane');
if (pane.hasClass('collapsed')){
pane.removeClass('collapsed');
pane.removeClass('new-msg');
pane.find('.talkerapp-private-chat-msgbox textarea').focus();
} else {
pane.addClass('collapsed');
var ol = pane.find('ol');
var divider = ol.find('li.divider');
ol.append(divider.length ? divider : chatDividerHTML);
}
});
$('.talkerapp-private-chat-msgbox textarea').live('keydown', function(e){
e.stopPropagation();
var textarea = $(this);
if (e.keyCode == 13){ // enter
e.preventDefault();
var val = $.trim(textarea.val());
if (val !== ''){
var talker = textarea.parents('.talkerapp-private-chat-pane').attr('data-talker');
Talker.trigger('MessageSend', {
type: 'message',
content: '/msg ' + talker + ' ' + val
});
textarea.val('').focus();
}
}
});
$('#people li').live('dblclick', function(){
var el = $(this);
var talker = $.trim(el.text());
insertMsg(talker, me, null);
});
$('.talkerapp-private-chat-head .close').live('click', function(){
if (confirm('Are you sure? All chat messages are NOT saved.')){
var el = $(this);
var pane = el.parents('.talkerapp-private-chat-pane');
var talker = pane.attr('data-talker');
for (var i = talkers.length; i--; i){
if (talkers[i] === talker) talkers.splice(i, 1);
}
pane.nextAll('.talkerapp-private-chat-pane').each(function(){
$(this).animate({
right: '-=' + (paneWidth+paneSpace)
});
});
pane.remove();
}
return false;
})
$('.talkerapp-private-chat-pane textarea').live('mousedown keydown click', function(){
if (offline) return false;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment