patashala/assets/js/neon-chat.js

859 lines
18 KiB
JavaScript
Raw Normal View History

/**
* Chat Plugin
*
* Created by: Arlind Nushi
*
* www.laborator.co
*/
var neonChat = neonChat || {
$current_user: null,
isOpen: false,
chat_history: [],
statuses: {
online: {class: 'is-online', order: 1, label: 'Online'},
offline: {class: 'is-offline', order: 4, label: 'Offline'},
idle: {class: 'is-idle', order: 3, label: 'Idle'},
busy: {class: 'is-busy', order: 2, label: 'Busy'}
}
};
;(function($, window, undefined)
{
"use strict";
var $chat = $("#chat"),
$chat_inner = $chat.find('.chat-inner'),
$chat_badge = $chat.find('.badge').add($('.chat-notifications-badge')),
$conversation_window = $chat.find(".chat-conversation"),
$conversation_header = $conversation_window.find(".conversation-header"),
$conversation_body = $conversation_window.find('.conversation-body'),
$textarea = $conversation_window.find('.chat-textarea textarea'),
sidebar_default_is_open = ! $(".page-container").hasClass('sidebar-collapsed');
$.extend(neonChat, {
init: function()
{
// Conversation Close
$conversation_window.on('click', '.conversation-close', neonChat.close);
$("body").on('click', '.chat-close', function(ev)
{
ev.preventDefault();
var animate = $(this).is('[data-animate]');
neonChat.hideChat(animate);
});
$("body").on('click', '.chat-open', function(ev)
{
ev.preventDefault();
var animate = $(this).is('[data-animate]');
neonChat.showChat(animate);
});
// Texarea
$textarea.keydown(function(e)
{
if(e.keyCode == 13 && !e.shiftKey)
{
e.preventDefault();
neonChat.submitMessage();
return false;
}
else
if(e.keyCode == 27)
{
neonChat.close();
}
});
$chat.on('click', '.chat-group a', function(ev)
{
ev.preventDefault();
var $chat_user = $(this);
if($chat_user.hasClass('active'))
{
neonChat.close();
}
else
{
neonChat.open($chat_user);
}
});
$chat.find('.chat-group a').each(function(i, el)
{
var $this = $(el);
$this.append('<span class="badge badge-info is-hidden">0</span>');
});
neonChat.refreshUserIds();
neonChat.orderGroups();
neonChat.prefetchMessages();
neonChat.countUnreadMessages();
neonChat.puffUnreads();
// Chat
if($chat.hasClass('fixed') && $chat_inner.length && $.isFunction($.fn.niceScroll))
{
$chat.find('.chat-inner').niceScroll({
cursorcolor: '#454a54',
cursorborder: '1px solid #454a54',
railpadding: {right: 3},
railalign: 'right',
cursorborderradius: 1
});
}
// Chat Toggle
$("body").on('click', '[data-toggle="chat"]', function(ev)
{
ev.preventDefault();
var $this = $(this),
with_animation = $this.is('[data-animate]'),
collapse_sidebar = $this.is('[data-collapse-sidebar]');
neonChat.toggleChat(with_animation, collapse_sidebar);
});
},
open: function($user_link)
{
this.refreshUserIds();
if(typeof $user_link == 'string')
{
$user_link = $($user_link);
}
// Set Active Class
$chat.find('.chat-group a').not($user_link).removeClass('active');
$user_link.addClass('active');
// Chat Header
var user_status = this.statuses[ this.chat_history[$user_link.attr('id')].status ];
$conversation_header.find('.display-name').html($user_link.find('em').text());
if(user_status)
{
$conversation_header.find('.user-status').attr('class', 'user-status ' + user_status.class);
$conversation_header.find('small').html(user_status.label);
}
$conversation_window.show();
$textarea.val('');
this.updateScrollbars();
this.updateConversationOffset($user_link);
$textarea.focus();
this.$current_user = $user_link;
this.isOpen = true;
this.renderMessages(this.$current_user.attr('id'));
this.resetUnreads(this.$current_user.attr('id'));
this.puffUnreadsAll();
},
close: function()
{
$chat.find('.chat-group a').removeClass('active');
$conversation_window.hide().css({top: 0, opacity: 0});
$conversation_body.find('li.unread').removeClass('unread');
this.$current_user = null;
this.isOpen = false;
return false;
},
updateScrollbars: function()
{
scrollToBottom('#chat .chat-conversation .conversation-body');
},
updateConversationOffset: function($el)
{
var top_h = $conversation_window.find('.conversation-body').position().top + 1,
offset = $el.position().top - top_h,
minus = 0,
con_h = $conversation_window.height(),
win_h = $(window).height();
if($chat.hasClass('fixed') && offset + con_h > win_h)
{
minus = offset + con_h - win_h;
}
if($(".page-container.horizontal-menu").length)
{
minus += $(".page-container.horizontal-menu .navbar").height();
}
offset -= minus;
$conversation_window.transition({
top: offset,
opacity: 1
});
},
getChatHistoryLength: function()
{
var max_chat_history = parseInt($chat.data('max-chat-history'), 10);
if( ! max_chat_history || max_chat_history < 1)
{
max_chat_history = 25;
}
return max_chat_history;
},
submitMessage: function() // Submit whats on textarea
{
var msg = $.trim($textarea.val());
$textarea.val('');
if(this.isOpen && this.$current_user)
{
var id = this.$current_user.uniqueId().attr('id');
this.pushMessage(id, msg.replace( /<.*?>/g, '' ), $chat.data('current-user'), new Date());
this.renderMessages(id);
}
},
refreshUserIds: function()
{
$('#chat .chat-group a').each(function(i, el)
{
var $this = $(el),
$status = $this.find('.user-status');
$this.uniqueId();
var id = $this.attr('id');
if(typeof neonChat.chat_history[id] == 'undefined')
{
var status = $this.data('status');
if( ! status)
{
for(var i in neonChat.statuses)
{
if($status.hasClass(neonChat.statuses[i].class))
{
status = i;
break;
}
}
}
neonChat.chat_history[id] = {
$el: $this,
messages: [],
unreads: 0,
status: status
};
}
});
},
pushMessage: function(id, msg, from, time, fromOpponent, unread)
{
if(id && msg)
{
this.refreshUserIds();
var max_chat_history = this.getChatHistoryLength();
if(this.chat_history[id].messages.length >= max_chat_history)
{
this.chat_history[id].messages = this.chat_history[id].messages.reverse().slice(0, max_chat_history - 1).reverse();
}
this.chat_history[id].messages.push({
message: msg,
from: from,
time: time,
fromOpponent: fromOpponent,
unread: unread
});
if(unread)
{
this.puffUnreadsAll();
}
this.puffUnreads();
}
},
renderMessages: function(id, slient)
{
if(typeof this.chat_history[id] != 'undefined')
{
$conversation_body.html('');
for(var i in this.chat_history[id].messages)
{
var entry = this.chat_history[id].messages[i],
$entry = $('<li><span class="user"></span><p></p><span class="time"></span></li>'),
date = entry.time,
date_formated = date;
if(typeof date == 'object')
{
var hour = date.getHours(),
hour = (hour < 10 ? "0" : "") + hour,
min = date.getMinutes(),
min = (min < 10 ? "0" : "") + min,
sec = date.getSeconds();
sec = (sec < 10 ? "0" : "") + sec;
date_formated = hour + ':' + min;
}
// Populate message DOM
$entry.find('.user').html(entry.from);
$entry.find('p').html(entry.message.replace(/\n/g, '<br>'));
$entry.find('.time').html(date_formated);
if(entry.fromOpponent)
{
$entry.addClass('odd');
}
if(entry.unread && typeof slient == 'undefined')
{
$entry.addClass('unread');
entry.unread = false;
}
$conversation_body.append($entry);
}
this.updateScrollbars();
}
},
getStatus: function(id)
{
if(typeof id == 'object')
{
id = id.attr('id');
}
var user = neonChat.chat_history[id];
if(user)
{
return user.status;
}
return null;
},
setStatus: function(id, status)
{
var $user = typeof id == 'string' ? $('.chat-group a#'+id.replace('#', '')) : id;
if($user.$el)
{
$user = $user.$el;
}
if($user.length && this.statuses[status].class)
{
var $status = $user.find('.user-status');
for(var i in this.statuses)
{
$status.removeClass(this.statuses[i].class);
}
$status.addClass(this.statuses[status].class);
$user.data('status', status);
neonChat.chat_history[ $user.attr('id') ].status = status;
this.orderGroups();
}
},
orderGroups: function()
{
var $groups = $chat.find('.chat-group');
if( ! $chat.data('order-by-status'))
{
return false;
}
$groups.each(function(i, el)
{
var $group = $(el),
$contacts = $group.find('> a');
$contacts.each(function(i, el)
{
var $contact = $(el),
$status = $contact.find('.user-status');
for(var i in neonChat.statuses)
{
var status = neonChat.statuses[i];
if(i == $contact.data('status'))
{
$contact.data('order-id', status.order);
return true;
}
else
if($status.hasClass(status.class))
{
$contact.data('order-id', status.order);
return true;
}
}
});
var $new_order = $contacts.sort(function(a,b){
return parseInt($(a).data('order-id'), 10) > parseInt($(b).data('order-id'), 10);
}).appendTo($group);
});
return true;
},
prefetchMessages: function()
{
$chat.find('.chat-group a').each(function(i, el)
{
var $contact = $(el),
id = $contact.attr('id'),
history_container = $contact.data('conversation-history');
if(history_container && history_container.length)
{
$($(history_container)).find('> li').each(function(j, el2)
{
var $entry = $(el2),
from = $entry.find('.user').html(),
message = $entry.find('p').html(),
time = $entry.find('.time').html(),
fromOpponent = $entry.hasClass('even') || $entry.hasClass('odd') || $entry.hasClass('opponent'),
unread = $entry.hasClass('unread');
neonChat.pushMessage(id, message, from, time, fromOpponent, unread)
});
}
});
},
countUnreadMessages: function(id)
{
var counter = 0;
if( ! id)
{
for(var id in neonChat.chat_history)
{
var user = neonChat.chat_history[id],
current_user_count = 0;
for(var i in user.messages)
{
if(user.messages[i].unread)
{
counter++;
current_user_count++;
}
}
user.unreads = current_user_count;
}
}
else
{
if(typeof id == 'object')
{
id = id.attr('id');
}
var user = neonChat.chat_history[id];
if(user)
{
return user.unreads;
}
}
return counter;
},
puffUnreads: function()
{
for(var i in this.chat_history)
{
var entry = neonChat.chat_history[i],
$badge = entry.$el.find('.badge');
if(entry.unreads > 0)
{
$badge.html(entry.unreads).removeClass('is-hidden');
}
else
{
$badge.html(entry.unreads).addClass('is-hidden');
}
}
},
puffUnreadsAll: function()
{
var total_unreads = this.countUnreadMessages();
$chat_badge.html(total_unreads);
$chat_badge[total_unreads > 0 ? 'removeClass' : 'addClass']('is-hidden');
},
resetUnreads: function(id)
{
if(typeof id == 'object')
{
id = id.attr('id');
}
var user = neonChat.chat_history[id];
if(user)
{
user.unreads = 0;
user.$el.find('.badge').html('0').addClass('is-hidden');
}
},
// Groups
createGroup: function(name, prepend)
{
var $group = $('<div class="chat-group"><strong>'+name+'</strong></div>');
if(prepend)
{
$group.insertBefore( $chat.find('.chat-group:first') );
}
else
{
$group['appendTo']($chat);
}
$group.hide().slideDown();
$group = $group.uniqueId();
return $group.attr('id');
},
removeGroup: function(group_id, move_users_to_group)
{
var $group = $chat.find("#" + group_id.replace('#', '') + '.chat-group');
if($group.length)
{
if(move_users_to_group)
{
var $group_2 = $chat.find("#" + move_users_to_group.replace('#', '') + '.chat-group');
if($group_2.length)
{
$group.find('a').each(function(i, el)
{
var $user = $(el);
$group_2.append($user);
$user.hide().slideDown();
});
}
this.orderGroups();
}
$group.slideUp(function()
{
$group.remove();
});
}
},
addUser: function(group_id, display_name, status, prepend, user_id)
{
var $group = group_id;
if(typeof group_id == 'string')
{
$group = $chat.find("#" + group_id.replace('#', '') + '.chat-group');
}
if($group && $group.length)
{
var status = this.statuses[status],
$user = $('<a href="#"><span class="user-status '+ status.class +'"></span> <em>'+ display_name +'</em> <span class="badge badge-info is-hidden>0</span></a>');
if(user_id)
{
$user.attr('id', user_id);
}
if(prepend)
{
$user.insertAfter( $group.find('> strong') );
}
else
{
$user['appendTo']($group);
}
$user.hide().slideDown();
this.refreshUserIds();
this.orderGroups();
return $user.uniqueId().attr('id');
}
return null;
},
addUserId: function(group_id, user_id, display_name, status, prepend)
{
return this.addUser(group_id, display_name, status, prepend, user_id);
},
getUser: function(id)
{
return this.chat_history[id] ? this.chat_history[id] : null;
},
moveUser: function(user_id, new_group_id, prepend)
{
var $new_group = $chat.find("#" + new_group_id.replace('#', '') + '.chat-group'),
user = this.chat_history[user_id];
if($new_group.length && user)
{
if(prepend)
{
user.$el.insertAfter($new_group.find('> strong'));
}
else
{
user.$el['appendTo']($new_group);
}
this.orderGroups();
return true;
}
return false;
},
// Chat Container
showChat: function(animated)
{
var visible_class = 'chat-visible';
if(isxs())
{
visible_class += ' toggle-click';
}
if(animated)
{
if($chat.data('is-busy'))
{
return false;
}
$chat.data('is-busy', true);
public_vars.$pageContainer.addClass(visible_class);
var mc_padding_right = parseInt(public_vars.$mainContent.css('padding-right'), 10),
mc_padding_left = parseInt(public_vars.$mainContent.css('padding-left'), 10),
chat_width = $chat.width();
public_vars.$pageContainer.removeClass(visible_class);
if(public_vars.$pageContainer.hasClass('right-sidebar'))
{
public_vars.$mainContent.transition({
paddingLeft: mc_padding_left,
duration: 500
});
}
else
{
public_vars.$mainContent.transition({
paddingRight: mc_padding_right,
duration: 500
});
}
$chat.show();
TweenMax.set($chat, {css: {autoAlpha: public_vars.$body.hasClass('boxed-layout') ? 0 : 1, transform: "translateX("+((public_vars.$pageContainer.hasClass('right-sidebar') ? -1 : 1) * chat_width)+"px)"}});
TweenMax.to($chat, .65, {css: {autoAlpha: 1, transform: "translateX(0)"}, ease: Sine.easeOut, onComplete: function()
{
public_vars.$pageContainer.addClass(visible_class);
public_vars.$mainContent.attr('style', '');
TweenMax.set($chat, {css: {transform: '', paddingRight: '', paddingLeft: ''}});
$chat.data('is-busy', false);
}});
}
else
{
public_vars.$pageContainer.addClass(visible_class);
}
},
hideChat: function(animated)
{
var visible_class = 'chat-visible';
if(isxs())
{
visible_class += ' toggle-click';
}
if(animated)
{
if($chat.data('is-busy'))
{
return false;
}
$chat.data('is-busy', true);
disableXOverflow();
public_vars.$pageContainer.removeClass(visible_class);
var mc_padding_right = parseInt(public_vars.$mainContent.css('padding-right'), 10),
mc_padding_left = parseInt(public_vars.$mainContent.css('padding-left'), 10),
chat_width = $chat.width();
public_vars.$pageContainer.addClass(visible_class);
// Close any opened conversation
neonChat.close();
TweenMax.to($chat, .4, {css: {autoAlpha: (public_vars.$body.hasClass('boxed-layout') ? 0 : 1), transform: "translateX("+ ((public_vars.$pageContainer.hasClass('right-sidebar') ? -1 : 1) * chat_width) +"px)"}, ease: Sine.easeIn});
var opts = {
paddingRight: mc_padding_right,
duration: 700,
complete: function()
{
public_vars.$pageContainer.attr('style', '');
public_vars.$mainContent.attr('style', '');
$chat.attr('style', '');
public_vars.$pageContainer.removeClass(visible_class);
enableXOverflow();
$chat.data('is-busy', false);
}
};
if(public_vars.$pageContainer.hasClass('right-sidebar'))
{
delete opts.paddingRight;
opts.paddingLeft = mc_padding_left;
}
public_vars.$mainContent.transition(opts);
}
else
{
public_vars.$pageContainer.removeClass(visible_class);
}
},
toggleChat: function(animated, collapse_sidebar)
{
var _func = public_vars.$pageContainer.hasClass('chat-visible') ? 'hideChat' : 'showChat';
if(isxs())
{
_func = public_vars.$pageContainer.hasClass('toggle-click') ? 'hideChat' : 'showChat';
}
neonChat[_func](animated);
if(collapse_sidebar)
{
if(sidebar_default_is_open)
{
if(_func == 'hideChat') // Hide Sidebar
{
show_sidebar_menu(animated);
}
else
{
hide_sidebar_menu(animated);
}
}
}
}
});
// Set Cursor
$conversation_body.on('click', function()
{
$textarea.focus();
});
// Refresh Ids
neonChat.init();
})(jQuery, window);