--- /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,'&'). + replace(/>/g,'>'). + replace(/</g,'<'). + replace(/"/g,'"'); +} + +function activate_links() +{ + $("[href='#support-chat']").click(display_ui); +} + +$(activate_links);