src/js/supportchat.js

changeset 36
562ff07a3968
parent 34
510ca613996a
child 37
010783d24970
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/js/supportchat.js	Thu Apr 01 16:07:16 2010 +0100
@@ -0,0 +1,234 @@
+/* Config */
+
+var support_config = {
+	login_domain: "anon.localhost",
+	bosh_url: "/http-bind",
+	muc_server: "support.localhost",
+	team_rooms: {
+		"Sales": "sales@support.localhost",
+		"Technical": "technical@support.localhost"
+	},
+	send_invites: true
+};
+
+/*** XMPP handling */
+var conn = null;
+
+/* Called by Strophe when status of connection changes
+   (from disconnected to connected, vice-versa, etc.)
+*/
+function handle_connection_status(status, err)
+{
+	if(err)
+		alert("Connection error: " + err); //FIXME: Handle gracefully
+}
+
+/* Initiate the connection to the XMPP server */
+function start_connection()
+{
+	conn = new Strophe.Connection(support_config.bosh_url);
+	var ret = true;
+	try
+	{
+		conn.connect(support_config.login_domain, null, handle_connection_status, 50);
+	}
+	catch(e)
+	{
+		alert("Connection error: " + e); //FIXME
+		ret = false;
+	}
+	return ret;
+}
+
+
+/*** UI handling */
+
+/* Initial UI state */
+var ui_state = "question";
+
+/* Change the UI state (question, wait, converse) */
+function set_ui_state(new_state)
+{
+	if(ui_state != new_state)
+	{
+		$("#support-"+ui_state).hide();
+		$("#support-"+(ui_state=new_state)).show();
+	}
+}
+
+/* Handle the user submitting the question form */
+function on_question_submit()
+{
+	var question_type = $("#support-question-type").val();
+	var question_name = $("#support-question-name").val();
+	var question_text = $("#support-question-text").val();
+	
+	var our_nick = question_name;
+	
+	set_ui_state("wait");
+	
+	// Create our question room
+	var question_muc = new MUC(conn, {
+		// Handle room joins
+		joined: function (stanza, muc, nick)
+		{
+			if(nick == our_nick)
+				// We joined the question room, now join the team room and tell them
+				team_muc.join(support_config.team_rooms[question_type], our_nick);
+			else if(ui_state == "wait")
+			{
+				// We were waiting for an assistant, and one just joined
+				var html = "<span class='muc-message'><span class='muc-nick'>" + htmlescape(nick) + "</span>" + " is answering your query</span><br/>\n";
+				$("#support-log").append(html).scrollTop($("#support-log")[0].scrollHeight);
+				$("#support-send-button").click(function ()
+					{
+						question_muc.send_message($("#support-input").val());
+						$("#support-input").val("");
+					});
+				set_ui_state("converse");
+			}
+		},
+		
+		// Handle incoming messages
+		message: function (stanza, muc, nick, message)
+		{
+			var html = "<span class='muc-message'><span class='muc-nick'>" + htmlescape(nick) + "</span>" + ": " + htmlescape(message) + "</span><br/>\n";
+			$("#support-log").append(html).scrollTop($("#support-log")[0].scrollHeight);
+		}
+	});
+
+	// Get a unique room name from the server and then join the question MUC
+	conn.sendIQ($iq({to: support_config.muc_server, type: "get"})
+		.c("query", { xmlns: "http://jabber.org/protocol/muc#unique" }),
+		function (result) // Success
+		{
+			var unique = Strophe.getText(result.getElementsByTagName("unique")[0]);
+			question_muc.join(unique + "@" + support_config.muc_server, our_nick);
+		},
+		function (result) // Failure to get unique room name
+		{
+			var unique = "support-"+Math.floor(Math.random()*512);
+			question_muc.join(unique + "@" + support_config.muc_server, our_nick);
+		});
+	
+	// Create the team MUC object (it will be joined after we join the question MUC)
+	var team_muc = new MUC(conn, {
+		joined: function (stanza, muc, nick)
+		{
+			if(nick != our_nick)
+				return;
+			
+			var sent = false;
+			for(var nick in team_muc.occupants)
+			{
+				//FIXME: Check affiliation
+				sent = true;
+				if(nick == our_nick)
+					continue;
+				else if(support_config.send_invites)
+					team_muc.send_invite(team_muc.jid+"/"+nick, question_text + "\n" + question_muc.jid);
+				else
+					team_muc.send_private_message(nick, question_text + "\n" + question_muc.jid);
+			}
+			if(!sent)
+			{
+				set_ui_state("offline");
+			}
+		},
+		
+		error: function (stanza, muc, error)
+		{
+			if(error == "conflict")
+			{
+				our_nick += "_";
+				muc.join(support_config.team_rooms[question_type], our_nick);
+			}
+			else
+				alert("unhandled error: " + error);
+		}
+	});
+}
+
+function build_ui()
+{
+	return $(' \
+	<div id="support-chat"> \
+		<div id="support-question"> \
+			<h2>What is the nature of your question?</h2> \
+			<select id="support-question-type"> \
+				<option>Sales</option> \
+				<option>Technical</option> \
+			</select> \
+			<h2>What is your name?</h2> \
+			<input id="support-question-name" type="text" /> \
+			<h2>Your question:</h2> \
+			<textarea id="support-question-text"></textarea><br/> \
+			<input id="support-question-submit" type="submit" /> \
+		</div> \
+		<div id="support-wait"> \
+			Please wait while we find someone to \
+			answer your query... \
+			<br/><br/><br/><br/> \
+			<center><img src="waiting.gif" alt="Waiting" /></center> \
+		</div> \
+		<div id="support-converse"> \
+			<div id="support-log"></div> \
+			<div id="support-input-container"><textarea id="support-input" type="text" value=""></textarea></div> \
+			<input id="support-send-button" type="submit" value="Send" /> \
+			<div style="clear:right;"></div> \
+		</div> \
+		<div id="support-offline"> \
+			<p>Sorry, there are no assistants available \
+			   to answer your question at the moment. \
+			</p> \
+			<div id="support-offline-form"> \
+				<p>To receive a reply to your question via \
+				   email, please enter your email address \
+				   below: \
+				</p> \
+				<input id="support-offline-email" type="text" /> \
+				<input id="support-send-button" type="submit" value="Submit" /> \
+			</div> \
+			<div id="support-offline-thanks"> \
+				<p>Thank you. Your question has been submitted \
+				   and will be replied to as soon as an assistant \
+				   becomes available.</p> \
+			</div> \
+		</div> \
+	</div> \
+	');
+}
+
+function display_ui()
+{
+	// Display pop-up, showing question form
+	var ui = build_ui();
+	
+	ui.appendTo("body");
+	
+	if(start_connection())
+	{
+		$("#support-question-submit").click(on_question_submit);
+		ui.dialog({
+			title:"Live Support",
+			height: 400,
+			width: 285
+		});
+	}
+}
+
+/*** Helper functions */
+function htmlescape(s)
+{
+	return s.replace(/&/g,'&amp;').
+		replace(/>/g,'&gt;').
+		replace(/</g,'&lt;').
+		replace(/"/g,'&quot;');
+}
+
+function activate_links()
+{
+	$("[href='#support-chat']").click(display_ui);
+}
+
+$(activate_links); //FIXME (debugging)

mercurial