|
1 /* Config */ |
|
2 |
|
3 var support_config = { |
|
4 login_domain: "anon.localhost", |
|
5 bosh_url: "/http-bind", |
|
6 muc_server: "support.localhost", |
|
7 team_rooms: { |
|
8 "Sales": "sales@support.localhost", |
|
9 "Technical": "technical@support.localhost" |
|
10 }, |
|
11 send_invites: true, |
|
12 offline_support: "support@localhost", |
|
13 alternative_url: "http://www.google.co.uk/" |
|
14 }; |
|
15 |
|
16 /*** XMPP handling */ |
|
17 var conn = null; |
|
18 |
|
19 /*** Query information */ |
|
20 var question_type; // E.g. "Sales", "Technical" |
|
21 var question_name; // Name of the submitter |
|
22 var question_text; // The query itself |
|
23 |
|
24 /* Called by Strophe when status of connection changes |
|
25 (from disconnected to connected, vice-versa, etc.) |
|
26 */ |
|
27 function handle_connection_status(status, err) |
|
28 { |
|
29 if(err) |
|
30 set_ui_state("error"); |
|
31 } |
|
32 |
|
33 /* Initiate the connection to the XMPP server */ |
|
34 function start_connection() |
|
35 { |
|
36 conn = new Strophe.Connection(support_config.bosh_url); |
|
37 var ret = true; |
|
38 try |
|
39 { |
|
40 conn.connect(support_config.login_domain, null, handle_connection_status, 50); |
|
41 } |
|
42 catch(e) |
|
43 { |
|
44 ret = false; |
|
45 } |
|
46 return ret; |
|
47 } |
|
48 |
|
49 /*** UI handling */ |
|
50 |
|
51 /* Initial UI state */ |
|
52 var ui_state = "question"; |
|
53 |
|
54 /* Called to change the UI state (question, wait, converse) */ |
|
55 function set_ui_state(new_state) |
|
56 { |
|
57 if(ui_state != new_state) |
|
58 { |
|
59 $("#support-"+ui_state).hide(); |
|
60 $("#support-"+(ui_state=new_state)).show(); |
|
61 } |
|
62 } |
|
63 |
|
64 /* Handle the user submitting the question form */ |
|
65 function on_question_submit() |
|
66 { |
|
67 question_type = $("#support-question-type").val(); |
|
68 question_name = $("#support-question-name").val(); |
|
69 question_text = $("#support-question-text").val(); |
|
70 |
|
71 var our_nick = question_name; |
|
72 |
|
73 set_ui_state("wait"); |
|
74 |
|
75 // Create our question room |
|
76 var question_muc = new MUC(conn, { |
|
77 // Handle room joins |
|
78 joined: function (stanza, muc, occupant) |
|
79 { |
|
80 if(occupant.nick == our_nick) |
|
81 // We joined the question room, now join the team room and tell them |
|
82 team_muc.join(support_config.team_rooms[question_type], our_nick); |
|
83 else if(ui_state == "wait") |
|
84 { |
|
85 // We were waiting for an assistant, and one just joined |
|
86 var html = "<span class='muc-message'><span class='muc-nick'>" + htmlescape(occupant.nick) + "</span>" + " is answering your query</span><br/>\n"; |
|
87 $("#support-log").append(html).scrollTop($("#support-log")[0].scrollHeight); |
|
88 $("#support-send-button").click(function () |
|
89 { |
|
90 question_muc.send_message($("#support-input").val()); |
|
91 $("#support-input").val(""); |
|
92 }); |
|
93 set_ui_state("converse"); |
|
94 } |
|
95 }, |
|
96 |
|
97 // Handle incoming messages |
|
98 message: function (stanza, muc, nick, message) |
|
99 { |
|
100 var html = "<span class='muc-message'><span class='muc-nick'>" + htmlescape(nick) + "</span>" + ": " + htmlescape(message) + "</span><br/>\n"; |
|
101 $("#support-log").append(html).scrollTop($("#support-log")[0].scrollHeight); |
|
102 } |
|
103 }); |
|
104 |
|
105 // Get a unique room name from the server and then join the question MUC |
|
106 conn.sendIQ($iq({to: support_config.muc_server, type: "get"}) |
|
107 .c("query", { xmlns: "http://jabber.org/protocol/muc#unique" }), |
|
108 function (result) // Success |
|
109 { |
|
110 var unique = Strophe.getText(result.getElementsByTagName("unique")[0]); |
|
111 question_muc.join(unique + "@" + support_config.muc_server, our_nick); |
|
112 }, |
|
113 function (result) // Failure to get unique room name |
|
114 { |
|
115 var unique = "support-"+Math.floor(Math.random()*512); |
|
116 question_muc.join(unique + "@" + support_config.muc_server, our_nick); |
|
117 }); |
|
118 |
|
119 // Create the team MUC object (it will be joined after we join the question MUC) |
|
120 var team_muc = new MUC(conn, { |
|
121 // Someone joined the team MUC |
|
122 joined: function (stanza, muc, occupant) |
|
123 { |
|
124 if(occupant.nick != our_nick) |
|
125 return; |
|
126 |
|
127 var sent = false; |
|
128 for(var nick in team_muc.occupants) |
|
129 { |
|
130 if(team_muc.occupants[nick].affiliation == "none" || nick == our_nick) |
|
131 continue; |
|
132 sent = true; |
|
133 if(support_config.send_invites) |
|
134 team_muc.send_invite(team_muc.jid+"/"+nick, question_text + "\n" + question_muc.jid); |
|
135 else |
|
136 team_muc.send_private_message(nick, question_text + "\n" + question_muc.jid); |
|
137 } |
|
138 if(!sent) |
|
139 { |
|
140 set_ui_state("offline"); |
|
141 } |
|
142 }, |
|
143 |
|
144 error: function (stanza, muc, error) |
|
145 { |
|
146 if(error == "conflict") |
|
147 { |
|
148 our_nick += "_"; |
|
149 muc.join(support_config.team_rooms[question_type], our_nick); |
|
150 } |
|
151 else |
|
152 set_ui_state("error"); |
|
153 } |
|
154 }); |
|
155 } |
|
156 |
|
157 function build_ui() |
|
158 { |
|
159 return $(" \ |
|
160 <div id='support-chat'> \ |
|
161 <div id='support-question'> \ |
|
162 <h2>What is the nature of your question?</h2> \ |
|
163 <select id='support-question-type'> \ |
|
164 <option>Sales</option> \ |
|
165 <option>Technical</option> \ |
|
166 </select> \ |
|
167 <h2>What is your name?</h2> \ |
|
168 <input id='support-question-name' type='text' /> \ |
|
169 <h2>Your question:</h2> \ |
|
170 <textarea id='support-question-text'></textarea><br/> \ |
|
171 <input id='support-question-submit' type='submit' /> \ |
|
172 </div> \ |
|
173 <div id='support-wait'> \ |
|
174 Please wait while we find someone to \ |
|
175 answer your query... \ |
|
176 <br/><br/><br/><br/> \ |
|
177 <center><img src='waiting.gif' alt='Waiting' /></center> \ |
|
178 </div> \ |
|
179 <div id='support-converse'> \ |
|
180 <div id='support-log'></div> \ |
|
181 <div id='support-input-container'><textarea id='support-input' type='text' value=''></textarea></div> \ |
|
182 <input id='support-send-button' type='submit' value='Send' /> \ |
|
183 <div style='clear:right;'></div> \ |
|
184 </div> \ |
|
185 <div id='support-offline'> \ |
|
186 <p>Sorry, there are no assistants available \ |
|
187 to answer your question at the moment. \ |
|
188 </p> \ |
|
189 <div id='support-offline-form'> \ |
|
190 <p>To receive a reply to your question via \ |
|
191 email, please enter your email address \ |
|
192 below: \ |
|
193 </p> \ |
|
194 <input id='support-offline-email' type='text' /> \ |
|
195 <input id='support-offline-submit-button' type='submit' value='Submit' /> \ |
|
196 </div> \ |
|
197 <div id='support-offline-thanks'> \ |
|
198 <p>Thank you. Your question has been submitted \ |
|
199 and will be replied to as soon as an assistant \ |
|
200 becomes available.</p> \ |
|
201 </div> \ |
|
202 </div> \ |
|
203 <div id='support-error'> \ |
|
204 <p>Sorry, there is a problem with the live support \ |
|
205 service at the moment. Please see our \ |
|
206 <a href='"+support_config.alternative_url+"'>alternative \ |
|
207 support channels</a> to receive assistance. \ |
|
208 </p> \ |
|
209 </div> \ |
|
210 </div> \ |
|
211 "); |
|
212 } |
|
213 |
|
214 function display_ui() |
|
215 { |
|
216 // Display pop-up, showing question form |
|
217 var ui = build_ui(); |
|
218 |
|
219 ui.appendTo("body"); |
|
220 |
|
221 $("#support-question-submit").click(on_question_submit); |
|
222 $("#support-offline-submit-button").click(function () |
|
223 { |
|
224 $("#support-offline-form").hide(); |
|
225 conn.send($msg({to: support_config.offline_support, type: "normal"}) |
|
226 .c("subject").t("Support query from " + question_name).up() |
|
227 .c("body").t(question_text + "\n\nReply via email to: "+ |
|
228 $("#support-offline-email").val())); |
|
229 $("#support-offline-thanks").show(); |
|
230 }); |
|
231 |
|
232 ui.dialog({ |
|
233 title:"Live Support", |
|
234 height: 400, |
|
235 width: 285 |
|
236 }); |
|
237 |
|
238 if(!start_connection()) |
|
239 { |
|
240 set_ui_state("error"); |
|
241 } |
|
242 } |
|
243 |
|
244 /*** Helper functions */ |
|
245 function htmlescape(s) |
|
246 { |
|
247 return s.replace(/&/g,'&'). |
|
248 replace(/>/g,'>'). |
|
249 replace(/</g,'<'). |
|
250 replace(/"/g,'"'); |
|
251 } |
|
252 |
|
253 function activate_links() |
|
254 { |
|
255 $("[href='#support-chat']").click(display_ui); |
|
256 } |
|
257 |
|
258 $(activate_links); |