2 *Plugin to implement the MUC extension.
3 http://xmpp.org/extensions/xep-0045.html
5 Nathan Zorn <nathan.zorn@gmail.com>
6 *Complete CoffeeScript rewrite:
7 Andreas Guth <guth@dbis.rwth-aachen.de>
9 var Occupant, RoomConfig, XmppRoom,
10 hasProp = {}.hasOwnProperty,
11 bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
13 Strophe.addConnectionPlugin('muc', {
19 Initialize the MUC plugin. Sets the correct connection object and
22 init: function(conn) {
23 this._connection = conn;
24 this._muc_handler = null;
25 Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC + "#owner");
26 Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");
27 Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user");
28 Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig");
29 return Strophe.addNamespace('MUC_REGISTER', "jabber:iq:register");
33 Join a multi-user chat room
35 (String) room - The multi-user chat room to join.
36 (String) nick - The nickname to use in the chat room. Optional
37 (Function) msg_handler_cb - The function call to handle messages from the
39 (Function) pres_handler_cb - The function call back to handle presence
41 (Function) roster_cb - The function call to handle roster info in the chat room
42 (String) password - The optional password to use. (password protected
44 (Object) history_attrs - Optional attributes for retrieving history
45 (XML DOM Element) extended_presence - Optional XML for extending presence
47 join: function(room, nick, msg_handler_cb, pres_handler_cb, roster_cb, password, history_attrs, extended_presence) {
49 room_nick = this.test_append_nick(room, nick);
51 from: this._connection.jid,
56 if (history_attrs != null) {
57 msg = msg.c("history", history_attrs).up();
59 if (password != null) {
60 msg.cnode(Strophe.xmlElement("password", [], password));
62 if (extended_presence != null) {
63 msg.up().cnode(extended_presence);
65 if (this._muc_handler == null) {
66 this._muc_handler = this._connection.addHandler((function(_this) {
67 return function(stanza) {
68 var from, handler, handlers, i, id, len, roomname, x, xmlns, xquery;
69 from = stanza.getAttribute('from');
73 roomname = from.split("/")[0];
74 if (!_this.rooms[roomname]) {
77 room = _this.rooms[roomname];
79 if (stanza.nodeName === "message") {
80 handlers = room._message_handlers;
81 } else if (stanza.nodeName === "presence") {
82 xquery = stanza.getElementsByTagName("x");
83 if (xquery.length > 0) {
84 for (i = 0, len = xquery.length; i < len; i++) {
86 xmlns = x.getAttribute("xmlns");
87 if (xmlns && xmlns.match(Strophe.NS.MUC)) {
88 handlers = room._presence_handlers;
94 for (id in handlers) {
95 handler = handlers[id];
96 if (!handler(stanza, room)) {
104 if (!this.rooms.hasOwnProperty(room)) {
105 this.rooms[room] = new XmppRoom(this, room, nick, password);
106 if (pres_handler_cb) {
107 this.rooms[room].addHandler('presence', pres_handler_cb);
109 if (msg_handler_cb) {
110 this.rooms[room].addHandler('message', msg_handler_cb);
113 this.rooms[room].addHandler('roster', roster_cb);
115 this.roomNames.push(room);
117 return this._connection.send(msg);
121 Leave a multi-user chat room
123 (String) room - The multi-user chat room to leave.
124 (String) nick - The nick name used in the room.
125 (Function) handler_cb - Optional function to handle the successful leave.
126 (String) exit_msg - optional exit message.
128 iqid - The unique id for the room leave.
130 leave: function(room, nick, handler_cb, exit_msg) {
131 var id, presence, presenceid, room_nick;
132 id = this.roomNames.indexOf(room);
133 delete this.rooms[room];
135 this.roomNames.splice(id, 1);
136 if (this.roomNames.length === 0) {
137 this._connection.deleteHandler(this._muc_handler);
138 this._muc_handler = null;
141 room_nick = this.test_append_nick(room, nick);
142 presenceid = this._connection.getUniqueId();
146 from: this._connection.jid,
149 if (exit_msg != null) {
150 presence.c("status", exit_msg);
152 if (handler_cb != null) {
153 this._connection.addHandler(handler_cb, null, "presence", null, presenceid);
155 this._connection.send(presence);
161 (String) room - The multi-user chat room name.
162 (String) nick - The nick name used in the chat room.
163 (String) message - The plaintext message to send to the room.
164 (String) html_message - The message to send to the room with html markup.
165 (String) type - "groupchat" for group chat messages o
166 "chat" for private chat messages
168 msgiq - the unique id used to send the message
170 message: function(room, nick, message, html_message, type, msgid) {
171 var msg, parent, room_nick;
172 room_nick = this.test_append_nick(room, nick);
173 type = type || (nick != null ? "chat" : "groupchat");
174 msgid = msgid || this._connection.getUniqueId();
177 from: this._connection.jid,
180 }).c("body").t(message);
182 if (html_message != null) {
184 xmlns: Strophe.NS.XHTML_IM
186 xmlns: Strophe.NS.XHTML
188 if (msg.node.childNodes.length === 0) {
189 parent = msg.node.parentNode;
191 msg.node.removeChild(parent);
197 xmlns: "jabber:x:event"
199 this._connection.send(msg);
204 Convenience Function to send a Message to all Occupants
206 (String) room - The multi-user chat room name.
207 (String) message - The plaintext message to send to the room.
208 (String) html_message - The message to send to the room with html markup.
209 (String) msgid - Optional unique ID which will be set as the 'id' attribute of the stanza
211 msgiq - the unique id used to send the message
213 groupchat: function(room, message, html_message, msgid) {
214 return this.message(room, null, message, html_message, void 0, msgid);
218 Send a mediated invitation.
220 (String) room - The multi-user chat room name.
221 (String) receiver - The invitation's receiver.
222 (String) reason - Optional reason for joining the room.
224 msgiq - the unique id used to send the invitation
226 invite: function(room, receiver, reason) {
227 var invitation, msgid;
228 msgid = this._connection.getUniqueId();
230 from: this._connection.jid,
234 xmlns: Strophe.NS.MUC_USER
238 if (reason != null) {
239 invitation.c('reason', reason);
241 this._connection.send(invitation);
246 Send a mediated multiple invitation.
248 (String) room - The multi-user chat room name.
249 (Array) receivers - The invitation's receivers.
250 (String) reason - Optional reason for joining the room.
252 msgiq - the unique id used to send the invitation
254 multipleInvites: function(room, receivers, reason) {
255 var i, invitation, len, msgid, receiver;
256 msgid = this._connection.getUniqueId();
258 from: this._connection.jid,
262 xmlns: Strophe.NS.MUC_USER
264 for (i = 0, len = receivers.length; i < len; i++) {
265 receiver = receivers[i];
266 invitation.c('invite', {
269 if (reason != null) {
270 invitation.c('reason', reason);
275 this._connection.send(invitation);
280 Send a direct invitation.
282 (String) room - The multi-user chat room name.
283 (String) receiver - The invitation's receiver.
284 (String) reason - Optional reason for joining the room.
285 (String) password - Optional password for the room.
287 msgiq - the unique id used to send the invitation
289 directInvite: function(room, receiver, reason, password) {
290 var attrs, invitation, msgid;
291 msgid = this._connection.getUniqueId();
293 xmlns: 'jabber:x:conference',
296 if (reason != null) {
297 attrs.reason = reason;
299 if (password != null) {
300 attrs.password = password;
303 from: this._connection.jid,
307 this._connection.send(invitation);
312 Queries a room for a list of occupants
313 (String) room - The multi-user chat room name.
314 (Function) success_cb - Optional function to handle the info.
315 (Function) error_cb - Optional function to handle an error.
317 id - the unique id used to send the info request
319 queryOccupants: function(room, success_cb, error_cb) {
322 xmlns: Strophe.NS.DISCO_ITEMS
325 from: this._connection.jid,
328 }).c('query', attrs);
329 return this._connection.sendIQ(info, success_cb, error_cb);
333 Start a room configuration.
335 (String) room - The multi-user chat room name.
336 (Function) handler_cb - Optional function to handle the config form.
338 id - the unique id used to send the configuration request
340 configure: function(room, handler_cb, error_cb) {
346 xmlns: Strophe.NS.MUC_OWNER
348 stanza = config.tree();
349 return this._connection.sendIQ(stanza, handler_cb, error_cb);
353 Cancel the room configuration
355 (String) room - The multi-user chat room name.
357 id - the unique id used to cancel the configuration.
359 cancelConfigure: function(room) {
365 xmlns: Strophe.NS.MUC_OWNER
367 xmlns: "jabber:x:data",
370 stanza = config.tree();
371 return this._connection.sendIQ(stanza);
375 Save a room configuration.
377 (String) room - The multi-user chat room name.
378 (Array) config- Form Object or an array of form elements used to configure the room.
380 id - the unique id used to save the configuration.
382 saveConfiguration: function(room, config, success_cb, error_cb) {
383 var conf, i, iq, len, stanza;
388 xmlns: Strophe.NS.MUC_OWNER
390 if (typeof Strophe.x !== "undefined" && typeof Strophe.x.Form !== "undefined" && config instanceof Strophe.x.Form) {
391 config.type = "submit";
392 iq.cnode(config.toXML());
395 xmlns: "jabber:x:data",
398 for (i = 0, len = config.length; i < len; i++) {
404 return this._connection.sendIQ(stanza, success_cb, error_cb);
409 (String) room - The multi-user chat room name.
411 id - the unique id used to create the chat room.
413 createInstantRoom: function(room, success_cb, error_cb) {
419 xmlns: Strophe.NS.MUC_OWNER
421 xmlns: "jabber:x:data",
424 return this._connection.sendIQ(roomiq.tree(), success_cb, error_cb);
429 (String) room - The multi-user chat room name.
430 (Object) config - the configuration. ex: {"muc#roomconfig_publicroom": "0", "muc#roomconfig_persistentroom": "1"}
432 id - the unique id used to create the chat room.
434 createConfiguredRoom: function(room, config, success_cb, error_cb) {
440 xmlns: Strophe.NS.MUC_OWNER
442 xmlns: "jabber:x:data",
447 }).c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up();
449 if (!hasProp.call(config, k)) continue;
453 }).c('value').t(v).up().up();
455 return this._connection.sendIQ(roomiq.tree(), success_cb, error_cb);
459 Set the topic of the chat room.
461 (String) room - The multi-user chat room name.
462 (String) topic - Topic message.
464 setTopic: function(room, topic) {
468 from: this._connection.jid,
471 xmlns: "jabber:client"
473 return this._connection.send(msg.tree());
477 Internal Function that Changes the role or affiliation of a member
478 of a MUC room. This function is used by modifyRole and modifyAffiliation.
479 The modification can only be done by a room moderator. An error will be
480 returned if the user doesn't have permission.
482 (String) room - The multi-user chat room name.
483 (Object) item - Object with nick and role or jid and affiliation attribute
484 (String) reason - Optional reason for the change.
485 (Function) handler_cb - Optional callback for success
486 (Function) error_cb - Optional callback for error
488 iq - the id of the mode change request.
490 _modifyPrivilege: function(room, item, reason, handler_cb, error_cb) {
496 xmlns: Strophe.NS.MUC_ADMIN
498 if (reason != null) {
499 iq.c("reason", reason);
501 return this._connection.sendIQ(iq.tree(), handler_cb, error_cb);
505 Changes the role of a member of a MUC room.
506 The modification can only be done by a room moderator. An error will be
507 returned if the user doesn't have permission.
509 (String) room - The multi-user chat room name.
510 (String) nick - The nick name of the user to modify.
511 (String) role - The new role of the user.
512 (String) affiliation - The new affiliation of the user.
513 (String) reason - Optional reason for the change.
514 (Function) handler_cb - Optional callback for success
515 (Function) error_cb - Optional callback for error
517 iq - the id of the mode change request.
519 modifyRole: function(room, nick, role, reason, handler_cb, error_cb) {
521 item = $build("item", {
525 return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
527 kick: function(room, nick, reason, handler_cb, error_cb) {
528 return this.modifyRole(room, nick, 'none', reason, handler_cb, error_cb);
530 voice: function(room, nick, reason, handler_cb, error_cb) {
531 return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
533 mute: function(room, nick, reason, handler_cb, error_cb) {
534 return this.modifyRole(room, nick, 'visitor', reason, handler_cb, error_cb);
536 op: function(room, nick, reason, handler_cb, error_cb) {
537 return this.modifyRole(room, nick, 'moderator', reason, handler_cb, error_cb);
539 deop: function(room, nick, reason, handler_cb, error_cb) {
540 return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
544 Changes the affiliation of a member of a MUC room.
545 The modification can only be done by a room moderator. An error will be
546 returned if the user doesn't have permission.
548 (String) room - The multi-user chat room name.
549 (String) jid - The jid of the user to modify.
550 (String) affiliation - The new affiliation of the user.
551 (String) reason - Optional reason for the change.
552 (Function) handler_cb - Optional callback for success
553 (Function) error_cb - Optional callback for error
555 iq - the id of the mode change request.
557 modifyAffiliation: function(room, jid, affiliation, reason, handler_cb, error_cb) {
559 item = $build("item", {
561 affiliation: affiliation
563 return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
565 ban: function(room, jid, reason, handler_cb, error_cb) {
566 return this.modifyAffiliation(room, jid, 'outcast', reason, handler_cb, error_cb);
568 member: function(room, jid, reason, handler_cb, error_cb) {
569 return this.modifyAffiliation(room, jid, 'member', reason, handler_cb, error_cb);
571 revoke: function(room, jid, reason, handler_cb, error_cb) {
572 return this.modifyAffiliation(room, jid, 'none', reason, handler_cb, error_cb);
574 owner: function(room, jid, reason, handler_cb, error_cb) {
575 return this.modifyAffiliation(room, jid, 'owner', reason, handler_cb, error_cb);
577 admin: function(room, jid, reason, handler_cb, error_cb) {
578 return this.modifyAffiliation(room, jid, 'admin', reason, handler_cb, error_cb);
582 Change the current users nick name.
584 (String) room - The multi-user chat room name.
585 (String) user - The new nick name.
587 changeNick: function(room, user) {
588 var presence, room_nick;
589 room_nick = this.test_append_nick(room, user);
591 from: this._connection.jid,
593 id: this._connection.getUniqueId()
595 return this._connection.send(presence.tree());
599 Change the current users status.
601 (String) room - The multi-user chat room name.
602 (String) user - The current nick.
603 (String) show - The new show-text.
604 (String) status - The new status-text.
606 setStatus: function(room, user, show, status) {
607 var presence, room_nick;
608 room_nick = this.test_append_nick(room, user);
610 from: this._connection.jid,
614 presence.c('show', show).up();
616 if (status != null) {
617 presence.c('status', status);
619 return this._connection.send(presence.tree());
623 Registering with a room.
624 @see http://xmpp.org/extensions/xep-0045.html#register
626 (String) room - The multi-user chat room name.
627 (Function) handle_cb - Function to call for room list return.
628 (Function) error_cb - Function to call on error.
630 registrationRequest: function(room, handle_cb, error_cb) {
634 from: this._connection.jid,
637 xmlns: Strophe.NS.MUC_REGISTER
639 return this._connection.sendIQ(iq, function(stanza) {
640 var $field, $fields, field, fields, i, len, length;
641 $fields = stanza.getElementsByTagName('field');
642 length = $fields.length;
647 for (i = 0, len = $fields.length; i < len; i++) {
650 "var": $field.getAttribute('var'),
651 label: $field.getAttribute('label'),
652 type: $field.getAttribute('type')
654 if ($field.getElementsByTagName('required').length > 0) {
655 fields.required.push(field);
657 fields.optional.push(field);
660 return handle_cb(fields);
665 Submits registration form.
667 (String) room - The multi-user chat room name.
668 (Function) handle_cb - Function to call for room list return.
669 (Function) error_cb - Function to call on error.
671 submitRegistrationForm: function(room, fields, handle_cb, error_cb) {
677 xmlns: Strophe.NS.MUC_REGISTER
680 xmlns: "jabber:x:data",
685 }).c('value').t('http://jabber.org/protocol/muc#register').up().up();
686 for (key in fields) {
690 }).c('value').t(val).up().up();
692 return this._connection.sendIQ(iq, handle_cb, error_cb);
696 List all chat room available on a server.
698 (String) server - name of chat server.
699 (String) handle_cb - Function to call for room list return.
700 (String) error_cb - Function to call on error.
702 listRooms: function(server, handle_cb, error_cb) {
706 from: this._connection.jid,
709 xmlns: Strophe.NS.DISCO_ITEMS
711 return this._connection.sendIQ(iq, handle_cb, error_cb);
713 test_append_nick: function(room, nick) {
715 node = Strophe.escapeNode(Strophe.getNodeFromJid(room));
716 domain = Strophe.getDomainFromJid(room);
717 return node + "@" + domain + (nick != null ? "/" + nick : "");
721 XmppRoom = (function() {
722 function XmppRoom(client, name1, nick1, password1) {
723 this.client = client;
726 this.password = password1;
727 this._roomRosterHandler = bind(this._roomRosterHandler, this);
728 this._addOccupant = bind(this._addOccupant, this);
730 this._message_handlers = {};
731 this._presence_handlers = {};
732 this._roster_handlers = {};
733 this._handler_ids = 0;
734 if (this.client.muc) {
735 this.client = this.client.muc;
737 this.name = Strophe.getBareJidFromJid(this.name);
738 this.addHandler('presence', this._roomRosterHandler);
741 XmppRoom.prototype.join = function(msg_handler_cb, pres_handler_cb, roster_cb) {
742 return this.client.join(this.name, this.nick, msg_handler_cb, pres_handler_cb, roster_cb, this.password);
745 XmppRoom.prototype.leave = function(handler_cb, message) {
746 this.client.leave(this.name, this.nick, handler_cb, message);
747 return delete this.client.rooms[this.name];
750 XmppRoom.prototype.message = function(nick, message, html_message, type) {
751 return this.client.message(this.name, nick, message, html_message, type);
754 XmppRoom.prototype.groupchat = function(message, html_message) {
755 return this.client.groupchat(this.name, message, html_message);
758 XmppRoom.prototype.invite = function(receiver, reason) {
759 return this.client.invite(this.name, receiver, reason);
762 XmppRoom.prototype.multipleInvites = function(receivers, reason) {
763 return this.client.invite(this.name, receivers, reason);
766 XmppRoom.prototype.directInvite = function(receiver, reason) {
767 return this.client.directInvite(this.name, receiver, reason, this.password);
770 XmppRoom.prototype.configure = function(handler_cb) {
771 return this.client.configure(this.name, handler_cb);
774 XmppRoom.prototype.cancelConfigure = function() {
775 return this.client.cancelConfigure(this.name);
778 XmppRoom.prototype.saveConfiguration = function(config) {
779 return this.client.saveConfiguration(this.name, config);
782 XmppRoom.prototype.queryOccupants = function(success_cb, error_cb) {
783 return this.client.queryOccupants(this.name, success_cb, error_cb);
786 XmppRoom.prototype.setTopic = function(topic) {
787 return this.client.setTopic(this.name, topic);
790 XmppRoom.prototype.modifyRole = function(nick, role, reason, success_cb, error_cb) {
791 return this.client.modifyRole(this.name, nick, role, reason, success_cb, error_cb);
794 XmppRoom.prototype.kick = function(nick, reason, handler_cb, error_cb) {
795 return this.client.kick(this.name, nick, reason, handler_cb, error_cb);
798 XmppRoom.prototype.voice = function(nick, reason, handler_cb, error_cb) {
799 return this.client.voice(this.name, nick, reason, handler_cb, error_cb);
802 XmppRoom.prototype.mute = function(nick, reason, handler_cb, error_cb) {
803 return this.client.mute(this.name, nick, reason, handler_cb, error_cb);
806 XmppRoom.prototype.op = function(nick, reason, handler_cb, error_cb) {
807 return this.client.op(this.name, nick, reason, handler_cb, error_cb);
810 XmppRoom.prototype.deop = function(nick, reason, handler_cb, error_cb) {
811 return this.client.deop(this.name, nick, reason, handler_cb, error_cb);
814 XmppRoom.prototype.modifyAffiliation = function(jid, affiliation, reason, success_cb, error_cb) {
815 return this.client.modifyAffiliation(this.name, jid, affiliation, reason, success_cb, error_cb);
818 XmppRoom.prototype.ban = function(jid, reason, handler_cb, error_cb) {
819 return this.client.ban(this.name, jid, reason, handler_cb, error_cb);
822 XmppRoom.prototype.member = function(jid, reason, handler_cb, error_cb) {
823 return this.client.member(this.name, jid, reason, handler_cb, error_cb);
826 XmppRoom.prototype.revoke = function(jid, reason, handler_cb, error_cb) {
827 return this.client.revoke(this.name, jid, reason, handler_cb, error_cb);
830 XmppRoom.prototype.owner = function(jid, reason, handler_cb, error_cb) {
831 return this.client.owner(this.name, jid, reason, handler_cb, error_cb);
834 XmppRoom.prototype.admin = function(jid, reason, handler_cb, error_cb) {
835 return this.client.admin(this.name, jid, reason, handler_cb, error_cb);
838 XmppRoom.prototype.changeNick = function(nick1) {
840 return this.client.changeNick(this.name, nick);
843 XmppRoom.prototype.setStatus = function(show, status) {
844 return this.client.setStatus(this.name, this.nick, show, status);
849 Adds a handler to the MUC room.
851 (String) handler_type - 'message', 'presence' or 'roster'.
852 (Function) handler - The handler function.
854 id - the id of handler.
857 XmppRoom.prototype.addHandler = function(handler_type, handler) {
859 id = this._handler_ids++;
860 switch (handler_type) {
862 this._presence_handlers[id] = handler;
865 this._message_handlers[id] = handler;
868 this._roster_handlers[id] = handler;
879 Removes a handler from the MUC room.
880 This function takes ONLY ids returned by the addHandler function
881 of this room. passing handler ids returned by connection.addHandler
884 (number) id - the id of the handler
887 XmppRoom.prototype.removeHandler = function(id) {
888 delete this._presence_handlers[id];
889 delete this._message_handlers[id];
890 return delete this._roster_handlers[id];
895 Creates and adds an Occupant to the Room Roster.
897 (Object) data - the data the Occupant is filled with
899 occ - the created Occupant.
902 XmppRoom.prototype._addOccupant = function(data) {
904 occ = new Occupant(data, this);
905 this.roster[occ.nick] = occ;
911 The standard handler that managed the Room Roster.
913 (Object) pres - the presence stanza containing user information
916 XmppRoom.prototype._roomRosterHandler = function(pres) {
917 var data, handler, id, newnick, nick, ref;
918 data = XmppRoom._parsePresence(pres);
920 newnick = data.newnick || null;
927 if (this.roster[nick] && this.roster[newnick]) {
928 this.roster[nick].update(this.roster[newnick]);
929 this.roster[newnick] = this.roster[nick];
931 if (this.roster[nick] && !this.roster[newnick]) {
932 this.roster[newnick] = this.roster[nick].update(data);
935 delete this.roster[nick];
938 if (this.roster[nick]) {
939 this.roster[nick].update(data);
941 this._addOccupant(data);
944 ref = this._roster_handlers;
947 if (!handler(this.roster, this)) {
948 delete this._roster_handlers[id];
956 Parses a presence stanza
958 (Object) data - the data extracted from the presence stanza
961 XmppRoom._parsePresence = function(pres) {
962 var c, c2, data, i, j, len, len1, ref, ref1;
964 data.nick = Strophe.getResourceFromJid(pres.getAttribute("from"));
965 data.type = pres.getAttribute("type");
967 ref = pres.childNodes;
968 for (i = 0, len = ref.length; i < len; i++) {
970 switch (c.nodeName) {
972 data.status = c.textContent || null;
975 data.show = c.textContent || null;
978 if (c.getAttribute("xmlns") === Strophe.NS.MUC_USER) {
980 for (j = 0, len1 = ref1.length; j < len1; j++) {
982 switch (c2.nodeName) {
984 data.affiliation = c2.getAttribute("affiliation");
985 data.role = c2.getAttribute("role");
986 data.jid = c2.getAttribute("jid");
987 data.newnick = c2.getAttribute("nick");
990 if (c2.getAttribute("code")) {
991 data.states.push(c2.getAttribute("code"));
1005 RoomConfig = (function() {
1006 function RoomConfig(info) {
1007 this.parse = bind(this.parse, this);
1013 RoomConfig.prototype.parse = function(result) {
1014 var attr, attrs, child, field, i, identity, j, l, len, len1, len2, query, ref;
1015 query = result.getElementsByTagName("query")[0].childNodes;
1016 this.identities = [];
1019 for (i = 0, len = query.length; i < len; i++) {
1021 attrs = child.attributes;
1022 switch (child.nodeName) {
1025 for (j = 0, len1 = attrs.length; j < len1; j++) {
1027 identity[attr.name] = attr.textContent;
1029 this.identities.push(identity);
1032 this.features.push(child.getAttribute("var"));
1035 if ((!child.childNodes[0].getAttribute("var") === 'FORM_TYPE') || (!child.childNodes[0].getAttribute("type") === 'hidden')) {
1038 ref = child.childNodes;
1039 for (l = 0, len2 = ref.length; l < len2; l++) {
1041 if (!field.attributes.type) {
1043 "var": field.getAttribute("var"),
1044 label: field.getAttribute("label") || "",
1045 value: field.firstChild.textContent || ""
1052 "identities": this.identities,
1053 "features": this.features,
1062 Occupant = (function() {
1063 function Occupant(data, room1) {
1065 this.update = bind(this.update, this);
1066 this.admin = bind(this.admin, this);
1067 this.owner = bind(this.owner, this);
1068 this.revoke = bind(this.revoke, this);
1069 this.member = bind(this.member, this);
1070 this.ban = bind(this.ban, this);
1071 this.modifyAffiliation = bind(this.modifyAffiliation, this);
1072 this.deop = bind(this.deop, this);
1073 this.op = bind(this.op, this);
1074 this.mute = bind(this.mute, this);
1075 this.voice = bind(this.voice, this);
1076 this.kick = bind(this.kick, this);
1077 this.modifyRole = bind(this.modifyRole, this);
1081 Occupant.prototype.modifyRole = function(role, reason, success_cb, error_cb) {
1082 return this.room.modifyRole(this.nick, role, reason, success_cb, error_cb);
1085 Occupant.prototype.kick = function(reason, handler_cb, error_cb) {
1086 return this.room.kick(this.nick, reason, handler_cb, error_cb);
1089 Occupant.prototype.voice = function(reason, handler_cb, error_cb) {
1090 return this.room.voice(this.nick, reason, handler_cb, error_cb);
1093 Occupant.prototype.mute = function(reason, handler_cb, error_cb) {
1094 return this.room.mute(this.nick, reason, handler_cb, error_cb);
1097 Occupant.prototype.op = function(reason, handler_cb, error_cb) {
1098 return this.room.op(this.nick, reason, handler_cb, error_cb);
1101 Occupant.prototype.deop = function(reason, handler_cb, error_cb) {
1102 return this.room.deop(this.nick, reason, handler_cb, error_cb);
1105 Occupant.prototype.modifyAffiliation = function(affiliation, reason, success_cb, error_cb) {
1106 return this.room.modifyAffiliation(this.jid, affiliation, reason, success_cb, error_cb);
1109 Occupant.prototype.ban = function(reason, handler_cb, error_cb) {
1110 return this.room.ban(this.jid, reason, handler_cb, error_cb);
1113 Occupant.prototype.member = function(reason, handler_cb, error_cb) {
1114 return this.room.member(this.jid, reason, handler_cb, error_cb);
1117 Occupant.prototype.revoke = function(reason, handler_cb, error_cb) {
1118 return this.room.revoke(this.jid, reason, handler_cb, error_cb);
1121 Occupant.prototype.owner = function(reason, handler_cb, error_cb) {
1122 return this.room.owner(this.jid, reason, handler_cb, error_cb);
1125 Occupant.prototype.admin = function(reason, handler_cb, error_cb) {
1126 return this.room.admin(this.jid, reason, handler_cb, error_cb);
1129 Occupant.prototype.update = function(data) {
1130 this.nick = data.nick || null;
1131 this.affiliation = data.affiliation || null;
1132 this.role = data.role || null;
1133 this.jid = data.jid || null;
1134 this.status = data.status || null;
1135 this.show = data.show || null;
1144 // generated by coffee-script 1.9.2