4 Strophe.addNamespace('TIME', "urn:xmpp:time");
6 function handleDisconnected() {
7 // Make things (in)visible
14 function handleError(error) {
15 alert("An error occured:" + error);
19 function addBubble(nick) {
22 if (!document.getElementById(id)) {
24 div += '<div id="' + id + '" class="bubble" onmousedown="startDrag(this)" style="display: none">';
25 div += '<a href="#" onclick="' +"$('#" + id + "').hide('slow')" + '">Close</a>';
26 div += '<div id="' + id + 'Chat" class="bubbleChat"></div>';
27 div += '<form id="' + id + 'Form" class="bubbleForm" onsubmit="return sendChatMessage(this,' + "'" + nick + "');" + '" action="#">';
28 div += '<input type="text" name="text" id="' + id + 'Text" class="bubbleForm"/>';
31 $('body').append(div);
33 $('#'+id).show('slow');
36 function handleMessage(msg) {
37 var html, sender, type, body, subject;
39 sender = Strophe.getResourceFromJid(msg.getAttribute('from'));
41 sender = Strophe.xmlescape(sender);
45 type = msg.getAttribute('type');
46 body = msg.getElementsByTagName('body')[0];
48 body = Strophe.xmlescape(Strophe.getText(body));
52 subject = msg.getElementsByTagName('subject')[0];
54 subject = Strophe.xmlescape(Strophe.getText(subject));
59 html += '<div class="msg">';
62 if (body.search(/^\/me/) === 0) {
63 body = body.replace(/^\/me/, sender);
64 html += '<span class="sender">';
66 html += '</span></div>';
68 html += '<span class="sender">';
71 html += body + '</div>';
74 html += '<span class="server">';
75 html += body + '</span></div>';
78 html += '<span class="server">';
79 html += "The subject is: " + subject + '</span></div>';
86 $('#' + sender + 'BubbleChat').append(html);
87 document.getElementById(sender + 'BubbleChat').lastChild.scrollIntoView();
89 $('#chat').append(html);
90 document.getElementById('chat').lastChild.scrollIntoView();
96 function handlePresence(presence) {
97 var roster_list, nick, type, element;
98 if (Strophe.getBareJidFromJid(presence.getAttribute('from')) != room) {
101 roster_list = document.getElementById('roster_list');
102 nick = Strophe.xmlescape(Strophe.getResourceFromJid(presence.getAttribute('from')));
103 type = presence.getAttribute('type');
104 if (type == 'unavailable') {
105 element = document.getElementById(nick);
106 roster_list.removeChild(element);
107 $('#chat').append('<div class="msg"><span class="server">' + nick + ' left the groupchat</span></div>');
109 roster_list.innerHTML += '<li id="' + nick + '" onclick="addBubble(' + "'" + nick + "')" + '" >' + nick + '</li>';
110 $('#chat').append('<div class="msg"><span class="server">' + nick + ' joined the groupchat</span></div>');
116 function handleIQ(iq) {
117 var to, from, type, id, reply;
118 to = iq.getAttribute('to');
119 from = iq.getAttribute('from');
120 type = iq.getAttribute('type');
121 id = iq.getAttribute('id');
123 //FIXME: Clients SHOULD send the content of the original stanza back for analysis
124 reply = $iq({to: from, from: to, id: id, type: 'error'}).c('error', {type: 'cancel'}).c('feature-not-implemented', {xmlns: Strophe.NS.STANZAS});
125 connection.send(reply.tree());
130 function handleIqVersion(iq) {
131 var to, from, id, reply;
132 to = iq.getAttribute('to');
133 from = iq.getAttribute('from');
134 id = iq.getAttribute('id');
136 reply = $iq({type: 'result', to: from, from: to, id: id}).c('query', {xmlns: Strophe.NS.VERSION}).c('name').t('XMPPChat').up().c('version').t('git').up().c('os').t(navigator.userAgent);
137 connection.send(reply.tree());
142 function handleIqTime(iq) {
143 var now, to, from, id, year, month, day, hours, minutes, seconds, offsetHour, offsetMin, reply;
145 to = iq.getAttribute('to');
146 from = iq.getAttribute('from');
147 id = iq.getAttribute('id');
149 year = now.getUTCFullYear();
150 month = now.getUTCMonth() + 1;
151 month = (month < 10) ? '0' + month : month;
152 day = now.getUTCDate();
153 day = (day < 10) ? '0' + day : day;
154 hours = now.getUTCHours();
155 hours = (hours < 10) ? '0' + hours : hours;
156 minutes = now.getUTCMinutes();
157 minutes = (minutes < 10) ? '0' + minutes : minutes;
158 seconds = now.getUTCSeconds();
159 seconds = (seconds < 10) ? '0' + seconds : seconds;
160 offsetMin = now.getTimezoneOffset() * (-1);
161 offsetHour = offsetMin / 60;
162 offsetHour = (offsetHour < 10) ? '0' + offsetHour : offsetHour;
163 offsetMin = offsetMin % 60;
164 offsetMin = (offsetMin < 0) ? (-1)*offsetMin : offsetMin;
165 offsetMin = (offsetMin < 10) ? '0' + offsetMin : offsetMin;
167 reply = $iq({type: 'result', from: to, to: from, id: id}).c('time', {xmlns: Strophe.NS.TIME}).c('utc').t(year + '-' + month + '-' + day + 'T' + hours + ':' + minutes + ':' + seconds + 'Z').up().c('tzo').t( ((offsetHour >= 0) ? '+':'') + offsetHour + ':' + offsetMin);
169 connection.send(reply.tree());
174 function sendMessage(aForm) {
176 if (aForm.text.value) {
177 message = $msg({type: 'groupchat', to: room}).c('body').t(aForm.text.value);
178 connection.send(message.tree());
179 aForm.text.value = '';
184 function sendChatMessage(aForm, to) {
185 var body, message, html;
186 if (aForm.text.value) {
187 body = aForm.text.value;
188 message = $msg({type: 'chat', to: room + '/' + to}).c('body').t(body);
189 connection.send(message.tree());
190 aForm.text.value = '';
192 html += '<div class="msg">';
193 html += '<span class="sender">';
196 html += Strophe.xmlescape(body) + '</div>';
197 document.getElementById(to + 'BubbleChat').innerHTML += html;
198 document.getElementById(to + 'BubbleChat').lastChild.scrollIntoView();
204 function onConnect(status) {
205 if (status == Strophe.Status.CONNFAIL) {
206 handleError('Failed to connect');
207 } else if (status == Strophe.Status.DISCONNECTED) {
208 handleDisconnected();
209 } else if (status == Strophe.Status.CONNECTED) {
210 // Add handlers connection.addHandler(callback, namespace, stanza_name, type, id, from, options)
211 connection.addHandler(handleMessage, null, 'message');
212 connection.addHandler(handlePresence, null, 'presence');
213 connection.addHandler(handleIQ, null, 'iq');
215 connection.addHandler(handleIqVersion, Strophe.NS.VERSION, 'iq');
216 connection.addHandler(handleIqTime, Strophe.NS.TIME, 'iq');
218 connection.send($pres().tree());
219 connection.send($pres({to: room + '/' + nickname}).tree());
221 // Make things (in)visible
229 function doLogin(aForm) {
230 if (!aForm.nickname.value) {
234 connection = new Strophe.Connection(BOSH_LOCATION);
235 connection.connect(jid, password, onConnect);
237 nickname = aForm.nickname.value;
245 function doDisconnect(aForm) {
247 connection.send($pres({to: room, type: 'unavailable'}).tree());
249 connection.disconnect();
255 var dragElement = null;
261 function startDrag(element) {
262 dragElement = element;
263 offX = mouseX - dragElement.offsetLeft;
264 offY = mouseY - dragElement.offsetTop;
267 function doDrag(eve) {
272 dragElement.style.left = (mouseX - offX) + 'px';
273 dragElement.style.top = (mouseY - offY) + 'px';
277 function stopDrag(eve) {
281 window.onunload = window.onbeforeunload = doDisconnect;
283 window.onmousemove = doDrag;
285 window.onmouseup = stopDrag;