Вы находитесь на странице: 1из 16

(function($, window, document, undefined) {

'use strict';
var win = $(window);
var COOKIE_NAME = 'last_cursor';
var DEFAULT_USERPIC = '/content/images/commentlogo.png';
var Notify = {
instance: null,
getInstance: function() {
if (!this.instance) {
var host = kat.notify;//'notify.' + document.domain;
var url = document.location.protocol + '//' + host;
this.instance = new Dklab_Realplexor(url);
}
return this.instance;
},
getPublicChannel: function(hash) {
return 'pub_' + hash;
},
getPrivateChannel: function(hash) {
return 'priv_' + hash;
}
};
function WindowResizeHandler(options) {
this.options = $.extend({
start: function() {},
stop: function() {},
resize: function() {}
}, options);
this.init();
}
WindowResizeHandler.prototype = {
timer: null,
started: false,
init: function() {
var me = this;
this.options._resize = function(event) {
if (me.timer) {
clearTimeout(me.timer);
}
if (!me.started) {
me.started = true;
me.options.start.apply(me, event);
}
me.timer = setTimeout(function() {
me.started = false;
me.options.stop.apply(me, event);
}, 500);
me.options.resize.apply(me, event);
};

win.on('resize', this.options._resize);
},
destroy: function() {
win.off('resize', this.options._resize);
}
};
function ChatWindow(options) {
this.options = $.extend({
top: null,
left: null,
width: 300,
minWidth: 300,
height: 400,
minHeight: 300,
zIndex: null,
focus: true,
online: false,
subscribe: false,
minimized: false,
sender: {
avatar: ''
},
recipient: {
hash: '',
nickname: ''
}
}, options || {});
this.open();
}
var CHAT_VERSION = '3.1';
ChatWindow.prototype = {
open: function() {
this.container = $(
'<div class="chat-container">' +
' <div class="chat-header">' +
'
<div class="chat-close">x</div>' +
'
<div class="chat-minimize"> </div>' +
'
<div class="chat-status"><span></span></div>' +
'
<div class="chat-title"><a href="#"></a></div>' +
' </div>' +
' <div class="chat-history"></div>' +
' <div class="chat-input">' +
'
<div class="chat-avatar"><img src="'+ DEFAULT_USERPIC +'
" /></div>' +
'
<div class="chat-textarea"><textarea></textarea></div>'
+
' </div>' +
'</div>'
);
this.container.appendTo($('body'));
this.container.draggable({
handle: '.chat-header',
containment: 'window',

start: this.onLayoutChangeStart,
stop: this.onLayoutChangeStop
});
this.container.resizable({
containment: 'body',
minWidth: this.options.minWidth,
minHeight: this.options.minHeight,
start: this.onLayoutChangeStart,
stop: this.onLayoutChangeStop
}).on('resize', function(event) {
event.stopPropagation();
});
this.setWidth(this.options.width);
this.setMinimized(this.options.minimized !== null ? this.options.min
imized : false);
if (this.getMinimized()) {
$(this.container).height($($('.chat-input', this.container).get(
0)).height());
} else {
this.setHeight(this.options.height);
}
var pos = this._getDefaultPosition();
this.setPosition({
top: this.options.top !== null ? this.options.top : pos.top,
left: this.options.left !== null ? this.options.left : pos.left
});
this.setZIndex(this.options.zIndex !== null ? this.options.zIndex :
this._getMaxZIndex() + 1);
this.setTitleText(this.options.recipient.nickname);
this.setTitleUrl('/messenger/dialog/' + encodeURI(this.options.recip
ient.nickname) + '/');
if (this.options.sender.avatar) {
this.setAvatar(this.options.sender.avatar);
}
this.setOnline(this.options.online);
if (this.options.focus) {
this.focus();
}
var me = this;
this.container.click(function() {
me.onClick();
});
$('.chat-close', this.container).click(function() {
me.onCloseButtonClick();
});
$('.chat-minimize', this.container).click(function() {
me.onMinimizeButtonClick();
});

$('textarea', this.container).keydown(function(event) {
me.onActivity();
if (event.keyCode == 13 && event.shiftKey == false && event.altK
ey == false) {
var ta = $(this), text = ta.val();
text = text.replace(/^\s+/, '');
text = text.replace(/\s+$/, '');
if (text) {
me.onSubmit(text);
}
ta.val('');
return false;
}
});
this.container.click(function() {
me.onActivity();
});
this.windowResizeHandler = new WindowResizeHandler({
start: this.onLayoutChangeStart,
stop: this.onLayoutChangeStop,
resize: function() {
me.onWindowResize();
}
});
if (this.options.subscribe) {
this.subscribe();
}
ChatManager.add(this);
ChatManager.save();
if (this.getMinimized()) {
var history_div = $('.chat-history', this.container).get(0);
var input_div = $('.chat-input', this.container).get(0);
$(history_div).hide();
$(input_div).hide();
$($('.chat-minimize', this.container).get(0)).html('+');
$('.chat-minimize', this.container).click(function() {
me.onMaximizeButtonClick();
});
};
},
close: function() {
if (this.options.subscribe) {
this.unsubscribe();
}
this.container.remove();
this.container = null;
this.windowResizeHandler.destroy();
ChatManager.remove(this);
ChatManager.save();
return this;
},
minimize: function() {
var history_div = $('.chat-history', this.container).get(0);

var input_div = $('.chat-input', this.container).get(0);


$(history_div).hide();
$(input_div).hide();
$(this.container).height($($('.chat-input', this.container).get(0)).
height())
this.setMinimized(true);
$($('.chat-minimize', this.container).get(0)).html('+');
var me = this;
$('.chat-minimize', this.container).off('click');
$('.chat-minimize', this.container).click(function() {
me.onMaximizeButtonClick();
});
ChatManager.save();
return this;
},
maximize: function() {
var history_div = $('.chat-history', this.container).get(0);
var input_div = $('.chat-input', this.container).get(0);
$(history_div).show();
$(input_div).show();
$(this.container).height(this.options.height);
this.setMinimized(false);
$($('.chat-minimize', this.container).get(0)).html(' ');
var me = this;
$('.chat-minimize', this.container).off('click');
$('.chat-minimize', this.container).click(function() {
me.onMinimizeButtonClick();
});
ChatManager.save();
return this;
},
subscribe: function() {
var me = this;
this.notify = Notify.getInstance();
this.notifyCallback = function(data) {
var response = $.extend({
type: '',
data: ''
}, $.parseJSON(data));
if (response.type == 'status_change') {
me.setOnline(response.data.status == 'online');
}
};
this.notify.subscribe(Notify.getPublicChannel(this.options.recipient
.hash), this.notifyCallback);
this.notify.execute();
},
unsubscribe: function() {
this.notify.unsubscribe(Notify.getPublicChannel(this.options.recipie
nt.hash), this.notifyCallback);
this.notify.execute();
},
isFocused: function() {
return $('textarea', this.container).is(':focus');
},

isOnline: function() {
return $('textarea', this.container).not(':disabled');
},
getWidth: function() {
return this.container.width();
},
setWidth: function(width) {
this.container.width(width);
return this;
},
getHeight: function() {
if (this.getMinimized()) return this.options.height;
return this.container.height();
},
setHeight: function(height) {
this.options.height = height;
this.container.height(height);
return this;
},
getMinimized: function() {
return this.options.minimized;
},
setMinimized: function(minimized) {
this.options.minimized = minimized;
return this;
},
getPosition: function() {
return {
top: parseInt(this.container.css('top')),
left: parseInt(this.container.css('left'))
};
},
setPosition: function(options) {
this.container.css({
top: (options.top > 50 ? options.top: 50),
left: options.left || 0
});
return this;
},
setTitleText: function(text) {
$('.chat-title a', this.container).html(text);
return this;
},
setTitleUrl: function(url) {
$('.chat-title a', this.container).prop('href', url);
return this;
},
setOnline: function(online) {

$('.chat-status span', this.container).prop({


class: online ? 'online' : 'offline',
title: online ? 'online' : 'offline'
});
return this;
},
getZIndex: function() {
return parseInt(this.container.css('z-index'));
},
setZIndex: function(zIndex) {
this.container.css('z-index', zIndex);
return this;
},
setAvatar: function(avatar) {
$('.chat-input .chat-avatar img', this.container).prop('src', avatar
);
return this;
},
scrollDown: function(animate) {
animate = animate || false;
var history = $('.chat-history', this.container).get(0);
if (animate) {
$(history).animate({
scrollTop: history.scrollHeight
}, 500);
} else {
history.scrollTop = history.scrollHeight;
}
return this;
},
focus: function() {
var max = this._getMaxZIndex();
this.setZIndex(max + 1);
$('textarea', this.container).focus();
return this;
},
addMessage: function(options) {
options = $.extend({
id: '',
time: 0,
owner: false,
text: '',
read: false,
sender: {
avatar: ''
}
}, options);
var entry = $('<div class="chat-history-entry"><div class="chat-avat
ar"><img src="/content/images/commentlogo.png" /></div><div class="chat-time"></
div><div class="chat-message"></div></div>');
entry.attr('data-id', options.id);

var now = new Date(),


date = new Date(options.time * 1000),
time;
if (date.getDay() == now.getDay() && date.getMonth() == now.getMonth
() && date.getYear() == now.getYear()) {
time = (('0' + date.getHours()).substr(-2, 2) + ':' + ('0' + dat
e.getMinutes()).substr(-2, 2) + ':' + ('0' + date.getSeconds()).substr(-2, 2));
} else {
time = (('0' + date.getMonth()).substr(-2, 2) + '/' + ('0' + dat
e.getDate()).substr(-2, 2) + '/' + ('0' + date.getYear()).substr(-2, 2));
}
$('.chat-time', entry).html(time);
if (options.owner) {
entry.addClass('chat-owner');
}
$('.chat-message', entry).html(options.text.replace(/(\r?\n)+/, '<br
/>'));
if (!options.read) {
entry.addClass('chat-unread');
if (this.getMinimized() && !options.owner) {
$($('.chat-header', this.container).get(0)).addClass('chat-u
nread');
};
}
if (options.sender.avatar) {
var disable_animated = $.cookie('disable_animated_upics');
var ext = options.sender.avatar.split('.').pop().toLowerCase();
$('.chat-avatar img', entry).prop('src', disable_animated && dis
able_animated == 'yes' && ext == 'gif' ? DEFAULT_USERPIC : options.sender.avatar
);
}
$('.chat-history', this.container).append(entry);
return this;
},
markAsRead: function(owner) {
var e = $('.chat-unread', this.container);
if (owner) {
e = e.filter('.chat-owner');
} else {
e = e.not('.chat-owner');
}
if (e.size()) {
e.removeClass('chat-unread');
$.post('/messenger/mark/', {
version: CHAT_VERSION,
recipient: this.options.recipient.hash
}, function() {}, 'json').fail(function() {
alert(xhr.responseText);
});
}
return this;

},
onClick: function() {
this.focus();
return this;
},
onCloseButtonClick: function() {
this.close();
return this;
},
onMinimizeButtonClick: function() {
this.minimize();
return this;
},
onMaximizeButtonClick: function() {
this.maximize();
return this;
},
onSubmit: function(text) {
$.post('/messenger/chat_send/', {
version: CHAT_VERSION,
recipient: this.options.recipient.hash,
text: text
}, function() {}, 'json').fail(function(xhr) {
alert(xhr.responseText);
});
},
onActivity: function() {
this.markAsRead(false);
updateMessagesCount();
},
onLayoutChangeStart: function() {
ChatManager.stop();
},
onLayoutChangeStop: function() {
ChatManager.save();
ChatManager.start();
},
onWindowResize: function() {
var pos = this.getPosition(),
mw = this.getWidth(),
mh = this.getHeight(),
ww = win.width(),
wh = win.height();
pos._changed = false;
if (pos.top + mh > wh) {
pos._changed = true;
pos.top = wh - mh;
}
if (pos.left + mw > ww) {
pos._changed = true;

pos.left = ww - mw;
}
if (pos._changed && pos.top >= 50 && pos.left >= 0) {
this.setPosition(pos);
}
},
_getDefaultPosition: function() {
var dx = 10,
dy = 50,
top = win.height() - this.container.height() - dy,
defaultLeft = win.width() - this.container.width() - dx,
left = defaultLeft,
rows = 1;
$('.chat-container').each(function() {
var l = parseInt($(this).css('left')),
t = parseInt($(this).css('top'));
if (l == left && t == top) {
left -= $(this).width() + rows * dx;
if (left < dx) {
left = defaultLeft;
rows++;
}
}
});
return {
top: top,
left: left
};
},
_getMaxZIndex: function() {
var max = 50;
$('.chat-container').each(function() {
var z = parseInt($(this).css('zIndex'));
if (z > max) {
max = z;
}
});
return max + 1;
}
};
var ChatManager = {
LS_KEY: 'ChatManagerDataV2',
SAVE_INTERVAL: 2000,
windows: {},
interval: null,
allow_save: false,
init: function() {
var me = this;
this.load();

win.on('beforeunload', function() {
me.save();
});
return this;
},
start: function() {
var me = this;
this.interval = setInterval(function() {
me.load();
}, this.SAVE_INTERVAL);
return this;
},
stop: function() {
clearInterval(this.interval);
return this;
},
load: function() {
var me = this,
hashes = [],
create = {},
options = {},
data = $.localStorage(this.LS_KEY) || {};
$.each(data, function(hash) {
hashes.push(hash);
options[hash] = {
top: this.t,
left: this.l,
width: this.w,
height: this.h,
zIndex: this.z,
focus: this.f,
minimized: this.m
};
});
$.each(options, function(hash) {
var chat = me.getByHash(hash);
if (chat) {
if (chat.getPosition().top != this.top || chat.getPosition()
.left != this.left) {
chat.setPosition({
top: this.top,
left: this.left
});
}
if (chat.getWidth() != this.width) {
chat.setWidth(this.width);
}
if (chat.getHeight() != this.height && !chat.getMinimized())
{
chat.setHeight(this.height);

}
if (chat.getZIndex() != this.zIndex) {
chat.setZIndex(this.zIndex);
}
if (chat.getMinimized() != this.minimized) {
var history_div = $('.chat-history', this.container).ge
t(0);
var input_div = $('.chat-input', this.container).get(0);
$(history_div).hide();
$(input_div).hide();
};
} else {
create[hash] = this;
}
});
$.each(this.windows, function(hash) {
if ($.inArray(hash, hashes) == -1) {
this.close();
}
});
if (!$.isEmptyObject(create)) {
this.stop();
ChatManager.create(create, function() {
this.save();
this.start();
});
}
return this;
},
save: function() {
if (!this.allow_save) return this;
var data = {};
$.each(this.windows, function(hash) {
var pos = this.getPosition();
if (pos.top < 50) {
pos.top = 50;
this.setPosition(pos);
}
data[hash] = {
t: pos.top,
l: pos.left,
w: this.getWidth(),
h: this.getHeight(),
z: this.getZIndex(),
f: this.isFocused(),
m: this.getMinimized()
};
});
$.localStorage(this.LS_KEY, data);

return this;
},
add: function(window) {
this.windows[window.options.recipient.hash] = window;
return this;
},
remove: function(window) {
delete this.windows[window.options.recipient.hash];
return this;
},
create: function(options, callback) {
var me = this,
hashes = [];
if (typeof options == 'string') {
if (!this.getByHash(options)) {
hashes.push(options);
}
} else if (typeof options == 'object') {
$.each(options, function(hash) {
if (!me.getByHash(hash)) {
hashes.push(hash);
}
});
}
if (!hashes.length) {
if (typeof callback == 'function') {
callback.apply(me);
}
return this;
}
$.post('/messenger/chat_init/', {
version: CHAT_VERSION,
recipients: hashes
}, function(data) {
me.allow_save = true;
$.each(data, function(hash, opts) {
if (me.getByHash(hash)) {
return;
}
$.extend(opts, options[hash]);
var chat = new ChatWindow(opts);
if (opts.messages.length) {
$.each(opts.messages, function() {
chat.addMessage(this);
});
chat.scrollDown();
}
chat.onWindowResize();
});

if (typeof callback == 'function') {


callback.apply(me);
}
}, 'json').fail(function(xhr) {
// alert('chat init aborted' + xhr.responseText);
});
return this;
},
getByHash: function(hash) {
if (typeof this.windows[hash] != 'undefined') {
return this.windows[hash];
}
return null;
}
};
$.fn.createChat = function() {
var $this = $(this),
hash = $this.prop('rel');
if (!hash) return;
var chat = ChatManager.getByHash(hash);
if (chat) {
chat.focus();
} else {
ChatManager.create(hash);
}
return this;
};
$(function() {
// delete old history data
$.localStorage('ChatHistoryDataV2', null);
ChatManager.init();
$(document).on('click', '.chat', function() {
$(this).createChat();
return false;
});
// private types
var types = {
new_message: function(data) {
var target = data.owner ? data.recipient : data.sender;
// update messages count
updateMessagesCount(data.unread_count);
if (!data.owner) {
State.run(function() {
// play sound
if (!katUser.disable_sounds) {
Sound.play('/content/audio/new_message');

}
// show chrome notification
$.notification({
iconUrl: target.avatar,
title: 'New message from ' + target.nickname,
body: data.text
});
});
}
var chat = ChatManager.getByHash(target.hash);
if (chat) {
// add message to chat window
chat.addMessage(data);
chat.scrollDown(true);
} else if (!data.owner) {
// show alert window
new AlertWindow({
acl: target.acl,
iconUrl: target.avatar,
title: target.nickname,
text: data.text,
timeout: 30000
}).on('click', function() {
var chat = ChatManager.getByHash(target.hash);
if (chat) {
chat.focus();
} else {
ChatManager.create(target.hash);
}
this.close();
}).on('mouseleave', function() {
this.close();
}).open();
}
},
mark_as_read: function(data) {
var chat = ChatManager.getByHash(data.sender.hash);
if (chat) {
// mark messages as read
chat.markAsRead(true);
}
}
};
var rpl = Notify.getInstance(),
cursor = $.cookie(COOKIE_NAME),
channel = Notify.getPrivateChannel(katUser.idhash);
if (cursor) {
rpl.setCursor(channel, cursor);
}
// subscribe to private user's channel
rpl.subscribe(channel, function(data, id, cursor) {
$.cookie(COOKIE_NAME, cursor, {
path: '/',

expires: 365
});
var response = $.parseJSON(data);
if (typeof response.type != 'undefined' && typeof response.data != '
undefined' && typeof types[response.type] == 'function') {
types[response.type](response.data);
}
});
rpl.execute();
});
})(jQuery, window, document);

Вам также может понравиться