Index: lams_tool_chat/web/includes/javascript/learning.js
===================================================================
RCS file: /usr/local/cvsroot/lams_tool_chat/web/includes/javascript/learning.js,v
diff -u -r1.11 -r1.12
--- lams_tool_chat/web/includes/javascript/learning.js 30 Apr 2008 02:26:13 -0000 1.11
+++ lams_tool_chat/web/includes/javascript/learning.js 24 Oct 2012 11:27:01 -0000 1.12
@@ -1,330 +1,115 @@
-
-/* ******* Constants ******* */
-var GROUPCHAT_MSG = "";
-var PRIVATE_MSG = "private_message";
+// for chat users to be indetified by different colours
var PALETTE = ["#0000FF", "#006699", "#0066FF", "#6633FF", "#00CCFF", "#009900", "#00CC33", "#339900", "#008080", "#66FF66", "#CC6600", "#FF6600", "#FF9900", "#CC6633", "#FF9933", "#990000", "#A50021", "#990033", "#CC3300", "#FF6666", "#330033", "#663399", "#6633CC", "#660099", "#FF00FF", "#999900", "#808000", "#FF9FF2", "#666633", "#292929", "#666666"];
-/* ******* Helper Functions ******* */
-function getColour(nick) {
- var charSum = 0;
- for (var i = 0; i < nick.length; i++) {
- charSum += nick.charCodeAt(i);
+// only Monitor can send a personal message
+var selectedUser = null;
+// last message in chat window
+var lastMessageUid = null;
+var pollInProgress = false;
+
+function updateChat() {
+ if (!pollInProgress) {
+ // synchronise: if polling takes too long, don't try to do it again
+ pollInProgress = true;
+ $.ajax({
+ url : LEARNING_ACTION,
+ data : {'dispatch' : 'getChatContent',
+ 'toolSessionID' : TOOL_SESSION_ID,
+ 'lastMessageUid' : lastMessageUid
+ },
+ cache : false,
+ dataType : 'json',
+ success : handleUpdateChatResult,
+ complete : function(){
+ pollInProgress = false;
+ }
+ });
}
- return PALETTE[charSum % (PALETTE.length)];
}
-function htmlEnc(str) {
- if (!str) {
- return null;
- }
- str = str.replace(/&/g, "&");
- str = str.replace(//g, ">");
- str = str.replace(/\"/g, """);
- str = str.replace(/\n/g, "
");
- return str;
-}
-function createElem(name, attrs, style, text) {
- var e = document.createElement(name);
- if (attrs) {
- for (var key in attrs) {
- if (key == "attrClass") {
- e.className = attrs[key];
- } else {
- if (key == "attrId") {
- e.id = attrs[key];
- } else {
- e.setAttribute(key, attrs[key]);
- }
- }
- }
- }
- if (style) {
- for (key in style) {
- e.style[key] = style[key];
- }
- }
- if (text) {
- e.appendChild(document.createTextNode(text));
- }
- return e;
-}
-/* ******* Roster ******* */
-function RosterUser(nick) {
- this.nick = nick;
- this.status = "unavailable";
-}
-function getRosterUserByNick(nick) {
- for (var i = 0; i < this.users.length; i++) {
- if (this.users[i].nick == nick) {
- return this.users[i];
- }
- }
- return null;
-}
-function AddRosterUser(user) {
- this.users[this.users.length] = user;
-}
-function UpdateRosterUser(user) {
- // TODO do we need this.
-}
-function RemoveRosterUser() {
-}
-function UpdateRosterDisplay() {
- var rosterDiv = document.getElementById("roster");
- rosterDiv.innerHTML = "";
- for (var i = 0; i < this.users.length; i++) {
- if (this.users[i].status != "unavailable") {
- var className = "unselected";
- if (i == this.currentIndex) {
- className = "selected";
- }
- var nick = this.users[i].nick;
- var userDiv = createElem("div", {attrId:"user-" + i, attrClass:className, onClick:"selectUser(this);"}, {width:"100%", color:getColour(this.users[i].nick)}, this.users[i].nick);
- rosterDiv.appendChild(userDiv);
- }
- }
+
+function handleUpdateChatResult(result) {
+ if (result.lastMessageUid) {
+ messageDiv.html('');
+ // all messasges need to be written out, not only new ones,
+ // as old ones could have been edited or hidden by Monitor
+
+ jQuery.each(result.messages, function(){
+ var container = $('
',{
+ 'class' : 'message ' + (this.type == 'chat' ? 'private_message' : '')
+ }).css('color' , getColour(this.from));
+ $('',{
+ 'class' : 'messageFrom',
+ 'text' : this.from
+ }).appendTo(container);
+ $('',{
+ 'text' : this.body
+ }).appendTo(container);
+
+ container.appendTo(messageDiv);
+ });
+
+ lastMessageUid = result.lastMessageUid;
+ messageDiv.scrollTop(messageDiv.prop('scrollHeight'));
+ }
+
+ rosterDiv.html('');
+ jQuery.each(result.roster, function(){
+ var userDiv = $('', {
+ 'class' : (this == selectedUser ? 'selected' : 'unselected'),
+ 'text' : this
+ }).css('color', getColour(this))
+ .appendTo(rosterDiv);
- // IE hack to ensure onclick event work when rosterDiv is updated. Only being used when in teacher mode.
- if (navigator.appName == "Microsoft Internet Explorer" && MODE == "teacher") {
- rosterDiv.parentNode.innerHTML = rosterDiv.parentNode.innerHTML;
- // following commands are ignored by IE unless we use a delay
- var t1 = setTimeout("scrollMessageDisplay()", 5);
- var t2 = setTimeout("setFocusOnTextarea()", 5);
+ // only Monitor can send a personal message
+ if (MODE == 'teacher') {
+ userDiv.click(function(){
+ userSelected($(this));
+ });
}
+ });
}
-function Roster() {
- this.users = [];
- this.currentIndex = null;
- // objects methods
- this.getUserByNick = getRosterUserByNick;
- this.addUser = AddRosterUser;
- this.updateUser = UpdateRosterUser;
- this.removeUser = RemoveRosterUser;
- this.updateDisplay = UpdateRosterDisplay;
-}
-var roster = new Roster();
-function selectUser(userDiv) {
- if (MODE == "teacher") {
- var newIndex = userDiv.id.substring(userDiv.id.indexOf("-") + 1, userDiv.id.length);
- if (roster.currentIndex == newIndex) {
- roster.currentIndex = null;
- } else {
- roster.currentIndex = newIndex;
- }
-
- // update "send message to" display
- var sendToUserSpan = document.getElementById("sendToUser");
- var sendToEveryoneSpan = document.getElementById("sendToEveryone");
- if (roster.currentIndex == null) {
- sendToEveryoneSpan.style.display = "inline";
- sendToUserSpan.style.display = "none";
- } else {
- sendToEveryoneSpan.style.display = "none";
- sendToUserSpan.style.display = "inline";
- var nick = roster.users[roster.currentIndex].nick;
- var nickElem = createElem("span", null, {color:getColour(nick)}, nick);
- sendToUserSpan.innerHTML = ""; // clear previous user name
- sendToUserSpan.appendChild(nickElem);
- }
- roster.updateDisplay();
+
+function userSelected(userDiv) {
+ var userDivContent = userDiv.html();
+ // is Monitor clicked the already selectedd user, desect him and make message go to everyone
+ selectedUser = userDivContent == selectedUser ? null : userDivContent;
+
+ if (selectedUser) {
+ sendToUserSpan.html(selectedUser)
+ .css('color', getColour(selectedUser));
}
+ sendToEveryoneSpan.css('display', selectedUser ? 'none' : 'inline');
+ sendToUserSpan.css('display', selectedUser ? 'inline' : 'none');
+ $('.selected').attr('class', 'unselected');
+ userDiv.attr('class', selectedUser ? 'selected' : 'unselected');
}
-/* ******* Chat functions ******* */
-function setFocusOnTextarea() {
- document.forms[0].msg.focus();
-}
-function scrollMessageDisplay() {
- var iRespDiv = document.getElementById("iResp");
- iRespDiv.scrollTop = iRespDiv.scrollHeight;
-}
-function generateMessageHTML(nick, message, type) {
- var colour = getColour(nick);
- var fromElem = createElem("div", {attrClass:"messageFrom"}, null, nick);
- var msgElem = createElem("div", {attrClass:"message " + type}, {color:colour}, null);
- msgElem.innerHTML = message;
- msgElem.insertBefore(fromElem, msgElem.firstChild);
- return msgElem;
-}
-function updateMessageDisplay(htmlMessage) {
- var iRespDiv = document.getElementById("iResp");
- iRespDiv.appendChild(htmlMessage);
- iRespDiv.scrollTop = iRespDiv.scrollHeight;
-}
-function sendMsg(aForm) {
- if (aForm.msg.value === "") {
+
+function sendMessage() {
+ var message = sendMessageArea.val();
+ if (!message || message == '') {
return false; // do not send empty messages.
}
- var aMsg = new JSJaCMessage();
- if (MODE == "teacher" && !(roster.currentIndex === null)) {
- var toNick = roster.users[roster.currentIndex].nick;
- aMsg.setTo(CONFERENCEROOM + "/" + toNick);
- aMsg.setType("chat");
- var message = "[" + toNick + "] " + aForm.msg.value;
- aMsg.setBody(message);
- // apending the private message to the incoming window,
- // since the jabber server will not echo sent private messages.
- // TODO: need to check if this is correct behaviour
- if (!(NICK == toNick)) {
- updateMessageDisplay(generateMessageHTML(NICK, message, PRIVATE_MSG));
- }
- } else {
- aMsg.setTo(CONFERENCEROOM);
- aMsg.setType("groupchat");
- aMsg.setBody(aForm.msg.value);
- }
-
- // }
- aMsg.setFrom(USERNAME + "@" + XMPPDOMAIN + "/" + RESOURCE);
- con.send(aMsg);
- aForm.msg.value = "";
- return false;
-}
-/* ******* Event Handlers ******* */
-function handleEvent(aJSJaCPacket) {
- document.getElementById("iResp").innerHTML += "IN (raw):
" + htmlEnc(aJSJaCPacket.xml()) + "
";
-}
-function handleMessage(aJSJaCPacket) {
- var nick = aJSJaCPacket.getFrom().substring(aJSJaCPacket.getFrom().indexOf("/") + 1);
- var message = htmlEnc(aJSJaCPacket.getBody());
- var type = aJSJaCPacket.getType();
- var htmlMessage;
- if (type == "chat") {
- htmlMessage = generateMessageHTML(nick, message, PRIVATE_MSG);
- } else {
- if (type == "groupchat") {
- htmlMessage = generateMessageHTML(nick, message, GROUPCHAT_MSG);
- } else {
- /* somethings wrong, dont add anything.*/
- htmlMessage = "";
- }
- }
- updateMessageDisplay(htmlMessage);
-}
-function handlePresence(presence) {
- var from = presence.getFrom();
- var status = presence.getStatus();
- var show = presence.getShow();
- var type = presence.getType();
- // get x element for MUC
- var x;
- for (var i = 0; i < presence.getNode().getElementsByTagName("x").length; i++) {
- if (presence.getNode().getElementsByTagName("x").item(i).getAttribute("xmlns") == "http://jabber.org/protocol/muc#user") {
- x = presence.getNode().getElementsByTagName("x").item(i);
- break;
- }
- }
+ sendMessageArea.val('');
- // extract nick.
- var nick;
- if (from.indexOf("/") != -1) {
- nick = from.substring(from.indexOf("/") + 1);
- }
- var user = roster.getUserByNick(nick);
- if (!user) {
- user = new RosterUser(nick);
- roster.addUser(user);
- }
- if (show) {
- user.status = show;
- } else {
- if (type) {
- if (type == "unavailable") {
- user.status = "unavailable";
- }
- } else {
- // default: means presence is available.
- user.status = "available";
- }
- }
- roster.updateDisplay();
-}
-function handleConnected() {
- if (MODE == "learner" && LEARNER_FINISHED == "true" && LOCK_ON_FINISHED == "true") {
- // disable sending messages.
- document.getElementById("msgArea").disabled = "disabled";
- var sendButton = document.getElementById("sendButton");
- sendButton.disabled = "disabled";
- sendButton.className = "disabled";
- }
+ // only Monitor can send a personal message
+ var isPrivate = MODE == 'teacher' && selectedUser;
- // clear the response window.
- document.getElementById("iResp").innerHTML = "";
-
- // send presence
- var aPresence = new JSJaCPresence();
- aPresence.setTo(CONFERENCEROOM + "/" + NICK);
- aPresence.setFrom(USERNAME + "@" + XMPPDOMAIN);
- var x = aPresence.getDoc().createElement("x");
- x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
- x.appendChild(aPresence.getDoc().createElement("password")).appendChild(aPresence.getDoc().createTextNode(PASSWORD));
- aPresence.getNode().appendChild(x);
- con.send(aPresence);
-
- // set up roster
- roster = new Roster();
+ $.ajax({
+ url : LEARNING_ACTION,
+ data : {'dispatch' : 'sendMessage',
+ 'toolSessionID' : TOOL_SESSION_ID,
+ 'message' : isPrivate ? '[' + selectedUser + '] ' + message : message,
+ 'user' : isPrivate ? selectedUser : null
+ },
+ cache : false,
+ success : updateChat
+ });
}
-function handleError(e) {
- document.getElementById("msgArea").disabled = "disabled";
- document.getElementById("sendButton").disabled = "disabled";
- document.getElementById("sendButton").className = "disabled";
- document.getElementById("iResp").innerHTML = "Couldn't connect. Please try again...
" + htmlEnc("Code: " + e.getAttribute("code") + "\nType: " + e.getAttribute("type") + "\nCondition: " + e.firstChild.nodeName);
- document.getElementById("roster").innerHTML = "";
-}
-/* ******* Init ******* */
-function doLogin() {
- try {
- // setup args for contructor
- var oArgs = {httpbase:HTTPBASE, timerval:6000};
- if (typeof (oDbg) != "undefined") {
- oArgs.oDbg = oDbg;
- }
- con = new JSJaCHttpBindingConnection(oArgs);
- con.registerHandler("message", handleMessage);
- con.registerHandler("presence", handlePresence);
- con.registerHandler("iq", handleEvent);
- con.registerHandler("onconnect", handleConnected);
- con.registerHandler("onerror", handleError);
-
- // setup args for connect method
- oArgs = {domain:XMPPDOMAIN, username:USERNAME, resource:RESOURCE, pass:PASSWORD};
- con.connect(oArgs);
+function getColour(nick) {
+ // same nick should give same colour
+ var charSum = 0;
+ for ( var i = 0; i < nick.length; i++) {
+ charSum += nick.charCodeAt(i);
}
- catch (e) {
- document.getElementById("iResp").innerHTML = e.toString();
- }
- finally {
- return false;
- }
-}
-function init() {
- if (typeof (Debugger) == "function") {
- var oDbg = new Debugger(4, "simpleclient");
- oDbg.start();
- }
- doLogin();
-}
-onload = init;
-onunload = function () {
- if (typeof (con) != "undefined" && con.disconnect) {
- con.disconnect();
- }
-};
-/* ******* Helper functions ******* */
-function checkEnter(e) { //e is event object passed from function invocation
- var characterCode; //literal character code will be stored in this variable
- if (e && e.which) { //if which property of event object is supported (NN4)
- e = e;
- characterCode = e.which; //character code is contained in NN4's which property
- } else {
- e = event;
- characterCode = e.keyCode; //character code is contained in IE's keyCode property
- }
- if (characterCode == 13) { //if generated character code is equal to ascii 13 (if enter key)
- //document.forms[0].submit(); //submit the form
- sendMsg(document.forms[0]);
- return false;
- } else {
- return true;
- }
-}
-
+ return PALETTE[charSum % (PALETTE.length)];
+}
\ No newline at end of file