Skip to content

Instantly share code, notes, and snippets.

@jamesfalkner
Created February 21, 2013 17:05
Show Gist options
  • Save jamesfalkner/5006270 to your computer and use it in GitHub Desktop.
Save jamesfalkner/5006270 to your computer and use it in GitHub Desktop.
AUI().use("anim-color", "anim-easing", "aui-base", "aui-live-search", "liferay-poller", "stylesheet", "swfobject", function (a) {
var h = a.Lang;
var d = h.now;
var f = a.config.doc;
var e = a.config.win.webkitNotifications;
var c = 0;
var g = 1;
var b = '\u004e\u0065\u0077\u0020\u004d\u0065\u0073\u0073\u0061\u0067\u0065\u0020\u0066\u0072\u006f\u006d\u0020\u007b\u0030\u007d';
Liferay.namespace("Chat");
a.one(f.documentElement).toggleClass("desktop-notifications", !!e);
Liferay.Chat.Util = {getDefaultColor: function () {
var i = this;
var k = i._defaultColor;
if (!k) {
var j = a.one("#chatBar .panel-trigger");
if (j) {
k = j.getStyle("backgroundColor");
while (k == "transparent") {
k = j.getStyle("backgroundColor");
j = j.ancestor()
}
}
i._defaultColor = k
}
return k
}, getWaitingColor: function () {
var i = this;
var k = i._waitingColor;
if (!k) {
var j = a.Node.create('<span class="aui-helper-hidden message-waiting" />').appendTo(f.body);
k = j.getStyle("backgroundColor");
j.remove();
i._waitingColor = k
}
return k
}, formatTime: function (l) {
var i = this;
l = Number(l);
l = new Date(l);
var k = "am";
var j = l.getHours();
var m = l.getMinutes();
if (j >= 11) {
k = "pm"
}
if (j > 12) {
j -= 12
}
if (j === 0) {
j += 12
}
if (m < 10) {
m = "0" + m
}
return j + ":" + m + " " + k
}, getCurrentTimestamp: function () {
var i = this;
return d() - i._getOffset()
}, getUserImagePath: function (j) {
var i = this;
return themeDisplay.getPathImage() + "/user_portrait?img_id=" + j
}, _getOffset: function () {
var i = this;
var j = i._offset;
if (h.isUndefined(j)) {
var k = a.one("#currentChatServerTime").val() || 0;
j = d() - k;
i._offset = j
}
return j
}, TIMESTAMP_24: (24 * 60 * 60 * 1000)};
Liferay.Chat.Panel = function (j) {
var i = this;
if (!j.container) {
i._tabsContainer = Liferay.Chat.Manager.getContainer()
} else {
i._tabsContainer = a.one(j.container)
}
i._chatProperties = {};
i._eventsSuspended = false;
i._panelId = j.panelId;
i._panelTitle = j.panelTitle;
i._panelIcon = j.panelIcon;
i._created = Liferay.Chat.Util.getCurrentTimestamp();
var k = i._setPanelHTML(j.panelHTML);
i.set("panelHTML", k);
i._createPanel(j.fromMarkup);
if (j.panelTitle) {
i.setTitle(j.panelTitle)
}
i._popupTrigger.unselectable()
};
Liferay.Chat.Panel.prototype = {close: function () {
var i = this;
i._panel.remove();
i.fire("close")
}, getPanel: function () {
var i = this;
return i._panel
}, getTitle: function () {
var i = this;
return i._popupTitle.text()
}, hide: function () {
var i = this;
i.set("selected", false);
i._panel.removeClass("selected");
i.fire("hide")
}, resumeEvents: function () {
var i = this;
i._eventsSuspended = false
}, setTitle: function (j) {
var i = this;
i._popupTrigger.one(".trigger-name").text(j);
i._popupTitle.text(j)
}, show: function () {
var i = this;
i.set("selected", true);
i._panel.addClass("selected");
i.fire("show")
}, suspendEvents: function () {
var i = this;
i._eventsSuspended = true
}, toggle: function () {
var i = this;
if (i.get("selected")) {
i.hide()
} else {
i.show()
}
}, _createPanel: function (k) {
var i = this;
var j;
if (k) {
j = a.one(k)
} else {
j = a.Node.create(i.get("panelHTML"))
}
i._popup = j.one(".chat-panel");
i._popupTitle = j.one(".panel-title");
i._textBox = j.one("textarea");
i._popupTrigger = j.one(".panel-trigger");
i._popupTrigger.on("click", i.toggle, i);
j.all(".panel-button").on("click", function (l) {
var m = l.currentTarget;
if (m.hasClass("minimize")) {
i.hide()
} else {
if (m.hasClass("close")) {
i.close()
}
}
});
i._panel = j;
i._tabsContainer.append(j)
}, _setPanelHTML: function (j) {
var i = this;
if (!j) {
j = '<li class="panel"><div class="panel-trigger"><span class="trigger-name"></span></div><div class="chat-panel"><div class="panel-window"><div class="panel-button minimize"></div><div class="panel-title"></div><div class="search-buddies"><input class="search-buddies-field" type="text" /></div><div class="panel-content"></div></div></div></li>'
}
return j
}};
a.augment(Liferay.Chat.Panel, a.Attribute);
Liferay.Chat.Conversation = function (j) {
var i = this;
Liferay.Chat.Conversation.superclass.constructor.call(i, j);
i._chatInput = i._panel.one(".panel-input textarea");
i._chatOutput = i._panel.one(".panel-output");
i._statusMessage = i._panel.one(".panel-profile");
i._created = Liferay.Chat.Util.getCurrentTimestamp();
i._lastMessageTime = 0;
i._lastTypedTime = 0;
i._typingDelay = 5000;
i._unreadMessages = 0;
i._originalPageTitle = f.title;
i._stopTypingTask = a.debounce(i.setTyping, i._typingDelay, i, false);
i._heightMonitor = a.Node.create('<pre class="chat-height-monitor" />');
i._heightMonitor.appendTo(f.body);
i._unreadMessagesContainer = i._panel.one(".unread");
if (!i._unreadMessagesContainer) {
i._unreadMessagesContainer = a.Node.create('<div class="unread" />');
i._popupTrigger.append(i._unreadMessagesContainer)
}
if (j.statusMessage) {
i._statusMessage.text(j.statusMessage)
}
i._chatInput.on("keyup", i._keystroke, i);
i._chatInput.on("focus", i._keystroke, i)
};
a.extend(Liferay.Chat.Conversation, Liferay.Chat.Panel, {send: function (j) {
var i = this;
Liferay.Chat.Manager.send(j)
}, setAsRead: function () {
var i = this;
i.setWaiting(false);
i._unreadMessagesContainer.hide();
i._unreadMessages = 0;
i.set("lastReadTime", Liferay.Chat.Util.getCurrentTimestamp());
f.title = i._originalPageTitle
}, setAsUnread: function () {
var i = this;
if (!i.get("selected")) {
if (i._unreadMessages > 1) {
i._unreadMessagesContainer.text(i._unreadMessages);
i._unreadMessagesContainer.show()
} else {
Liferay.Chat.Manager.triggerSound();
i.setWaiting(true);
i._unreadMessagesContainer.hide()
}
f.title = i._originalPageTitle + " - Unread messages (" + i._unreadMessages + ")"
}
}, setTyping: function (j) {
var i = this;
if (j) {
i._panel.addClass("typing")
} else {
i._panel.removeClass("typing")
}
}, setWaiting: function (k) {
var i = this;
var j = i._panel;
var l = i._waitingAnim;
if (k) {
if (!l) {
var m = Liferay.Chat.Util;
l = new a.Anim({direction: "alternate", duration: 0.65, easing: "easeBoth", from: {backgroundColor: m.getDefaultColor()}, iterations: "infinite", node: j, to: {backgroundColor: m.getWaitingColor()}});
i._waitingAnim = l
}
l.run()
} else {
if (l) {
l.stop()
}
j.setStyle("backgroundColor", "")
}
}, show: function () {
var i = this;
Liferay.Chat.Panel.prototype.show.call(i);
i.setAsRead();
var j = i._chatOutput.getDOM();
j.scrollTop = j.scrollHeight
}, update: function (j) {
var i = this;
if (j.incoming && !j.cache) {
if (j.content.length) {
if (!i.get("selected")) {
var k = i.get("lastReadTime") || 0;
if (k < j.createDate) {
i._unreadMessages++
}
Liferay.Chat.Manager.notify(Liferay.Chat.Util.getUserImagePath(i._panelIcon), h.sub(b, [i._panelTitle]), j.content.replace(/\n/g, " "))
}
i.setAsUnread()
} else {
i.setTyping(true);
i._stopTypingTask()
}
}
if (j.content.length) {
i._updateMessageWindow(j);
i.setTyping(false)
}
if (j.statusMessage) {
i._statusMessage.text(j.statusMessage)
}
}, updateStatus: function (j) {
var i = this;
i._statusMessage.text(j)
}, _autoSize: function () {
var k = this;
var j = k._heightMonitor.getDOM();
if (!k._chatInputWidth) {
k._chatInputWidth = k._chatInput.get("offsetWidth");
k._heightMonitor.setStyle("width", k._chatInputWidth)
}
var l = k._chatInput.getDOM();
var m = Liferay.Util.escapeHTML(l.value);
var n = f.createTextNode(m);
j.innerHTML = "";
j.appendChild(n);
m = j.innerHTML;
if (!m.length) {
m = "&nbsp;&nbsp;"
}
if (Liferay.Browser.isIe()) {
m = m.replace(/\n/g, "<br />")
}
j.innerHTML = m;
var i = Math.max(j.offsetHeight, 14);
i = Math.min(i, 64);
l.style.overflowY = "auto";
if (i != k._lastHeight) {
k._lastHeight = i;
l.style.height = i + "px";
l.style.overflowY = (i == 64) ? "scroll" : "hidden";
l.parentNode.style.height = (i + 5) + "px"
}
}, _keystroke: function (o) {
var i = this;
var n = i._chatInput;
var k = i._panelId;
var j = n.getDOM();
var m = j.value.replace(/\n|\r/gim, "");
if (o.type == "keyup") {
if (i.get("typedTo") == k) {
var l = Liferay.Chat.Util.getCurrentTimestamp();
if (l - i._lastTypedTime > i._typingDelay) {
i.send({toUserId: k, content: ""});
i._lastTypedTime = l
}
}
i.set("typedTo", k)
}
if (o.keyCode == 13 && !o.shiftKey && m.length) {
i._sendChat(j.value);
j.value = ""
}
i._autoSize()
}, _sendChat: function (l) {
var i = this;
var k = Liferay.Chat.Util.getCurrentTimestamp();
var j = i._panelId;
var m = Liferay.Util.escapeHTML(l);
i.send({content: l, toUserId: j});
i._updateMessageWindow({content: m, createDate: k})
}, _setPanelHTML: function () {
var i = this;
var k = Liferay.Chat.Util.getUserImagePath(i._panelIcon);
var j = '<li class="user user_' + i._panelId + '" panelId="' + i._panelId + '"><div class="panel-trigger"><span class="trigger-name"></span><div class="typing-status"></div></div><div class="chat-panel"><div class="panel-window"><div class="panel-button minimize"></div><div class="panel-button close"></div><img alt="" class="panel-icon" src="' + k + '" /><div class="panel-title">' + i._panelTitle + '</div><div class="panel-profile">...</div><div class="panel-output"></div><div class="panel-input"><textarea></textarea></div></div></div></li>';
return j
}, _updateMessageWindow: function (n) {
var o = this;
var i = o._chatOutput;
var q = "outgoing";
var l = n.content;
var j = n.incoming;
var m = themeDisplay.getUserName();
if (j) {
q = "incoming";
m = o._panelTitle
}
l = l.replace(/\n/g, "<br />");
var p = '<p class="blurb ' + q + '"><b class="name">' + m + '</b><i class="date">' + Liferay.Chat.Util.formatTime(n.createDate) + '</i><span class="text">' + l + "</span></p>";
var k = i.getDOM();
k.innerHTML += p;
o._lastMessageTime = n.createDate;
setTimeout(function () {
k.scrollTop = k.scrollHeight - k.clientHeight
}, 1)
}});
Liferay.Chat.Manager = {init: function () {
var i = this;
i._closedChats = {};
i._notificationTimeout = 8000;
i._initialRequest = true;
i._chatContainer = a.one("#chatBar");
i._activePanelId = a.one("#activePanelId").val() || "";
i._portletId = a.one("#chatPortletId").val();
i._myStatus = i._chatContainer.one(".status-message");
i._soundContainer = i._chatContainer.one(".chat-sound");
i._tabsContainer = i._chatContainer.one(".chat-tabs");
i._created = Liferay.Chat.Util.getCurrentTimestamp();
i._sendTask = a.debounce(i.send, 100, i);
i._sound = new SWFObject("/chat-portlet/alert.swf", "alertsound", "0", "0", "8");
i._updatePresenceTask = a.debounce(i._updatePresence, 30000, i);
i._updatePresenceTask.delay(0);
Liferay.Poller.addListener(i._portletId, i._onPollerUpdate, i);
Liferay.bind("sessionExpired", function (j) {
Liferay.Poller.removeListener(i._portletId);
i._chatContainer.hide()
});
i._createBuddyListPanel();
i._createSettingsPanel()
}, close: function (k) {
var i = this;
if ((k != "buddylist") && (k != "settings")) {
var j = i._panels[k];
if (j) {
j.close()
}
}
}, getContainer: function () {
var i = this;
return i._tabsContainer
}, notify: function (k, m, j) {
var i = this;
if (e && e.checkPermission() === c) {
var l = e.createNotification(k, m, j);
l.show();
setTimeout(function () {
l.cancel()
}, i._notificationTimeout)
}
}, registerBuddyService: function (k) {
var i = this;
var j = k.name;
var m = k.fn;
var l = k.icon;
i._buddyServices[j] = m;
var n = i._styleSheet;
if (!n) {
n = new a.StyleSheet();
i._styleSheet = n
}
n.set(".chat-bar .buddy-services ." + j, {backgroundImage: 'url("' + l + '")'})
}, send: function (j, k) {
var i = this;
if (!j.updatePresence) {
i._updatePresenceTask.cancel()
}
Liferay.Poller.submitRequest(i._portletId, j, k);
i._updatePresenceTask()
}, show: function (k) {
var i = this;
var j = i._panels[k];
if (j) {
j.show()
}
}, toggle: function (k) {
var i = this;
var j = i._panels[k];
if (j) {
j.toggle()
}
}, triggerSound: function () {
var i = this;
if (i._playSound) {
i._sound.write(i._soundContainer.getDOM())
}
}, _addChat: function (k, j) {
var i = this;
i._chatSessions[k] = j
}, _addPanel: function (k, j) {
var i = this;
i._panels[k] = j;
j.on("close", i._onPanelClose, i);
j.on("hide", i._onPanelHide, i);
j.on("show", i._onPanelShow, i)
}, _createBuddyListPanel: function () {
var i = this;
var l = new Liferay.Chat.Panel({fromMarkup: ".chat-tabs > .buddy-list", panelId: "buddylist"});
i._addPanel("buddylist", l);
var k = l.getPanel();
var j = k.one(".online-users");
var n = k.one(".search-buddies-field");
var m = new a.LiveSearch({input: n, nodes: "#chatBar .buddy-list .online-users li", data: function (o) {
return o.one(".name").text()
}});
n.on("focus", m.refreshIndex, m);
l.on("show", function (o) {
if (n.val()) {
n.selectText()
}
});
if (j) {
j.delegate("click", function (p) {
var q = p.currentTarget;
if (q.ancestor(".buddy-services")) {
p.stopPropagation();
var o = q.getAttribute("class");
i._buddyServices[o](q.ancestor("li.user"))
} else {
i._createChatFromUser(q)
}
}, "li, .buddy-services div")
}
i._searchBuddiesField = n;
i._liveSearch = m;
i._onlineBuddies = j
}, _createChatFromUser: function (k) {
var i = this;
var l;
var n = i._buddies;
var m = k;
k = a.one(k);
if (k) {
m = k.getAttribute("userId")
}
if (!isNaN(Number(m))) {
l = n[m];
if (l) {
var j = i._chatSessions[m];
if (!j) {
j = i._createChatSession(l)
}
j.show()
}
}
}, _createChatSession: function (m) {
var k = this;
var o = m.userId;
var l = new Liferay.Chat.Conversation({panelId: m.userId, panelTitle: m.fullName, panelIcon: m.portraitId, statusMessage: m.statusMessage});
k._addChat(o, l);
k._addPanel(o, l);
if (k._entryCache && k._entryCache[o]) {
var j = k._entryCache[o];
for (var n in j) {
var p = j[n];
l.update({cache: true, content: p.content, createDate: p.createDate, incoming: (p.fromUserId == o)})
}
}
if (m.open) {
l.show()
}
return l
}, _createSettingsPanel: function () {
var i = this;
var n = new Liferay.Chat.Panel({fromMarkup: ".chat-tabs > .chat-settings", panelId: "settings"});
i._addPanel("settings", n);
var l = n.getPanel();
var m = l.one("#saveSettings");
i._statusMessageObj = l.one("#statusMessage");
i._onlineObj = l.one("#onlineStatus");
i._playSoundObj = l.one("#playSound");
i._showNotificationsObj = l.one("#showNotifications");
i._statusMessage = i._statusMessageObj.val() || "";
i._online = i._onlineObj.get("checked") ? 1 : 0;
i._playSound = i._playSoundObj.get("checked") ? 1 : 0;
if (e) {
var j = i._showNotificationsObj;
var o = e.checkPermission();
var k = {checked: (o === c)};
if (o === g) {
k.disabled = false
}
j.attr(k)
}
m.on("click", i._updateSettings, i)
}, _getSettings: function () {
var i = this;
return{activePanelId: i._activePanelId, online: i._online, statusMessage: i._statusMessage, playSound: i._playSound}
}, _loadCache: function (m) {
var s = this;
if (!s._entryCache) {
s._entryCache = {}
}
if (!s._entryIds) {
s._entryIds = [0]
}
var k = s._entryCache;
var r = s._entryIds;
var j = themeDisplay.getUserId();
var o = m.length;
for (var l = 0; l < o; l++) {
var q = m[l];
var n = q.toUserId;
if (n == j) {
n = q.fromUserId
}
if (!k[n]) {
k[n] = {}
}
var p = k[n];
if (q.content !== "") {
p[q.entryId] = q;
r.push(q.entryId)
}
}
}, _isMessageNew: function (m, k) {
var j = this;
var l = m.createDate;
var n = j._created;
var i = j._closedChats[k] || 0;
return(l > n && l > i)
}, _onPanelClose: function (l) {
var i = this;
var j = l.target;
var k = j._panelId;
delete i._panels[k];
if (j instanceof Liferay.Chat.Conversation) {
delete i._chatSessions[k]
}
i._closedChats[k] = Liferay.Chat.Util.getCurrentTimestamp();
i._activePanelId = "";
i._saveSettings()
}, _onPanelHide: function (j) {
var i = this;
i._activePanelId = "";
i._saveSettings()
}, _onPanelShow: function (m) {
var j = this;
var k = m.target;
for (var l in j._panels) {
if (j._panels[l] != k) {
j._panels[l].hide()
}
}
if (k instanceof Liferay.Chat.Conversation) {
k._chatInput.focus()
}
j._activePanelId = k._panelId;
j._saveSettings()
}, _onPollerUpdate: function (k, j) {
var i = this;
i._updateBuddies(k.buddies);
if (i._cacheLoaded) {
i._updateConversations(k.entries)
}
if (i._initialRequest) {
i._loadCache(k.entries);
if (i._activePanelId.length) {
var l = parseInt(i._activePanelId, 10);
if (!isNaN(l)) {
i._createChatFromUser(i._activePanelId)
}
}
i._cacheLoaded = true;
i._initialRequest = false;
i._chatContainer.one(".chat-tabs > .buddy-list").removeClass("loading")
}
}, _saveSettings: function () {
var i = this;
i._sendTask(i._getSettings())
}, _updateBuddies: function (k) {
var x = this;
var w = x._searchBuddiesField;
var y = w.val().toLowerCase();
var u = k || [];
var t = u.length;
var l = x._buddies;
var j = x._chatSessions;
x._onlineBuddiesCount = t;
var m = [""];
for (var n = 0; n < t; n++) {
var q = u[n];
var r = l[q.userId];
var v = j[q.userId];
q.isTyping = false;
if (v && (!r || r.statusMessage != q.statusMessage)) {
v.updateStatus(q.statusMessage)
}
l[q.userId] = q;
var s = Liferay.Chat.Util.getUserImagePath(q.portraitId);
m.push('<li class="user active" userId="' + q.userId + '"><img alt="" src="' + s + '" /><div class="name">' + q.fullName + '</div><div class="buddy-services">');
var p = x._buddyServices;
for (var o in p) {
m.push('<div class="' + o + '"></div>')
}
m.push("</div></li>")
}
x._onlineBuddies.html(m.join(""));
if (w.test(":visible") && (y.length > 2 || w.compareTo(f.activeElement))) {
x._liveSearch.refreshIndex();
x._liveSearch.fire("search", {liveSearch: {}})
}
x._updateBuddyList();
x.fire("updateBuddies", k)
}, _updateBuddyList: function (k) {
var i = this;
var j = i._panels.buddylist;
var l = j.getTitle();
l = l.replace(/\(\d+\)/, "(" + i._onlineBuddiesCount + ")");
j.setTitle(l)
}, _updateConversations: function (m) {
var t = this;
var o = m.length;
var j = themeDisplay.getUserId();
var s = t._entryIds.join("|");
for (var l = 0; l < o; l++) {
var r = m[l];
var q = (s.indexOf("|" + r.entryId) > -1);
if (!q) {
var n = r.toUserId;
var k = false;
if (r.fromUserId != j) {
n = r.fromUserId;
k = true
}
var p = t._buddies[n];
if (p && k) {
var u = t._chatSessions[n];
if (!u && r.content && t._isMessageNew(r, n)) {
u = t._createChatSession({portraitId: p.portraitId, userId: p.userId, fullName: p.fullName, statusMessage: p.statusMessage})
}
if (u) {
u.update({incoming: k, content: r.content, createDate: r.createDate, entryId: r.entryId, statusMessage: p.statusMessage})
}
}
}
}
t._loadCache(m)
}, _updatePresence: function () {
var i = this;
i.send({updatePresence: true})
}, _updateSettings: function () {
var i = this;
var l = i._panels.settings;
var k = l.getPanel();
i._statusMessage = i._statusMessageObj.val();
i._online = i._onlineObj.get("checked") ? 1 : 0;
i._playSound = i._playSoundObj.get("checked") ? 1 : 0;
var j = i._showNotificationsObj;
if (j.attr("checked") && e && e.checkPermission() === g) {
e.requestPermission(function () {
var m = e.checkPermission() == c;
j.attr({checked: m, disabled: m})
})
}
i._activePanelId = "";
l.hide();
i._saveSettings();
k.addClass("saved");
if (i._statusMessage) {
i._myStatus.html("You are <strong>" + Liferay.Util.escapeHTML(i._statusMessage) + "</strong>")
}
setTimeout(function () {
k.removeClass("saved")
}, 1500)
}, _buddies: {}, _buddyServices: {}, _chatSessions: {}, _entries: [], _panels: {}, _settings: {}, _styleSheet: null};
a.augment(Liferay.Chat.Manager, a.Attribute, true);
Liferay.publish("chatPortletReady", {defaultFn: a.bind(Liferay.Chat.Manager.init, Liferay.Chat.Manager), fireOnce: true});
a.on("domready", function () {
Liferay.fire("chatPortletReady")
})
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment