support-chat/js/supportchat.js

changeset 48
12b42931151a
parent 44
094640b971b4
child 50
53bfdcb686f7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/support-chat/js/supportchat.js	Mon Apr 05 13:15:59 2010 +0100
@@ -0,0 +1,258 @@
+/* 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,
+	offline_support: "support@localhost",
+	alternative_url: "http://www.google.co.uk/"
+};
+
+/*** XMPP handling */
+var conn = null;
+
+/*** Query information */
+var question_type; // E.g. "Sales", "Technical"
+var question_name; // Name of the submitter
+var question_text; // The query itself
+
+/* Called by Strophe when status of connection changes
+   (from disconnected to connected, vice-versa, etc.)
+*/
+function handle_connection_status(status, err)
+{
+	if(err)
+		set_ui_state("error");
+}
+
+/* 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)
+	{
+		ret = false;
+	}
+	return ret;
+}
+
+/*** UI handling */
+
+/* Initial UI state */
+var ui_state = "question";
+
+/* Called to 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()
+{
+	question_type = $("#support-question-type").val();
+	question_name = $("#support-question-name").val();
+	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, occupant)
+		{
+			if(occupant.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(occupant.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, {
+		// Someone joined the team MUC
+		joined: function (stanza, muc, occupant)
+		{
+			if(occupant.nick != our_nick)
+				return;
+			
+			var sent = false;
+			for(var nick in team_muc.occupants)
+			{
+				if(team_muc.occupants[nick].affiliation == "none" || nick == our_nick)
+					continue;
+				sent = true;
+				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
+				set_ui_state("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-offline-submit-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 id='support-error'> \
+			<p>Sorry, there is a problem with the live support \
+			   service at the moment. Please see our \
+			   <a href='"+support_config.alternative_url+"'>alternative \
+			   support channels</a> to receive assistance. \
+			</p> \
+		</div> \
+	</div> \
+	");
+}
+
+function display_ui()
+{
+	// Display pop-up, showing question form
+	var ui = build_ui();
+	
+	ui.appendTo("body");
+	
+	$("#support-question-submit").click(on_question_submit);
+	$("#support-offline-submit-button").click(function ()
+	{
+		$("#support-offline-form").hide();
+		conn.send($msg({to: support_config.offline_support, type: "normal"})
+			.c("subject").t("Support query from " + question_name).up()
+			.c("body").t(question_text + "\n\nReply via email to: "+
+				$("#support-offline-email").val()));
+		$("#support-offline-thanks").show();
+	});
+
+	ui.dialog({
+		title:"Live Support",
+		height: 400,
+		width: 285
+	});
+
+	if(!start_connection())
+	{
+		set_ui_state("error");
+	}
+}
+
+/*** 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);

mercurial