From bfacd516454241ebb4d7e263c1b643d5a804a097 Mon Sep 17 00:00:00 2001 From: Michael Weibel Date: Sun, 19 Jan 2014 10:43:46 +0100 Subject: [PATCH] Use uglify for concatenating, update CONTRIBUTING - Uglify for concatenating enables sourcemap support - Add sourcemaps - Fix `Candy.Core.log`: Shows now correct line numbers - we should test if it works in IE still (@pstadler likes to test?) - Remove grunt-contrib-concat - Update CONTRIBUTING.md with vagrant install - FIXME: Make this easier --- CONTRIBUTING.md | 19 +- Gruntfile.js | 78 +- candy.bundle.js | 7448 +++++++++++++++++++----------------------- candy.bundle.map | 1 + candy.min.js | 2 +- libs/libs.bundle.js | 7310 ++++++++++++++++++----------------------- libs/libs.bundle.map | 1 + libs/libs.min.js | 6 +- package.json | 1 - src/core.js | 16 +- 10 files changed, 6740 insertions(+), 8142 deletions(-) create mode 100644 candy.bundle.map create mode 100644 libs/libs.bundle.map diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31087de9..870ce22a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,20 @@ You want to help us? **Awesome!** ### How to contribute A few hopefully helpful hints to contributing to Candy +#### Using vagrant +1. [Fork](https://help.github.com/articles/fork-a-repo) Candy +2. [Install Vagrant](http://vagrantup.com/) +3. Follow instructions [for Candy Vagrant](https://github.com/candy-chat/vagrant) +4. Change the remote in the `candy` and `candy-plugins` repos: `git remote set-url origin git://github.com/YOURNAME/candy` (or candy-plugins) +5. Create a branch based on the `dev` branch (`git checkout -B my-awesome-feature`) +6. Run `grunt watch` to automatically run jshint (syntax checker) and the build of `candy.bundle.js` and `candy.min.js` while developing. +7. Make your changes, fix eventual *jshint* errors & push them back to your fork +8. Create a [pull request](https://help.github.com/articles/using-pull-requests) + + +#### On your own machine +Please note that you should have a working XMPP server to test your changes (the vagrant way does already have a working XMPP server). + 1. [Fork](https://help.github.com/articles/fork-a-repo) Candy 2. Clone your fork 2. Checkout out `dev` branch (`git checkout dev`) & Update git submodules `git submodule update --init` @@ -26,8 +40,7 @@ A few hopefully helpful hints to contributing to Candy 5. Install npm dependencies (`npm install` in candy root directory) 6. Create a branch based on the `dev` branch (`git checkout -B my-awesome-feature`) 7. Run `grunt watch` to automatically run jshint (syntax checker) and the build of `candy.bundle.js` and `candy.min.js` while developing. -8. Make your changes & push them back to your fork -9. Run `grunt jshint` and fix errors -10. Create a [pull request](https://help.github.com/articles/using-pull-requests) +8. Make your changes, fix eventual *jshint* errors & push them back to your fork +9. Create a [pull request](https://help.github.com/articles/using-pull-requests) In case you have any questions, don't hesitate to ask on the [Mailing list](http://groups.google.com/group/candy-chat). diff --git a/Gruntfile.js b/Gruntfile.js index 30f6bb20..e9f44ef5 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -23,38 +23,53 @@ module.exports = function(grunt) { ] } }, - concat: { - bundle: { - src: [ - 'src/candy.js', 'src/core.js', 'src/view.js', - 'src/util.js', 'src/core/action.js', - 'src/core/chatRoom.js', 'src/core/chatRoster.js', - 'src/core/chatUser.js', 'src/core/event.js', - 'src/view/observer.js', 'src/view/pane.js', - 'src/view/template.js', 'src/view/translation.js' - ], - dest: 'candy.bundle.js' - }, - libs: { - src: [ - 'libs/strophejs/strophe.js', - 'libs/strophejs-plugins/muc/strophe.muc.js', - 'libs/strophejs-plugins/disco/strophe.disco.js', - 'libs/strophejs-plugins/caps/strophe.caps.jsonly.js', - 'libs/mustache.js/mustache.js', - 'libs/jquery-i18n/jquery.i18n.js', - 'libs/dateformat/dateFormat.js' - ], - dest: 'libs/libs.bundle.js' - } - }, uglify: { bundle: { + files: { + 'candy.bundle.js': [ + 'src/candy.js', 'src/core.js', 'src/view.js', + 'src/util.js', 'src/core/action.js', + 'src/core/chatRoom.js', 'src/core/chatRoster.js', + 'src/core/chatUser.js', 'src/core/event.js', + 'src/view/observer.js', 'src/view/pane.js', + 'src/view/template.js', 'src/view/translation.js', + 'src/view/translation/*.js' + ] + }, + options: { + sourceMap: true, + mangle: false, + compress: false, + beautify: true, + preserveComments: 'all' + } + }, + min: { files: { 'candy.min.js': ['candy.bundle.js'] } }, libs: { + files: { + 'libs/libs.bundle.js': [ + 'libs/strophejs/strophe.js', + 'libs/strophejs-plugins/muc/strophe.muc.js', + 'libs/strophejs-plugins/disco/strophe.disco.js', + 'libs/strophejs-plugins/caps/strophe.caps.jsonly.js', + 'libs/mustache.js/mustache.js', + 'libs/jquery-i18n/jquery.i18n.js', + 'libs/dateformat/dateFormat.js' + ] + }, + options: { + sourceMap: true, + mangle: false, + compress: false, + beautify: true, + preserveComments: 'all' + } + }, + 'libs-min': { files: { 'libs/libs.min.js': ['libs/libs.bundle.js'] } @@ -63,11 +78,11 @@ module.exports = function(grunt) { watch: { bundle: { files: ['src/*.js', 'src/**/*.js'], - tasks: ['jshint', 'concat:bundle', 'uglify:bundle', 'notify:bundle'] + tasks: ['jshint', 'uglify:bundle', 'uglify:min', 'notify:bundle'] }, libs: { files: ['libs/*/**/*.js'], - tasks: ['concat:libs', 'uglify:libs', 'notify:libs'] + tasks: ['uglify:libs', 'uglify:libs-min', 'notify:libs'] } }, natural_docs: { @@ -80,8 +95,8 @@ module.exports = function(grunt) { } }, clean: { - bundle: ['./candy.bundle.js', './candy.min.js'], - libs: ['./libs/libs.bundle.js', './libs/libs.min.js'], + bundle: ['./candy.bundle.js', './candy.bundle.map', './candy.min.js'], + libs: ['./libs/libs.bundle.js', './libs/libs.bundle.map', './libs/libs.min.js'], docs: ['./docs'] }, mkdir: { @@ -117,7 +132,6 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-natural-docs'); @@ -126,8 +140,8 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-sync-pkg'); grunt.registerTask('default', [ - 'jshint', 'concat:libs', 'uglify:libs', - 'concat:bundle', 'uglify:bundle', 'notify:default' + 'jshint', 'uglify:libs', 'uglify:libs-min', + 'uglify:bundle', 'uglify:min', 'notify:default' ]); grunt.registerTask('docs', ['mkdir:docs', 'natural_docs', 'notify:docs']); }; \ No newline at end of file diff --git a/candy.bundle.js b/candy.bundle.js index c9fe2370..cbf95d7b 100644 --- a/candy.bundle.js +++ b/candy.bundle.js @@ -9,10 +9,9 @@ * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global jQuery */ - /** Class: Candy * Candy base class for initalizing the view and the core * @@ -20,20 +19,19 @@ * (Candy) self - itself * (jQuery) $ - jQuery */ -var Candy = (function(self, $) { - /** Object: about +var Candy = function(self, $) { + /** Object: about * About candy * * Contains: * (String) name - Candy * (Float) version - Candy version */ - self.about = { - name: 'Candy', - version: '1.6.0-beta3' - }; - - /** Function: init + self.about = { + name: "Candy", + version: "1.6.0-beta3" + }; + /** Function: init * Init view & core * * Parameters: @@ -44,16 +42,15 @@ var Candy = (function(self, $) { * (Boolean) debug - Debug (Default: false) * (Array|Boolean) autojoin - Autojoin these channels. When boolean true, do not autojoin, wait if the server sends something. */ - self.init = function(service, options) { - if (!options.viewClass) { - options.viewClass = self.View; - } - options.viewClass.init($('#candy'), options.view); - self.Core.init(service, options.core); - }; - - return self; -}(Candy || {}, jQuery)); + self.init = function(service, options) { + if (!options.viewClass) { + options.viewClass = self.View; + } + options.viewClass.init($("#candy"), options.view); + self.Core.init(service, options.core); + }; + return self; +}(Candy || {}, jQuery); /** File: core.js * Candy - Chats are not dead yet. @@ -66,10 +63,9 @@ var Candy = (function(self, $) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy, window, Strophe, jQuery */ - /** Class: Candy.Core * Candy Chat Core * @@ -78,141 +74,121 @@ var Candy = (function(self, $) { * (Strophe) Strophe - Strophe JS * (jQuery) $ - jQuery */ -Candy.Core = (function(self, Strophe, $) { - /** PrivateVariable: _connection +Candy.Core = function(self, Strophe, $) { + /** PrivateVariable: _connection * Strophe connection */ - var _connection = null, - /** PrivateVariable: _service + var _connection = null, /** PrivateVariable: _service * URL of BOSH service */ - _service = null, - /** PrivateVariable: _user + _service = null, /** PrivateVariable: _user * Current user (me) */ - _user = null, - /** PrivateVariable: _rooms + _user = null, /** PrivateVariable: _rooms * Opened rooms, containing instances of Candy.Core.ChatRooms */ - _rooms = {}, - /** PrivateVariable: _anonymousConnection + _rooms = {}, /** PrivateVariable: _anonymousConnection * Set in when jidOrHost doesn't contain a @-char. */ - _anonymousConnection = false, - /** PrivateVariable: _status + _anonymousConnection = false, /** PrivateVariable: _status * Current Strophe connection state */ - _status, - /** PrivateVariable: _options + _status, /** PrivateVariable: _options * Options: * (Boolean) debug - Debug (Default: false) * (Array|Boolean) autojoin - Autojoin these channels. When boolean true, do not autojoin, wait if the server sends something. */ - _options = { - /** Boolean: autojoin + _options = { + /** Boolean: autojoin * If set to `true` try to get the bookmarks and autojoin the rooms (supported by Openfire). * You may want to define an array of rooms to autojoin: `['room1@conference.host.tld', 'room2...]` (ejabberd, Openfire, ...) */ - autojoin: undefined, - debug: false, - disableWindowUnload: false, - /** Integer: presencePriority + autojoin: undefined, + debug: false, + disableWindowUnload: false, + /** Integer: presencePriority * Default priority for presence messages in order to receive messages across different resources */ - presencePriority: 1, - /** String: resource + presencePriority: 1, + /** String: resource * JID resource to use when connecting to the server. * Specify `''` (an empty string) to request a random resource. */ - resource: Candy.about.name - }, - - /** PrivateFunction: _addNamespace + resource: Candy.about.name + }, /** PrivateFunction: _addNamespace * Adds a namespace. * * Parameters: * (String) name - namespace name (will become a constant living in Strophe.NS.*) * (String) value - XML Namespace */ - _addNamespace = function(name, value) { - Strophe.addNamespace(name, value); - }, - - /** PrivateFunction: _addNamespaces + _addNamespace = function(name, value) { + Strophe.addNamespace(name, value); + }, /** PrivateFunction: _addNamespaces * Adds namespaces needed by Candy. */ - _addNamespaces = function() { - _addNamespace('PRIVATE', 'jabber:iq:private'); - _addNamespace('BOOKMARKS', 'storage:bookmarks'); - _addNamespace('PRIVACY', 'jabber:iq:privacy'); - _addNamespace('DELAY', 'jabber:x:delay'); - }, - - _getEscapedJidFromJid = function(jid) { - var node = Strophe.getNodeFromJid(jid), - domain = Strophe.getDomainFromJid(jid); - return node ? Strophe.escapeNode(node) + '@' + domain : domain; - }; - - /** Function: init + _addNamespaces = function() { + _addNamespace("PRIVATE", "jabber:iq:private"); + _addNamespace("BOOKMARKS", "storage:bookmarks"); + _addNamespace("PRIVACY", "jabber:iq:privacy"); + _addNamespace("DELAY", "jabber:x:delay"); + }, _getEscapedJidFromJid = function(jid) { + var node = Strophe.getNodeFromJid(jid), domain = Strophe.getDomainFromJid(jid); + return node ? Strophe.escapeNode(node) + "@" + domain : domain; + }; + /** Function: init * Initialize Core. * * Parameters: * (String) service - URL of BOSH/Websocket service * (Object) options - Options for candy */ - self.init = function(service, options) { - _service = service; - // Apply options - $.extend(true, _options, options); - - // Enable debug logging - if(_options.debug) { - self.log = function(str) { - try { // prevent erroring - if(typeof window.console !== undefined && typeof window.console.log !== undefined) { - console.log(str); - } - } catch(e) {} - }; - self.log('[Init] Debugging enabled'); - } - - _addNamespaces(); - - // Connect to BOSH/Websocket service - _connection = new Strophe.Connection(_service); - _connection.rawInput = self.rawInput.bind(self); - _connection.rawOutput = self.rawOutput.bind(self); - - // set caps node - _connection.caps.node = 'https://candy-chat.github.io/candy/'; - - // Window unload handler... works on all browsers but Opera. There is NO workaround. - // Opera clients getting disconnected 1-2 minutes delayed. - if (!_options.disableWindowUnload) { - window.onbeforeunload = self.onWindowUnload; - } - }; - - /** Function: registerEventHandlers + self.init = function(service, options) { + _service = service; + // Apply options + $.extend(true, _options, options); + // Enable debug logging + if (_options.debug) { + if (typeof window.console !== undefined && typeof window.console.log !== undefined) { + if (Function.prototype.bind) { + self.log = Function.prototype.bind.call(console.log, console); + } else { + self.log = function() { + Function.prototype.apply.call(console.log, console, arguments); + }; + } + } + self.log("[Init] Debugging enabled"); + } + _addNamespaces(); + // Connect to BOSH/Websocket service + _connection = new Strophe.Connection(_service); + _connection.rawInput = self.rawInput.bind(self); + _connection.rawOutput = self.rawOutput.bind(self); + // set caps node + _connection.caps.node = "https://candy-chat.github.io/candy/"; + // Window unload handler... works on all browsers but Opera. There is NO workaround. + // Opera clients getting disconnected 1-2 minutes delayed. + if (!_options.disableWindowUnload) { + window.onbeforeunload = self.onWindowUnload; + } + }; + /** Function: registerEventHandlers * Adds listening handlers to the connection. * * Use with caution from outside of Candy. */ - self.registerEventHandlers = function() { - self.addHandler(self.Event.Jabber.Version, Strophe.NS.VERSION, 'iq'); - self.addHandler(self.Event.Jabber.Presence, null, 'presence'); - self.addHandler(self.Event.Jabber.Message, null, 'message'); - self.addHandler(self.Event.Jabber.Bookmarks, Strophe.NS.PRIVATE, 'iq'); - self.addHandler(self.Event.Jabber.Room.Disco, Strophe.NS.DISCO_INFO, 'iq', 'result'); - - self.addHandler(_connection.disco._onDiscoInfo.bind(_connection.disco), Strophe.NS.DISCO_INFO, 'iq', 'get'); - self.addHandler(_connection.disco._onDiscoItems.bind(_connection.disco), Strophe.NS.DISCO_ITEMS, 'iq', 'get'); - self.addHandler(_connection.caps._delegateCapabilities.bind(_connection.caps), Strophe.NS.CAPS); - }; - - /** Function: connect + self.registerEventHandlers = function() { + self.addHandler(self.Event.Jabber.Version, Strophe.NS.VERSION, "iq"); + self.addHandler(self.Event.Jabber.Presence, null, "presence"); + self.addHandler(self.Event.Jabber.Message, null, "message"); + self.addHandler(self.Event.Jabber.Bookmarks, Strophe.NS.PRIVATE, "iq"); + self.addHandler(self.Event.Jabber.Room.Disco, Strophe.NS.DISCO_INFO, "iq", "result"); + self.addHandler(_connection.disco._onDiscoInfo.bind(_connection.disco), Strophe.NS.DISCO_INFO, "iq", "get"); + self.addHandler(_connection.disco._onDiscoItems.bind(_connection.disco), Strophe.NS.DISCO_ITEMS, "iq", "get"); + self.addHandler(_connection.caps._delegateCapabilities.bind(_connection.caps), Strophe.NS.CAPS); + }; + /** Function: connect * Connect to the jabber host. * * There are four different procedures to login: @@ -231,11 +207,11 @@ Candy.Core = (function(self, Strophe, $) { * (String) nick - Nick of the user. Set one if you want to anonymously connect but preset a nick. If jidOrHost is a domain * and this param is not set, Candy will prompt for a nick. */ - self.connect = function(jidOrHost, password, nick) { - // Reset before every connection attempt to make sure reconnections work after authfail, alltabsclosed, ... - _connection.reset(); - self.registerEventHandlers(); - /** Event: candy:core.before-connect + self.connect = function(jidOrHost, password, nick) { + // Reset before every connection attempt to make sure reconnections work after authfail, alltabsclosed, ... + _connection.reset(); + self.registerEventHandlers(); + /** Event: candy:core.before-connect * Triggered before a connection attempt is made. * * Plugins should register their stanza handlers using this event @@ -246,33 +222,30 @@ Candy.Core = (function(self, Strophe, $) { * Parameters: * (Strophe.Connection) conncetion - Strophe connection */ - $(Candy).triggerHandler('candy:core.before-connect', { - connection: _connection - }); - - _anonymousConnection = !_anonymousConnection ? jidOrHost && jidOrHost.indexOf("@") < 0 : true; - - if(jidOrHost && password) { - // authentication - _connection.connect(_getEscapedJidFromJid(jidOrHost) + '/' + _options.resource, password, Candy.Core.Event.Strophe.Connect); - if (nick) { - _user = new self.ChatUser(jidOrHost, nick); - } else { - _user = new self.ChatUser(jidOrHost, Strophe.getNodeFromJid(jidOrHost)); - } - } else if(jidOrHost && nick) { - // anonymous connect - _connection.connect(_getEscapedJidFromJid(jidOrHost) + '/' + _options.resource, null, Candy.Core.Event.Strophe.Connect); - _user = new self.ChatUser(null, nick); // set jid to null because we'll later receive it - } else if(jidOrHost) { - Candy.Core.Event.Login(jidOrHost); - } else { - // display login modal - Candy.Core.Event.Login(); - } - }; - - /** Function: attach + $(Candy).triggerHandler("candy:core.before-connect", { + connection: _connection + }); + _anonymousConnection = !_anonymousConnection ? jidOrHost && jidOrHost.indexOf("@") < 0 : true; + if (jidOrHost && password) { + // authentication + _connection.connect(_getEscapedJidFromJid(jidOrHost) + "/" + _options.resource, password, Candy.Core.Event.Strophe.Connect); + if (nick) { + _user = new self.ChatUser(jidOrHost, nick); + } else { + _user = new self.ChatUser(jidOrHost, Strophe.getNodeFromJid(jidOrHost)); + } + } else if (jidOrHost && nick) { + // anonymous connect + _connection.connect(_getEscapedJidFromJid(jidOrHost) + "/" + _options.resource, null, Candy.Core.Event.Strophe.Connect); + _user = new self.ChatUser(null, nick); + } else if (jidOrHost) { + Candy.Core.Event.Login(jidOrHost); + } else { + // display login modal + Candy.Core.Event.Login(); + } + }; + /** Function: attach * Attach an already binded & connected session to the server * * _See_ Strophe.Connection.attach @@ -282,25 +255,23 @@ Candy.Core = (function(self, Strophe, $) { * (Integer) sid - Session ID * (Integer) rid - rid */ - self.attach = function(jid, sid, rid) { - _user = new self.ChatUser(jid, Strophe.getNodeFromJid(jid)); - self.registerEventHandlers(); - _connection.attach(jid, sid, rid, Candy.Core.Event.Strophe.Connect); - }; - - /** Function: disconnect + self.attach = function(jid, sid, rid) { + _user = new self.ChatUser(jid, Strophe.getNodeFromJid(jid)); + self.registerEventHandlers(); + _connection.attach(jid, sid, rid, Candy.Core.Event.Strophe.Connect); + }; + /** Function: disconnect * Leave all rooms and disconnect */ - self.disconnect = function() { - if(_connection.connected) { - $.each(self.getRooms(), function() { - Candy.Core.Action.Jabber.Room.Leave(this.getJid()); - }); - _connection.disconnect(); - } - }; - - /** Function: addHandler + self.disconnect = function() { + if (_connection.connected) { + $.each(self.getRooms(), function() { + Candy.Core.Action.Jabber.Room.Leave(this.getJid()); + }); + _connection.disconnect(); + } + }; + /** Function: addHandler * Wrapper for Strophe.Connection.addHandler() to add a stanza handler for the connection. * * Parameters: @@ -315,71 +286,64 @@ Candy.Core = (function(self, Strophe, $) { * Returns: * A reference to the handler that can be used to remove it. */ - self.addHandler = function(handler, ns, name, type, id, from, options) { - return _connection.addHandler(handler, ns, name, type, id, from, options); - }; - - /** Function: getUser + self.addHandler = function(handler, ns, name, type, id, from, options) { + return _connection.addHandler(handler, ns, name, type, id, from, options); + }; + /** Function: getUser * Gets current user * * Returns: * Instance of Candy.Core.ChatUser */ - self.getUser = function() { - return _user; - }; - - /** Function: setUser + self.getUser = function() { + return _user; + }; + /** Function: setUser * Set current user. Needed when anonymous login is used, as jid gets retrieved later. * * Parameters: * (Candy.Core.ChatUser) user - User instance */ - self.setUser = function(user) { - _user = user; - }; - - /** Function: getConnection + self.setUser = function(user) { + _user = user; + }; + /** Function: getConnection * Gets Strophe connection * * Returns: * Instance of Strophe.Connection */ - self.getConnection = function() { - return _connection; - }; - - /** Function: removeRoom + self.getConnection = function() { + return _connection; + }; + /** Function: removeRoom * Removes a room from the rooms list * * Parameters: * (String) roomJid - roomJid */ - self.removeRoom = function(roomJid) { - delete _rooms[roomJid]; - }; - - /** Function: getRooms + self.removeRoom = function(roomJid) { + delete _rooms[roomJid]; + }; + /** Function: getRooms * Gets all joined rooms * * Returns: * Object containing instances of Candy.Core.ChatRoom */ - self.getRooms = function() { - return _rooms; - }; - - /** Function: getStropheStatus + self.getRooms = function() { + return _rooms; + }; + /** Function: getStropheStatus * Get the status set by Strophe. * * Returns: * (Strophe.Status.*) - one of Strophe's statuses */ - self.getStropheStatus = function() { - return _status; - }; - - /** Function: setStropheStatus + self.getStropheStatus = function() { + return _status; + }; + /** Function: setStropheStatus * Set the strophe status * * Called by: @@ -388,30 +352,27 @@ Candy.Core = (function(self, Strophe, $) { * Parameters: * (Strophe.Status.*) status - Strophe's status */ - self.setStropheStatus = function(status) { - _status = status; - }; - - /** Function: isAnonymousConnection + self.setStropheStatus = function(status) { + _status = status; + }; + /** Function: isAnonymousConnection * Returns true if was first called with a domain instead of a jid as the first param. * * Returns: * (Boolean) */ - self.isAnonymousConnection = function() { - return _anonymousConnection; - }; - - /** Function: getOptions + self.isAnonymousConnection = function() { + return _anonymousConnection; + }; + /** Function: getOptions * Gets options * * Returns: * Object */ - self.getOptions = function() { - return _options; - }; - + self.getOptions = function() { + return _options; + }; /** Function: getRoom * Gets a specific room * @@ -421,51 +382,46 @@ Candy.Core = (function(self, Strophe, $) { * Returns: * If the room is joined, instance of Candy.Core.ChatRoom, otherwise null. */ - self.getRoom = function(roomJid) { - if (_rooms[roomJid]) { - return _rooms[roomJid]; - } - return null; - }; - - /** Function: onWindowUnload + self.getRoom = function(roomJid) { + if (_rooms[roomJid]) { + return _rooms[roomJid]; + } + return null; + }; + /** Function: onWindowUnload * window.onbeforeunload event which disconnects the client from the Jabber server. */ - self.onWindowUnload = function() { - // Enable synchronous requests because Safari doesn't send asynchronous requests within unbeforeunload events. - // Only works properly when following patch is applied to strophejs: https://github.com/metajack/strophejs/issues/16/#issuecomment-600266 - _connection.options.sync = true; - self.disconnect(); - _connection.flush(); - }; - - /** Function: rawInput + self.onWindowUnload = function() { + // Enable synchronous requests because Safari doesn't send asynchronous requests within unbeforeunload events. + // Only works properly when following patch is applied to strophejs: https://github.com/metajack/strophejs/issues/16/#issuecomment-600266 + _connection.options.sync = true; + self.disconnect(); + _connection.flush(); + }; + /** Function: rawInput * (Overridden from Strophe.Connection.rawInput) * * Logs all raw input if debug is set to true. */ - self.rawInput = function(data) { - this.log('RECV: ' + data); - }; - - /** Function rawOutput + self.rawInput = function(data) { + this.log("RECV: " + data); + }; + /** Function rawOutput * (Overridden from Strophe.Connection.rawOutput) * * Logs all raw output if debug is set to true. */ - self.rawOutput = function(data) { - this.log('SENT: ' + data); - }; - - /** Function: log + self.rawOutput = function(data) { + this.log("SENT: " + data); + }; + /** Function: log * Overridden to do something useful if debug is set to true. * * See: Candy.Core#init */ - self.log = function() {}; - - return self; -}(Candy.Core || {}, Strophe, jQuery)); + self.log = function() {}; + return self; +}(Candy.Core || {}, Strophe, jQuery); /** File: view.js * Candy - Chats are not dead yet. @@ -478,10 +434,9 @@ Candy.Core = (function(self, Strophe, $) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global jQuery, Candy, window, Mustache, document */ - /** Class: Candy.View * The Candy View Class * @@ -489,12 +444,14 @@ Candy.Core = (function(self, Strophe, $) { * (Candy.View) self - itself * (jQuery) $ - jQuery */ -Candy.View = (function(self, $) { - /** PrivateObject: _current +Candy.View = function(self, $) { + /** PrivateObject: _current * Object containing current container & roomJid which the client sees. */ - var _current = { container: null, roomJid: null }, - /** PrivateObject: _options + var _current = { + container: null, + roomJid: null + }, /** PrivateObject: _options * * Options: * (String) language - language to use @@ -502,17 +459,23 @@ Candy.View = (function(self, $) { * (Object) messages - limit: clean up message pane when n is reached / remove: remove n messages after limit has been reached * (Object) crop - crop if longer than defined: message.nickname=15, message.body=1000, roster.nickname=15 */ - _options = { - language: 'en', - resources: 'res/', - messages: { limit: 2000, remove: 500 }, - crop: { - message: { nickname: 15, body: 1000 }, - roster: { nickname: 15 } - } - }, - - /** PrivateFunction: _setupTranslation + _options = { + language: "en", + resources: "res/", + messages: { + limit: 2e3, + remove: 500 + }, + crop: { + message: { + nickname: 15, + body: 1e3 + }, + roster: { + nickname: 15 + } + } + }, /** PrivateFunction: _setupTranslation * Set dictionary using jQuery.i18n plugin. * * See: view/translation.js @@ -521,114 +484,99 @@ Candy.View = (function(self, $) { * Parameters: * (String) language - Language identifier */ - _setupTranslation = function(language) { - $.i18n.load(self.Translation[language]); - }, - - /** PrivateFunction: _registerObservers + _setupTranslation = function(language) { + $.i18n.load(self.Translation[language]); + }, /** PrivateFunction: _registerObservers * Register observers. Candy core will now notify the View on changes. */ - _registerObservers = function() { - $(Candy).on('candy:core.chat.connection', self.Observer.Chat.Connection); - $(Candy).on('candy:core.chat.message', self.Observer.Chat.Message); - $(Candy).on('candy:core.login', self.Observer.Login); - $(Candy).on('candy:core.autojoin-missing', self.Observer.AutojoinMissing); - $(Candy).on('candy:core.presence', self.Observer.Presence.update); - $(Candy).on('candy:core.presence.leave', self.Observer.Presence.update); - $(Candy).on('candy:core.presence.room', self.Observer.Presence.update); - $(Candy).on('candy:core.presence.error', self.Observer.PresenceError); - $(Candy).on('candy:core.message', self.Observer.Message); - }, - - /** PrivateFunction: _registerWindowHandlers + _registerObservers = function() { + $(Candy).on("candy:core.chat.connection", self.Observer.Chat.Connection); + $(Candy).on("candy:core.chat.message", self.Observer.Chat.Message); + $(Candy).on("candy:core.login", self.Observer.Login); + $(Candy).on("candy:core.autojoin-missing", self.Observer.AutojoinMissing); + $(Candy).on("candy:core.presence", self.Observer.Presence.update); + $(Candy).on("candy:core.presence.leave", self.Observer.Presence.update); + $(Candy).on("candy:core.presence.room", self.Observer.Presence.update); + $(Candy).on("candy:core.presence.error", self.Observer.PresenceError); + $(Candy).on("candy:core.message", self.Observer.Message); + }, /** PrivateFunction: _registerWindowHandlers * Register window focus / blur / resize handlers. * * jQuery.focus()/.blur() <= 1.5.1 do not work for IE < 9. Fortunately onfocusin/onfocusout will work for them. */ - _registerWindowHandlers = function() { - if(Candy.Util.getIeVersion() < 9) { - $(document).focusin(Candy.View.Pane.Window.onFocus).focusout(Candy.View.Pane.Window.onBlur); - } else { - $(window).focus(Candy.View.Pane.Window.onFocus).blur(Candy.View.Pane.Window.onBlur); - } - $(window).resize(Candy.View.Pane.Chat.fitTabs); - }, - - /** PrivateFunction: _initToolbar + _registerWindowHandlers = function() { + if (Candy.Util.getIeVersion() < 9) { + $(document).focusin(Candy.View.Pane.Window.onFocus).focusout(Candy.View.Pane.Window.onBlur); + } else { + $(window).focus(Candy.View.Pane.Window.onFocus).blur(Candy.View.Pane.Window.onBlur); + } + $(window).resize(Candy.View.Pane.Chat.fitTabs); + }, /** PrivateFunction: _initToolbar * Initialize toolbar. */ - _initToolbar = function() { - self.Pane.Chat.Toolbar.init(); - }, - - /** PrivateFunction: _delegateTooltips + _initToolbar = function() { + self.Pane.Chat.Toolbar.init(); + }, /** PrivateFunction: _delegateTooltips * Delegate mouseenter on tooltipified element to . */ - _delegateTooltips = function() { - $('body').delegate('li[data-tooltip]', 'mouseenter', Candy.View.Pane.Chat.Tooltip.show); - }; - - /** Function: init + _delegateTooltips = function() { + $("body").delegate("li[data-tooltip]", "mouseenter", Candy.View.Pane.Chat.Tooltip.show); + }; + /** Function: init * Initialize chat view (setup DOM, register handlers & observers) * * Parameters: * (jQuery.element) container - Container element of the whole chat view * (Object) options - Options: see _options field (value passed here gets extended by the default value in _options field) */ - self.init = function(container, options) { - $.extend(true, _options, options); - _setupTranslation(_options.language); - - // Set path to emoticons - Candy.Util.Parser.setEmoticonPath(this.getOptions().resources + 'img/emoticons/'); - - // Start DOMination... - _current.container = container; - _current.container.html(Mustache.to_html(Candy.View.Template.Chat.pane, { - tooltipEmoticons : $.i18n._('tooltipEmoticons'), - tooltipSound : $.i18n._('tooltipSound'), - tooltipAutoscroll : $.i18n._('tooltipAutoscroll'), - tooltipStatusmessage : $.i18n._('tooltipStatusmessage'), - tooltipAdministration : $.i18n._('tooltipAdministration'), - tooltipUsercount : $.i18n._('tooltipUsercount'), - resourcesPath : this.getOptions().resources - }, { - tabs: Candy.View.Template.Chat.tabs, - rooms: Candy.View.Template.Chat.rooms, - modal: Candy.View.Template.Chat.modal, - toolbar: Candy.View.Template.Chat.toolbar, - soundcontrol: Candy.View.Template.Chat.soundcontrol - })); - - // ... and let the elements dance. - _registerWindowHandlers(); - _initToolbar(); - _registerObservers(); - _delegateTooltips(); - }; - - /** Function: getCurrent + self.init = function(container, options) { + $.extend(true, _options, options); + _setupTranslation(_options.language); + // Set path to emoticons + Candy.Util.Parser.setEmoticonPath(this.getOptions().resources + "img/emoticons/"); + // Start DOMination... + _current.container = container; + _current.container.html(Mustache.to_html(Candy.View.Template.Chat.pane, { + tooltipEmoticons: $.i18n._("tooltipEmoticons"), + tooltipSound: $.i18n._("tooltipSound"), + tooltipAutoscroll: $.i18n._("tooltipAutoscroll"), + tooltipStatusmessage: $.i18n._("tooltipStatusmessage"), + tooltipAdministration: $.i18n._("tooltipAdministration"), + tooltipUsercount: $.i18n._("tooltipUsercount"), + resourcesPath: this.getOptions().resources + }, { + tabs: Candy.View.Template.Chat.tabs, + rooms: Candy.View.Template.Chat.rooms, + modal: Candy.View.Template.Chat.modal, + toolbar: Candy.View.Template.Chat.toolbar, + soundcontrol: Candy.View.Template.Chat.soundcontrol + })); + // ... and let the elements dance. + _registerWindowHandlers(); + _initToolbar(); + _registerObservers(); + _delegateTooltips(); + }; + /** Function: getCurrent * Get current container & roomJid in an object. * * Returns: * Object containing container & roomJid */ - self.getCurrent = function() { - return _current; - }; - - /** Function: getOptions + self.getCurrent = function() { + return _current; + }; + /** Function: getOptions * Gets options * * Returns: * Object */ - self.getOptions = function() { - return _options; - }; - - return self; -}(Candy.View || {}, jQuery)); + self.getOptions = function() { + return _options; + }; + return self; +}(Candy.View || {}, jQuery); /** File: util.js * Candy - Chats are not dead yet. @@ -641,10 +589,9 @@ Candy.View = (function(self, $) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy, MD5, Strophe, document, escape, jQuery */ - /** Class: Candy.Util * Candy utils * @@ -652,8 +599,8 @@ Candy.View = (function(self, $) { * (Candy.Util) self - itself * (jQuery) $ - jQuery */ -Candy.Util = (function(self, $){ - /** Function: jidToId +Candy.Util = function(self, $) { + /** Function: jidToId * Translates a jid to a MD5-Id * * Parameters: @@ -662,11 +609,10 @@ Candy.Util = (function(self, $){ * Returns: * MD5-ified jid */ - self.jidToId = function(jid) { - return MD5.hexdigest(jid); - }; - - /** Function: escapeJid + self.jidToId = function(jid) { + return MD5.hexdigest(jid); + }; + /** Function: escapeJid * Escapes a jid (node & resource get escaped) * * See: @@ -678,20 +624,15 @@ Candy.Util = (function(self, $){ * Returns: * (String) - escaped jid */ - self.escapeJid = function(jid) { - var node = Strophe.escapeNode(Strophe.getNodeFromJid(jid)), - domain = Strophe.getDomainFromJid(jid), - resource = Strophe.getResourceFromJid(jid); - - jid = node + '@' + domain; - if (resource) { - jid += '/' + resource; - } - - return jid; - }; - - /** Function: unescapeJid + self.escapeJid = function(jid) { + var node = Strophe.escapeNode(Strophe.getNodeFromJid(jid)), domain = Strophe.getDomainFromJid(jid), resource = Strophe.getResourceFromJid(jid); + jid = node + "@" + domain; + if (resource) { + jid += "/" + resource; + } + return jid; + }; + /** Function: unescapeJid * Unescapes a jid (node & resource get unescaped) * * See: @@ -703,34 +644,28 @@ Candy.Util = (function(self, $){ * Returns: * (String) - unescaped Jid */ - self.unescapeJid = function(jid) { - var node = Strophe.unescapeNode(Strophe.getNodeFromJid(jid)), - domain = Strophe.getDomainFromJid(jid), - resource = Strophe.getResourceFromJid(jid); - - jid = node + '@' + domain; - if(resource) { - jid += '/' + resource; - } - - return jid; - }; - - /** Function: crop + self.unescapeJid = function(jid) { + var node = Strophe.unescapeNode(Strophe.getNodeFromJid(jid)), domain = Strophe.getDomainFromJid(jid), resource = Strophe.getResourceFromJid(jid); + jid = node + "@" + domain; + if (resource) { + jid += "/" + resource; + } + return jid; + }; + /** Function: crop * Crop a string with the specified length * * Parameters: * (String) str - String to crop * (Integer) len - Max length */ - self.crop = function(str, len) { - if (str.length > len) { - str = str.substr(0, len - 3) + '...'; - } - return str; - }; - - /** Function: setCookie + self.crop = function(str, len) { + if (str.length > len) { + str = str.substr(0, len - 3) + "..."; + } + return str; + }; + /** Function: setCookie * Sets a new cookie * * Parameters: @@ -738,13 +673,12 @@ Candy.Util = (function(self, $){ * (String) value - Value * (Integer) lifetime_days - Lifetime in days */ - self.setCookie = function(name, value, lifetime_days) { - var exp = new Date(); - exp.setDate(new Date().getDate() + lifetime_days); - document.cookie = name + '=' + value + ';expires=' + exp.toUTCString() + ';path=/'; - }; - - /** Function: cookieExists + self.setCookie = function(name, value, lifetime_days) { + var exp = new Date(); + exp.setDate(new Date().getDate() + lifetime_days); + document.cookie = name + "=" + value + ";expires=" + exp.toUTCString() + ";path=/"; + }; + /** Function: cookieExists * Tests if a cookie with the given name exists * * Parameters: @@ -753,11 +687,10 @@ Candy.Util = (function(self, $){ * Returns: * (Boolean) - true/false */ - self.cookieExists = function(name) { - return document.cookie.indexOf(name) > -1; - }; - - /** Function: getCookie + self.cookieExists = function(name) { + return document.cookie.indexOf(name) > -1; + }; + /** Function: getCookie * Returns the cookie value if there's one with this name, otherwise returns undefined * * Parameters: @@ -766,27 +699,24 @@ Candy.Util = (function(self, $){ * Returns: * Cookie value or undefined */ - self.getCookie = function(name) { - if(document.cookie) { - var regex = new RegExp(escape(name) + '=([^;]*)', 'gm'), - matches = regex.exec(document.cookie); - if(matches) { - return matches[1]; - } - } - }; - - /** Function: deleteCookie + self.getCookie = function(name) { + if (document.cookie) { + var regex = new RegExp(escape(name) + "=([^;]*)", "gm"), matches = regex.exec(document.cookie); + if (matches) { + return matches[1]; + } + } + }; + /** Function: deleteCookie * Deletes a cookie with the given name * * Parameters: * (String) name - cookie name */ - self.deleteCookie = function(name) { - document.cookie = name + '=;expires=Thu, 01-Jan-70 00:00:01 GMT;path=/'; - }; - - /** Function: getPosLeftAccordingToWindowBounds + self.deleteCookie = function(name) { + document.cookie = name + "=;expires=Thu, 01-Jan-70 00:00:01 GMT;path=/"; + }; + /** Function: getPosLeftAccordingToWindowBounds * Fetches the window width and element width * and checks if specified position + element width is bigger * than the window width. @@ -800,21 +730,18 @@ Candy.Util = (function(self, $){ * Returns: * Object containing `px` (calculated position in pixel) and `alignment` (alignment of the element in relation to pos, either 'left' or 'right') */ - self.getPosLeftAccordingToWindowBounds = function(elem, pos) { - var windowWidth = $(document).width(), - elemWidth = elem.outerWidth(), - marginDiff = elemWidth - elem.outerWidth(true), - backgroundPositionAlignment = 'left'; - - if (pos + elemWidth >= windowWidth) { - pos -= elemWidth - marginDiff; - backgroundPositionAlignment = 'right'; - } - - return { px: pos, backgroundPositionAlignment: backgroundPositionAlignment }; - }; - - /** Function: getPosTopAccordingToWindowBounds + self.getPosLeftAccordingToWindowBounds = function(elem, pos) { + var windowWidth = $(document).width(), elemWidth = elem.outerWidth(), marginDiff = elemWidth - elem.outerWidth(true), backgroundPositionAlignment = "left"; + if (pos + elemWidth >= windowWidth) { + pos -= elemWidth - marginDiff; + backgroundPositionAlignment = "right"; + } + return { + px: pos, + backgroundPositionAlignment: backgroundPositionAlignment + }; + }; + /** Function: getPosTopAccordingToWindowBounds * Fetches the window height and element height * and checks if specified position + element height is bigger * than the window height. @@ -828,21 +755,18 @@ Candy.Util = (function(self, $){ * Returns: * Object containing `px` (calculated position in pixel) and `alignment` (alignment of the element in relation to pos, either 'top' or 'bottom') */ - self.getPosTopAccordingToWindowBounds = function(elem, pos) { - var windowHeight = $(document).height(), - elemHeight = elem.outerHeight(), - marginDiff = elemHeight - elem.outerHeight(true), - backgroundPositionAlignment = 'top'; - - if (pos + elemHeight >= windowHeight) { - pos -= elemHeight - marginDiff; - backgroundPositionAlignment = 'bottom'; - } - - return { px: pos, backgroundPositionAlignment: backgroundPositionAlignment }; - }; - - /** Function: localizedTime + self.getPosTopAccordingToWindowBounds = function(elem, pos) { + var windowHeight = $(document).height(), elemHeight = elem.outerHeight(), marginDiff = elemHeight - elem.outerHeight(true), backgroundPositionAlignment = "top"; + if (pos + elemHeight >= windowHeight) { + pos -= elemHeight - marginDiff; + backgroundPositionAlignment = "bottom"; + } + return { + px: pos, + backgroundPositionAlignment: backgroundPositionAlignment + }; + }; + /** Function: localizedTime * Localizes ISO-8610 Date with the time/dateformat specified in the translation. * * See: libs/dateformat/dateFormat.js @@ -855,20 +779,18 @@ Candy.Util = (function(self, $){ * Returns: * If current date is equal to the date supplied, format with timeFormat, otherwise with dateFormat */ - self.localizedTime = function(dateTime) { - if (dateTime === undefined) { - return undefined; - } - - var date = self.iso8601toDate(dateTime); - if(date.toDateString() === new Date().toDateString()) { - return date.format($.i18n._('timeFormat')); - } else { - return date.format($.i18n._('dateFormat')); - } - }; - - /** Function: iso8610toDate + self.localizedTime = function(dateTime) { + if (dateTime === undefined) { + return undefined; + } + var date = self.iso8601toDate(dateTime); + if (date.toDateString() === new Date().toDateString()) { + return date.format($.i18n._("timeFormat")); + } else { + return date.format($.i18n._("dateFormat")); + } + }; + /** Function: iso8610toDate * Parses a ISO-8610 Date to a Date-Object. * * Uses a fallback if the client's browser doesn't support it. @@ -886,29 +808,28 @@ Candy.Util = (function(self, $){ * Returns: * Date-Object */ - self.iso8601toDate = function(date) { - var timestamp = Date.parse(date); - if(isNaN(timestamp)) { - var struct = /^(\d{4}|[+\-]\d{6})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?))?/.exec(date); - if(struct) { - var minutesOffset = 0; - if(struct[8] !== 'Z') { - minutesOffset = +struct[10] * 60 + (+struct[11]); - if(struct[9] === '+') { - minutesOffset = -minutesOffset; - } - } - minutesOffset -= new Date().getTimezoneOffset(); - return new Date(+struct[1], +struct[2] - 1, +struct[3], +struct[4], +struct[5] + minutesOffset, +struct[6], struct[7] ? +struct[7].substr(0, 3) : 0); - } else { - // XEP-0091 date - timestamp = Date.parse(date.replace(/^(\d{4})(\d{2})(\d{2})/, '$1-$2-$3') + 'Z'); - } - } - return new Date(timestamp); - }; - - /** Function: isEmptyObject + self.iso8601toDate = function(date) { + var timestamp = Date.parse(date); + if (isNaN(timestamp)) { + var struct = /^(\d{4}|[+\-]\d{6})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?))?/.exec(date); + if (struct) { + var minutesOffset = 0; + if (struct[8] !== "Z") { + minutesOffset = +struct[10] * 60 + +struct[11]; + if (struct[9] === "+") { + minutesOffset = -minutesOffset; + } + } + minutesOffset -= new Date().getTimezoneOffset(); + return new Date(+struct[1], +struct[2] - 1, +struct[3], +struct[4], +struct[5] + minutesOffset, +struct[6], struct[7] ? +struct[7].substr(0, 3) : 0); + } else { + // XEP-0091 date + timestamp = Date.parse(date.replace(/^(\d{4})(\d{2})(\d{2})/, "$1-$2-$3") + "Z"); + } + } + return new Date(timestamp); + }; + /** Function: isEmptyObject * IE7 doesn't work with jQuery.isEmptyObject (<=1.5.1), workaround. * * Parameters: @@ -917,167 +838,141 @@ Candy.Util = (function(self, $){ * Returns: * Boolean true or false. */ - self.isEmptyObject = function(obj) { - var prop; - for(prop in obj) { - if (obj.hasOwnProperty(prop)) { - return false; - } - } - return true; - }; - - /** Function: forceRedraw + self.isEmptyObject = function(obj) { + var prop; + for (prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; + } + } + return true; + }; + /** Function: forceRedraw * Fix IE7 not redrawing under some circumstances. * * Parameters: * (jQuery.element) elem - jQuery element to redraw */ - self.forceRedraw = function(elem) { - elem.css({display:'none'}); - setTimeout(function() { - this.css({display:'block'}); - }.bind(elem), 1); - }; - - /** PrivateVariable: ie + self.forceRedraw = function(elem) { + elem.css({ + display: "none" + }); + setTimeout(function() { + this.css({ + display: "block" + }); + }.bind(elem), 1); + }; + /** PrivateVariable: ie * Checks for IE version * * From: http://stackoverflow.com/a/5574871/315242 */ - var ie = (function(){ - var undef, - v = 3, - div = document.createElement('div'), - all = div.getElementsByTagName('i'); - while ( - // adds innerhtml and continues as long as all[0] is truthy - div.innerHTML = '', - all[0] - ) {} - return v > 4 ? v : undef; - }()); - - /** Function: getIeVersion + var ie = function() { + var undef, v = 3, div = document.createElement("div"), all = div.getElementsByTagName("i"); + while (// adds innerhtml and continues as long as all[0] is truthy + div.innerHTML = "", all[0]) {} + return v > 4 ? v : undef; + }(); + /** Function: getIeVersion * Returns local variable `ie` which you can use to detect which IE version * is available. * * Use e.g. like this: if(Candy.Util.getIeVersion() < 9) alert('kaboom'); */ - self.getIeVersion = function() { - return ie; - }; - - /** Class: Candy.Util.Parser + self.getIeVersion = function() { + return ie; + }; + /** Class: Candy.Util.Parser * Parser for emoticons, links and also supports escaping. */ - self.Parser = { - /** PrivateVariable: _emoticonPath + self.Parser = { + /** PrivateVariable: _emoticonPath * Path to emoticons. * * Use setEmoticonPath() to change it */ - _emoticonPath: '', - - /** Function: setEmoticonPath + _emoticonPath: "", + /** Function: setEmoticonPath * Set emoticons location. * * Parameters: * (String) path - location of emoticons with trailing slash */ - setEmoticonPath: function(path) { - this._emoticonPath = path; - }, - - /** Array: emoticons + setEmoticonPath: function(path) { + this._emoticonPath = path; + }, + /** Array: emoticons * Array containing emoticons to be replaced by their images. * * Can be overridden/extended. */ - emoticons: [ - { - plain: ':)', - regex: /((\s):-?\)|:-?\)(\s|$))/gm, - image: 'Smiling.png' - }, - { - plain: ';)', - regex: /((\s);-?\)|;-?\)(\s|$))/gm, - image: 'Winking.png' - }, - { - plain: ':D', - regex: /((\s):-?D|:-?D(\s|$))/gm, - image: 'Grinning.png' - }, - { - plain: ';D', - regex: /((\s);-?D|;-?D(\s|$))/gm, - image: 'Grinning_Winking.png' - }, - { - plain: ':(', - regex: /((\s):-?\(|:-?\((\s|$))/gm, - image: 'Unhappy.png' - }, - { - plain: '^^', - regex: /((\s)\^\^|\^\^(\s|$))/gm, - image: 'Happy_3.png' - }, - { - plain: ':P', - regex: /((\s):-?P|:-?P(\s|$))/igm, - image: 'Tongue_Out.png' - }, - { - plain: ';P', - regex: /((\s);-?P|;-?P(\s|$))/igm, - image: 'Tongue_Out_Winking.png' - }, - { - plain: ':S', - regex: /((\s):-?S|:-?S(\s|$))/igm, - image: 'Confused.png' - }, - { - plain: ':/', - regex: /((\s):-?\/|:-?\/(\s|$))/gm, - image: 'Uncertain.png' - }, - { - plain: '8)', - regex: /((\s)8-?\)|8-?\)(\s|$))/gm, - image: 'Sunglasses.png' - }, - { - plain: '$)', - regex: /((\s)\$-?\)|\$-?\)(\s|$))/gm, - image: 'Greedy.png' - }, - { - plain: 'oO', - regex: /((\s)oO|oO(\s|$))/gm, - image: 'Huh.png' - }, - { - plain: ':x', - regex: /((\s):x|:x(\s|$))/gm, - image: 'Lips_Sealed.png' - }, - { - plain: ':666:', - regex: /((\s):666:|:666:(\s|$))/gm, - image: 'Devil.png' - }, - { - plain: '<3', - regex: /((\s)<3|<3(\s|$))/gm, - image: 'Heart.png' - } - ], - - /** Function: emotify + emoticons: [ { + plain: ":)", + regex: /((\s):-?\)|:-?\)(\s|$))/gm, + image: "Smiling.png" + }, { + plain: ";)", + regex: /((\s);-?\)|;-?\)(\s|$))/gm, + image: "Winking.png" + }, { + plain: ":D", + regex: /((\s):-?D|:-?D(\s|$))/gm, + image: "Grinning.png" + }, { + plain: ";D", + regex: /((\s);-?D|;-?D(\s|$))/gm, + image: "Grinning_Winking.png" + }, { + plain: ":(", + regex: /((\s):-?\(|:-?\((\s|$))/gm, + image: "Unhappy.png" + }, { + plain: "^^", + regex: /((\s)\^\^|\^\^(\s|$))/gm, + image: "Happy_3.png" + }, { + plain: ":P", + regex: /((\s):-?P|:-?P(\s|$))/gim, + image: "Tongue_Out.png" + }, { + plain: ";P", + regex: /((\s);-?P|;-?P(\s|$))/gim, + image: "Tongue_Out_Winking.png" + }, { + plain: ":S", + regex: /((\s):-?S|:-?S(\s|$))/gim, + image: "Confused.png" + }, { + plain: ":/", + regex: /((\s):-?\/|:-?\/(\s|$))/gm, + image: "Uncertain.png" + }, { + plain: "8)", + regex: /((\s)8-?\)|8-?\)(\s|$))/gm, + image: "Sunglasses.png" + }, { + plain: "$)", + regex: /((\s)\$-?\)|\$-?\)(\s|$))/gm, + image: "Greedy.png" + }, { + plain: "oO", + regex: /((\s)oO|oO(\s|$))/gm, + image: "Huh.png" + }, { + plain: ":x", + regex: /((\s):x|:x(\s|$))/gm, + image: "Lips_Sealed.png" + }, { + plain: ":666:", + regex: /((\s):666:|:666:(\s|$))/gm, + image: "Devil.png" + }, { + plain: "<3", + regex: /((\s)<3|<3(\s|$))/gm, + image: "Heart.png" + } ], + /** Function: emotify * Replaces text-emoticons with their image equivalent. * * Parameters: @@ -1086,15 +981,14 @@ Candy.Util = (function(self, $){ * Returns: * Emotified text */ - emotify: function(text) { - var i; - for(i = this.emoticons.length-1; i >= 0; i--) { - text = text.replace(this.emoticons[i].regex, '$2$1$3'); - } - return text; - }, - - /** Function: linkify + emotify: function(text) { + var i; + for (i = this.emoticons.length - 1; i >= 0; i--) { + text = text.replace(this.emoticons[i].regex, '$2$1$3'); + } + return text; + }, + /** Function: linkify * Replaces URLs with a HTML-link. * * Parameters: @@ -1103,12 +997,11 @@ Candy.Util = (function(self, $){ * Returns: * Linkified text */ - linkify: function(text) { - text = text.replace(/(^|[^\/])(www\.[^\.]+\.[\S]+(\b|$))/gi, '$1http://$2'); - return text.replace(/(\b(https?|ftp|file):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/ig, '$1'); - }, - - /** Function: escape + linkify: function(text) { + text = text.replace(/(^|[^\/])(www\.[^\.]+\.[\S]+(\b|$))/gi, "$1http://$2"); + return text.replace(/(\b(https?|ftp|file):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/gi, '$1'); + }, + /** Function: escape * Escapes a text using a jQuery function (like htmlspecialchars in PHP) * * Parameters: @@ -1117,11 +1010,10 @@ Candy.Util = (function(self, $){ * Returns: * Escaped text */ - escape: function(text) { - return $('
').text(text).html(); - }, - - /** Function: nl2br + escape: function(text) { + return $("
").text(text).html(); + }, + /** Function: nl2br * replaces newline characters with a
to make multi line messages look nice * * Parameters: @@ -1130,11 +1022,10 @@ Candy.Util = (function(self, $){ * Returns: * Processed text */ - nl2br: function(text) { - return text.replace(/\r\n|\r|\n/g, '
'); - }, - - /** Function: all + nl2br: function(text) { + return text.replace(/\r\n|\r|\n/g, "
"); + }, + /** Function: all * Does everything of the parser: escaping, linkifying and emotifying. * * Parameters: @@ -1143,19 +1034,18 @@ Candy.Util = (function(self, $){ * Returns: * Parsed text */ - all: function(text) { - if(text) { - text = this.escape(text); - text = this.linkify(text); - text = this.emotify(text); - text = this.nl2br(text); - } - return text; - } - }; - - return self; -}(Candy.Util || {}, jQuery)); + all: function(text) { + if (text) { + text = this.escape(text); + text = this.linkify(text); + text = this.emotify(text); + text = this.nl2br(text); + } + return text; + } + }; + return self; +}(Candy.Util || {}, jQuery); /** File: action.js * Candy - Chats are not dead yet. @@ -1168,10 +1058,9 @@ Candy.Util = (function(self, $){ * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy, $iq, navigator, Candy, $pres, Strophe, jQuery */ - /** Class: Candy.Core.Action * Chat Actions (basicly a abstraction of Jabber commands) * @@ -1180,31 +1069,30 @@ Candy.Util = (function(self, $){ * (Strophe) Strophe - Strophe * (jQuery) $ - jQuery */ -Candy.Core.Action = (function(self, Strophe, $) { - /** Class: Candy.Core.Action.Jabber +Candy.Core.Action = function(self, Strophe, $) { + /** Class: Candy.Core.Action.Jabber * Jabber actions */ - self.Jabber = { - /** Function: Version + self.Jabber = { + /** Function: Version * Replies to a version request * * Parameters: * (jQuery.element) msg - jQuery element */ - Version: function(msg) { - Candy.Core.getConnection().send($iq({ - type: 'result', - to: Candy.Util.escapeJid(msg.attr('from')), - from: Candy.Util.escapeJid(msg.attr('to')), - id: msg.attr('id') - }).c('query', { - name: Candy.about.name, - version: Candy.about.version, - os: navigator.userAgent - })); - }, - - /** Function: SetNickname + Version: function(msg) { + Candy.Core.getConnection().send($iq({ + type: "result", + to: Candy.Util.escapeJid(msg.attr("from")), + from: Candy.Util.escapeJid(msg.attr("to")), + id: msg.attr("id") + }).c("query", { + name: Candy.about.name, + version: Candy.about.version, + os: navigator.userAgent + })); + }, + /** Function: SetNickname * Sets the supplied nickname for all rooms (if parameter "room" is not specified) or * sets it only for the specified rooms * @@ -1212,52 +1100,56 @@ Candy.Core.Action = (function(self, Strophe, $) { * (String) nickname - New nickname * (Array) rooms - Rooms */ - SetNickname: function(nickname, rooms) { - rooms = rooms instanceof Array ? rooms : Candy.Core.getRooms(); - var roomNick, presence; - $.each(rooms, function(roomJid) { - roomNick = Candy.Util.escapeJid(roomJid + '/' + nickname); - presence = $pres({ - to: roomNick, - from: Candy.Core.getConnection().jid, - id: 'pres:' + Candy.Core.getConnection().getUniqueId() - }); - Candy.Core.getConnection().send(presence); - }); - }, - - /** Function: Roster + SetNickname: function(nickname, rooms) { + rooms = rooms instanceof Array ? rooms : Candy.Core.getRooms(); + var roomNick, presence; + $.each(rooms, function(roomJid) { + roomNick = Candy.Util.escapeJid(roomJid + "/" + nickname); + presence = $pres({ + to: roomNick, + from: Candy.Core.getConnection().jid, + id: "pres:" + Candy.Core.getConnection().getUniqueId() + }); + Candy.Core.getConnection().send(presence); + }); + }, + /** Function: Roster * Sends a request for a roster */ - Roster: function() { - Candy.Core.getConnection().send($iq({type: 'get', xmlns: Strophe.NS.CLIENT}).c('query', {xmlns: Strophe.NS.ROSTER}).tree()); - }, - - /** Function: Presence + Roster: function() { + Candy.Core.getConnection().send($iq({ + type: "get", + xmlns: Strophe.NS.CLIENT + }).c("query", { + xmlns: Strophe.NS.ROSTER + }).tree()); + }, + /** Function: Presence * Sends a request for presence * * Parameters: * (Object) attr - Optional attributes * (Strophe.Builder) el - Optional element to include in presence stanza */ - Presence: function(attr, el) { - var pres = $pres(attr).c('priority').t(Candy.Core.getOptions().presencePriority.toString()) - .up().c('c', Candy.Core.getConnection().caps.generateCapsAttrs()) - .up(); - if(el) { - pres.node.appendChild(el.node); - } - Candy.Core.getConnection().send(pres.tree()); - }, - - /** Function: Services + Presence: function(attr, el) { + var pres = $pres(attr).c("priority").t(Candy.Core.getOptions().presencePriority.toString()).up().c("c", Candy.Core.getConnection().caps.generateCapsAttrs()).up(); + if (el) { + pres.node.appendChild(el.node); + } + Candy.Core.getConnection().send(pres.tree()); + }, + /** Function: Services * Sends a request for disco items */ - Services: function() { - Candy.Core.getConnection().send($iq({type: 'get', xmlns: Strophe.NS.CLIENT}).c('query', {xmlns: Strophe.NS.DISCO_ITEMS}).tree()); - }, - - /** Function: Autojoin + Services: function() { + Candy.Core.getConnection().send($iq({ + type: "get", + xmlns: Strophe.NS.CLIENT + }).c("query", { + xmlns: Strophe.NS.DISCO_ITEMS + }).tree()); + }, + /** Function: Autojoin * When Candy.Core.getOptions().autojoin is true, request autojoin bookmarks (OpenFire) * * Otherwise, if Candy.Core.getOptions().autojoin is an array, join each channel specified. @@ -1266,97 +1158,101 @@ Candy.Core.Action = (function(self, Strophe, $) { * Triggers: * candy:core.autojoin-missing in case no autojoin info has been found */ - Autojoin: function() { - // Request bookmarks - if(Candy.Core.getOptions().autojoin === true) { - Candy.Core.getConnection().sendIQ($iq({ - type: 'get', - xmlns: Strophe.NS.CLIENT - }) - .c('query', {xmlns: Strophe.NS.PRIVATE}) - .c('storage', {xmlns: Strophe.NS.BOOKMARKS}) - .tree()); - // Join defined rooms - } else if($.isArray(Candy.Core.getOptions().autojoin)) { - $.each(Candy.Core.getOptions().autojoin, function() { - self.Jabber.Room.Join.apply(null, this.valueOf().split(':',2)); - }); - } else { - /** Event: candy:core.autojoin-missing + Autojoin: function() { + // Request bookmarks + if (Candy.Core.getOptions().autojoin === true) { + Candy.Core.getConnection().sendIQ($iq({ + type: "get", + xmlns: Strophe.NS.CLIENT + }).c("query", { + xmlns: Strophe.NS.PRIVATE + }).c("storage", { + xmlns: Strophe.NS.BOOKMARKS + }).tree()); + } else if ($.isArray(Candy.Core.getOptions().autojoin)) { + $.each(Candy.Core.getOptions().autojoin, function() { + self.Jabber.Room.Join.apply(null, this.valueOf().split(":", 2)); + }); + } else { + /** Event: candy:core.autojoin-missing * Triggered when no autojoin information has been found */ - $(Candy).triggerHandler('candy:core.autojoin-missing'); - } - }, - - /** Function: ResetIgnoreList + $(Candy).triggerHandler("candy:core.autojoin-missing"); + } + }, + /** Function: ResetIgnoreList * Create new ignore privacy list (and reset the previous one, if it exists). */ - ResetIgnoreList: function() { - Candy.Core.getConnection().sendIQ($iq({ - type: 'set', - from: Candy.Core.getUser().getEscapedJid() - }) - .c('query', {xmlns: Strophe.NS.PRIVACY }) - .c('list', {name: 'ignore'}) - .c('item', {'action': 'allow', 'order': '0'}) - .tree()); - }, - - /** Function: RemoveIgnoreList + ResetIgnoreList: function() { + Candy.Core.getConnection().sendIQ($iq({ + type: "set", + from: Candy.Core.getUser().getEscapedJid() + }).c("query", { + xmlns: Strophe.NS.PRIVACY + }).c("list", { + name: "ignore" + }).c("item", { + action: "allow", + order: "0" + }).tree()); + }, + /** Function: RemoveIgnoreList * Remove an existing ignore list. */ - RemoveIgnoreList: function() { - Candy.Core.getConnection().sendIQ($iq({ - type: 'set', - from: Candy.Core.getUser().getEscapedJid() - }) - .c('query', {xmlns: Strophe.NS.PRIVACY }) - .c('list', {name: 'ignore'}).tree()); - }, - - /** Function: GetIgnoreList + RemoveIgnoreList: function() { + Candy.Core.getConnection().sendIQ($iq({ + type: "set", + from: Candy.Core.getUser().getEscapedJid() + }).c("query", { + xmlns: Strophe.NS.PRIVACY + }).c("list", { + name: "ignore" + }).tree()); + }, + /** Function: GetIgnoreList * Get existing ignore privacy list when connecting. */ - GetIgnoreList: function() { - var iq = $iq({ - type: 'get', - from: Candy.Core.getUser().getEscapedJid() - }) - .c('query', {xmlns: Strophe.NS.PRIVACY}) - .c('list', {name: 'ignore'}).tree(); - var iqId = Candy.Core.getConnection().sendIQ(iq); - // add handler (<#200 at https://github.com/candy-chat/candy/issues/200>) - Candy.Core.addHandler(Candy.Core.Event.Jabber.PrivacyList, null, 'iq', null, iqId); - }, - - /** Function: SetIgnoreListActive + GetIgnoreList: function() { + var iq = $iq({ + type: "get", + from: Candy.Core.getUser().getEscapedJid() + }).c("query", { + xmlns: Strophe.NS.PRIVACY + }).c("list", { + name: "ignore" + }).tree(); + var iqId = Candy.Core.getConnection().sendIQ(iq); + // add handler (<#200 at https://github.com/candy-chat/candy/issues/200>) + Candy.Core.addHandler(Candy.Core.Event.Jabber.PrivacyList, null, "iq", null, iqId); + }, + /** Function: SetIgnoreListActive * Set ignore privacy list active */ - SetIgnoreListActive: function() { - Candy.Core.getConnection().sendIQ($iq({ - type: 'set', - from: Candy.Core.getUser().getEscapedJid()}) - .c('query', {xmlns: Strophe.NS.PRIVACY }) - .c('active', {name:'ignore'}).tree()); - }, - - /** Function: GetJidIfAnonymous + SetIgnoreListActive: function() { + Candy.Core.getConnection().sendIQ($iq({ + type: "set", + from: Candy.Core.getUser().getEscapedJid() + }).c("query", { + xmlns: Strophe.NS.PRIVACY + }).c("active", { + name: "ignore" + }).tree()); + }, + /** Function: GetJidIfAnonymous * On anonymous login, initially we don't know the jid and as a result, Candy.Core._user doesn't have a jid. * Check if user doesn't have a jid and get it if necessary from the connection. */ - GetJidIfAnonymous: function() { - if (!Candy.Core.getUser().getJid()) { - Candy.Core.log("[Jabber] Anonymous login"); - Candy.Core.getUser().data.jid = Candy.Core.getConnection().jid; - } - }, - - /** Class: Candy.Core.Action.Jabber.Room + GetJidIfAnonymous: function() { + if (!Candy.Core.getUser().getJid()) { + Candy.Core.log("[Jabber] Anonymous login"); + Candy.Core.getUser().data.jid = Candy.Core.getConnection().jid; + } + }, + /** Class: Candy.Core.Action.Jabber.Room * Room-specific commands */ - Room: { - /** Function: Join + Room: { + /** Function: Join * Requests disco of specified room and joins afterwards. * * TODO: @@ -1367,49 +1263,49 @@ Candy.Core.Action = (function(self, Strophe, $) { * (String) roomJid - Room to join * (String) password - [optional] Password for the room */ - Join: function(roomJid, password) { - self.Jabber.Room.Disco(roomJid); - roomJid = Candy.Util.escapeJid(roomJid); - var conn = Candy.Core.getConnection(), - roomNick = roomJid + '/' + Candy.Core.getUser().getNick(), - pres = $pres({ to: roomNick }) - .c('x', {xmlns: Strophe.NS.MUC}); - if (password) { - pres.c('password').t(password); - } - pres.up().c('c', conn.caps.generateCapsAttrs()); - conn.send(pres.tree()); - }, - - /** Function: Leave + Join: function(roomJid, password) { + self.Jabber.Room.Disco(roomJid); + roomJid = Candy.Util.escapeJid(roomJid); + var conn = Candy.Core.getConnection(), roomNick = roomJid + "/" + Candy.Core.getUser().getNick(), pres = $pres({ + to: roomNick + }).c("x", { + xmlns: Strophe.NS.MUC + }); + if (password) { + pres.c("password").t(password); + } + pres.up().c("c", conn.caps.generateCapsAttrs()); + conn.send(pres.tree()); + }, + /** Function: Leave * Leaves a room. * * Parameters: * (String) roomJid - Room to leave */ - Leave: function(roomJid) { - var user = Candy.Core.getRoom(roomJid).getUser(); - roomJid = Candy.Util.escapeJid(roomJid); - if (user) { - Candy.Core.getConnection().muc.leave(roomJid, user.getNick(), function() {}); - } - }, - - /** Function: Disco + Leave: function(roomJid) { + var user = Candy.Core.getRoom(roomJid).getUser(); + roomJid = Candy.Util.escapeJid(roomJid); + if (user) { + Candy.Core.getConnection().muc.leave(roomJid, user.getNick(), function() {}); + } + }, + /** Function: Disco * Requests . * * Parameters: * (String) roomJid - Room to get info for */ - Disco: function(roomJid) { - Candy.Core.getConnection().sendIQ($iq({ - type: 'get', - from: Candy.Core.getUser().getEscapedJid(), - to: Candy.Util.escapeJid(roomJid) - }).c('query', {xmlns: Strophe.NS.DISCO_INFO}).tree()); - }, - - /** Function: Message + Disco: function(roomJid) { + Candy.Core.getConnection().sendIQ($iq({ + type: "get", + from: Candy.Core.getUser().getEscapedJid(), + to: Candy.Util.escapeJid(roomJid) + }).c("query", { + xmlns: Strophe.NS.DISCO_INFO + }).tree()); + }, + /** Function: Message * Send message * * Parameters: @@ -1420,17 +1316,16 @@ Candy.Core.Action = (function(self, Strophe, $) { * Returns: * (Boolean) - true if message is not empty after trimming, false otherwise. */ - Message: function(roomJid, msg, type) { - // Trim message - msg = $.trim(msg); - if(msg === '') { - return false; - } - Candy.Core.getConnection().muc.message(Candy.Util.escapeJid(roomJid), null, msg, null, type); - return true; - }, - - /** Function: IgnoreUnignore + Message: function(roomJid, msg, type) { + // Trim message + msg = $.trim(msg); + if (msg === "") { + return false; + } + Candy.Core.getConnection().muc.message(Candy.Util.escapeJid(roomJid), null, msg, null, type); + return true; + }, + /** Function: IgnoreUnignore * Checks if the user is already ignoring the target user, if yes: unignore him, if no: ignore him. * * Uses the ignore privacy list set on connecting. @@ -1438,36 +1333,44 @@ Candy.Core.Action = (function(self, Strophe, $) { * Parameters: * (String) userJid - Target user jid */ - IgnoreUnignore: function(userJid) { - Candy.Core.getUser().addToOrRemoveFromPrivacyList('ignore', userJid); - Candy.Core.Action.Jabber.Room.UpdatePrivacyList(); - }, - - /** Function: UpdatePrivacyList + IgnoreUnignore: function(userJid) { + Candy.Core.getUser().addToOrRemoveFromPrivacyList("ignore", userJid); + Candy.Core.Action.Jabber.Room.UpdatePrivacyList(); + }, + /** Function: UpdatePrivacyList * Updates privacy list according to the privacylist in the currentUser */ - UpdatePrivacyList: function() { - var currentUser = Candy.Core.getUser(), - iq = $iq({type: 'set', from: currentUser.getEscapedJid()}) - .c('query', {xmlns: 'jabber:iq:privacy' }) - .c('list', {name: 'ignore'}), - privacyList = currentUser.getPrivacyList('ignore'); - if (privacyList.length > 0) { - $.each(privacyList, function(index, jid) { - iq.c('item', {type:'jid', value: Candy.Util.escapeJid(jid), action: 'deny', order : index}) - .c('message').up().up(); - }); - } else { - iq.c('item', {action: 'allow', order : '0'}); - } - Candy.Core.getConnection().sendIQ(iq.tree()); - }, - - /** Class: Candy.Core.Action.Jabber.Room.Admin + UpdatePrivacyList: function() { + var currentUser = Candy.Core.getUser(), iq = $iq({ + type: "set", + from: currentUser.getEscapedJid() + }).c("query", { + xmlns: "jabber:iq:privacy" + }).c("list", { + name: "ignore" + }), privacyList = currentUser.getPrivacyList("ignore"); + if (privacyList.length > 0) { + $.each(privacyList, function(index, jid) { + iq.c("item", { + type: "jid", + value: Candy.Util.escapeJid(jid), + action: "deny", + order: index + }).c("message").up().up(); + }); + } else { + iq.c("item", { + action: "allow", + order: "0" + }); + } + Candy.Core.getConnection().sendIQ(iq.tree()); + }, + /** Class: Candy.Core.Action.Jabber.Room.Admin * Room administration commands */ - Admin: { - /** Function: UserAction + Admin: { + /** Function: UserAction * Kick or ban a user * * Parameters: @@ -1479,45 +1382,48 @@ Candy.Core.Action = (function(self, Strophe, $) { * Returns: * (Boolean) - true if sent successfully, false if type is not one of "kick" or "ban". */ - UserAction: function(roomJid, userJid, type, reason) { - roomJid = Candy.Util.escapeJid(roomJid); - userJid = Candy.Util.escapeJid(userJid); - var itemObj = {nick: Strophe.getResourceFromJid(userJid)}; - switch(type) { - case 'kick': - itemObj.role = 'none'; - break; - case 'ban': - itemObj.affiliation = 'outcast'; - break; - default: - return false; - } - Candy.Core.getConnection().sendIQ($iq({ - type: 'set', - from: Candy.Core.getUser().getEscapedJid(), - to: roomJid - }).c('query', {xmlns: Strophe.NS.MUC_ADMIN }) - .c('item', itemObj).c('reason').t(reason).tree()); - return true; - }, - - /** Function: SetSubject + UserAction: function(roomJid, userJid, type, reason) { + roomJid = Candy.Util.escapeJid(roomJid); + userJid = Candy.Util.escapeJid(userJid); + var itemObj = { + nick: Strophe.getResourceFromJid(userJid) + }; + switch (type) { + case "kick": + itemObj.role = "none"; + break; + + case "ban": + itemObj.affiliation = "outcast"; + break; + + default: + return false; + } + Candy.Core.getConnection().sendIQ($iq({ + type: "set", + from: Candy.Core.getUser().getEscapedJid(), + to: roomJid + }).c("query", { + xmlns: Strophe.NS.MUC_ADMIN + }).c("item", itemObj).c("reason").t(reason).tree()); + return true; + }, + /** Function: SetSubject * Sets subject (topic) of a room. * * Parameters: * (String) roomJid - Room * (String) subject - Subject to set */ - SetSubject: function(roomJid, subject) { - Candy.Core.getConnection().muc.setTopic(Candy.Util.escapeJid(roomJid), subject); - } - } - } - }; - - return self; -}(Candy.Core.Action || {}, Strophe, jQuery)); + SetSubject: function(roomJid, subject) { + Candy.Core.getConnection().muc.setTopic(Candy.Util.escapeJid(roomJid), subject); + } + } + } + }; + return self; +}(Candy.Core.Action || {}, Strophe, jQuery); /** File: chatRoom.js * Candy - Chats are not dead yet. @@ -1530,10 +1436,9 @@ Candy.Core.Action = (function(self, Strophe, $) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy, Strophe */ - /** Class: Candy.Core.ChatRoom * Candy Chat Room * @@ -1541,93 +1446,84 @@ Candy.Core.Action = (function(self, Strophe, $) { * (String) roomJid - Room jid */ Candy.Core.ChatRoom = function(roomJid) { - /** Object: room + /** Object: room * Object containing roomJid and name. */ - this.room = { - jid: roomJid, - name: Strophe.getNodeFromJid(roomJid) - }; - - /** Variable: user + this.room = { + jid: roomJid, + name: Strophe.getNodeFromJid(roomJid) + }; + /** Variable: user * Current local user of this room. */ - this.user = null; - - /** Variable: Roster + this.user = null; + /** Variable: Roster * Candy.Core.ChatRoster instance */ - this.roster = new Candy.Core.ChatRoster(); - - /** Function: setUser + this.roster = new Candy.Core.ChatRoster(); + /** Function: setUser * Set user of this room. * * Parameters: * (Candy.Core.ChatUser) user - Chat user */ - this.setUser = function(user) { - this.user = user; - }; - - /** Function: getUser + this.setUser = function(user) { + this.user = user; + }; + /** Function: getUser * Get current local user * * Returns: * (Object) - Candy.Core.ChatUser instance or null */ - this.getUser = function() { - return this.user; - }; - - /** Function: getJid + this.getUser = function() { + return this.user; + }; + /** Function: getJid * Get room jid * * Returns: * (String) - Room jid */ - this.getJid = function() { - return this.room.jid; - }; - - /** Function: setName + this.getJid = function() { + return this.room.jid; + }; + /** Function: setName * Set room name * * Parameters: * (String) name - Room name */ - this.setName = function(name) { - this.room.name = name; - }; - - /** Function: getName + this.setName = function(name) { + this.room.name = name; + }; + /** Function: getName * Get room name * * Returns: * (String) - Room name */ - this.getName = function() { - return this.room.name; - }; - - /** Function: setRoster + this.getName = function() { + return this.room.name; + }; + /** Function: setRoster * Set roster of room * * Parameters: * (Candy.Core.ChatRoster) roster - Chat roster */ - this.setRoster = function(roster) { - this.roster = roster; - }; - - /** Function: getRoster + this.setRoster = function(roster) { + this.roster = roster; + }; + /** Function: getRoster * Get roster * * Returns * (Candy.Core.ChatRoster) - instance */ - this.getRoster = function() { - return this.roster; - }; + this.getRoster = function() { + return this.roster; + }; }; /** File: chatRoster.js @@ -1641,40 +1537,36 @@ Candy.Core.ChatRoom = function(roomJid) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy */ - /** Class: Candy.Core.ChatRoster * Chat Roster */ -Candy.Core.ChatRoster = function () { - /** Object: items +Candy.Core.ChatRoster = function() { + /** Object: items * Roster items */ - this.items = {}; - - /** Function: add + this.items = {}; + /** Function: add * Add user to roster * * Parameters: * (Candy.Core.ChatUser) user - User to add */ - this.add = function(user) { - this.items[user.getJid()] = user; - }; - - /** Function: remove + this.add = function(user) { + this.items[user.getJid()] = user; + }; + /** Function: remove * Remove user from roster * * Parameters: * (String) jid - User jid */ - this.remove = function(jid) { - delete this.items[jid]; - }; - - /** Function: get + this.remove = function(jid) { + delete this.items[jid]; + }; + /** Function: get * Get user from roster * * Parameters: @@ -1683,19 +1575,18 @@ Candy.Core.ChatRoster = function () { * Returns: * (Candy.Core.ChatUser) - User */ - this.get = function(jid) { - return this.items[jid]; - }; - - /** Function: getAll + this.get = function(jid) { + return this.items[jid]; + }; + /** Function: getAll * Get all items * * Returns: * (Object) - all roster items */ - this.getAll = function() { - return this.items; - }; + this.getAll = function() { + return this.items; + }; }; /** File: chatUser.js @@ -1709,25 +1600,22 @@ Candy.Core.ChatRoster = function () { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy, Strophe */ - /** Class: Candy.Core.ChatUser * Chat User */ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { - /** Constant: ROLE_MODERATOR + /** Constant: ROLE_MODERATOR * Moderator role */ - this.ROLE_MODERATOR = 'moderator'; - - /** Constant: AFFILIATION_OWNER + this.ROLE_MODERATOR = "moderator"; + /** Constant: AFFILIATION_OWNER * Affiliation owner */ - this.AFFILIATION_OWNER = 'owner'; - - /** Object: data + this.AFFILIATION_OWNER = "owner"; + /** Object: data * User data containing: * - jid * - nick @@ -1736,17 +1624,16 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * - privacyLists * - customData to be used by e.g. plugins */ - this.data = { - jid: jid, - nick: Strophe.unescapeNode(nick), - affiliation: affiliation, - role: role, - privacyLists: {}, - customData: {}, - previousNick: undefined - }; - - /** Function: getJid + this.data = { + jid: jid, + nick: Strophe.unescapeNode(nick), + affiliation: affiliation, + role: role, + privacyLists: {}, + customData: {}, + previousNick: undefined + }; + /** Function: getJid * Gets an unescaped user jid * * See: @@ -1755,14 +1642,13 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * Returns: * (String) - jid */ - this.getJid = function() { - if(this.data.jid) { - return Candy.Util.unescapeJid(this.data.jid); - } - return; - }; - - /** Function: getEscapedJid + this.getJid = function() { + if (this.data.jid) { + return Candy.Util.unescapeJid(this.data.jid); + } + return; + }; + /** Function: getEscapedJid * Escapes the user's jid (node & resource get escaped) * * See: @@ -1771,71 +1657,64 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * Returns: * (String) - escaped jid */ - this.getEscapedJid = function() { - return Candy.Util.escapeJid(this.data.jid); - }; - - /** Function: setJid + this.getEscapedJid = function() { + return Candy.Util.escapeJid(this.data.jid); + }; + /** Function: setJid * Sets a user's jid * * Parameters: * (String) jid - New Jid */ - this.setJid = function(jid) { - this.data.jid = jid; - }; - - /** Function: getNick + this.setJid = function(jid) { + this.data.jid = jid; + }; + /** Function: getNick * Gets user nick * * Returns: * (String) - nick */ - this.getNick = function() { - return Strophe.unescapeNode(this.data.nick); - }; - - /** Function: setNick + this.getNick = function() { + return Strophe.unescapeNode(this.data.nick); + }; + /** Function: setNick * Sets a user's nick * * Parameters: * (String) nick - New nick */ - this.setNick = function(nick) { - this.data.nick = nick; - }; - - /** Function: getRole + this.setNick = function(nick) { + this.data.nick = nick; + }; + /** Function: getRole * Gets user role * * Returns: * (String) - role */ - this.getRole = function() { - return this.data.role; - }; - - /** Function: getAffiliation + this.getRole = function() { + return this.data.role; + }; + /** Function: getAffiliation * Gets user affiliation * * Returns: * (String) - affiliation */ - this.getAffiliation = function() { - return this.data.affiliation; - }; - - /** Function: isModerator + this.getAffiliation = function() { + return this.data.affiliation; + }; + /** Function: isModerator * Check if user is moderator. Depends on the room. * * Returns: * (Boolean) - true if user has role moderator or affiliation owner */ - this.isModerator = function() { - return this.getRole() === this.ROLE_MODERATOR || this.getAffiliation() === this.AFFILIATION_OWNER; - }; - - /** Function: addToOrRemoveFromPrivacyList + this.isModerator = function() { + return this.getRole() === this.ROLE_MODERATOR || this.getAffiliation() === this.AFFILIATION_OWNER; + }; + /** Function: addToOrRemoveFromPrivacyList * Convenience function for adding/removing users from ignore list. * * Check if user is already in privacy list. If yes, remove it. If no, add it. @@ -1847,20 +1726,19 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * Returns: * (Array) - Current privacy list. */ - this.addToOrRemoveFromPrivacyList = function(list, jid) { - if (!this.data.privacyLists[list]) { - this.data.privacyLists[list] = []; - } - var index = -1; - if ((index = this.data.privacyLists[list].indexOf(jid)) !== -1) { - this.data.privacyLists[list].splice(index, 1); - } else { - this.data.privacyLists[list].push(jid); - } - return this.data.privacyLists[list]; - }; - - /** Function: getPrivacyList + this.addToOrRemoveFromPrivacyList = function(list, jid) { + if (!this.data.privacyLists[list]) { + this.data.privacyLists[list] = []; + } + var index = -1; + if ((index = this.data.privacyLists[list].indexOf(jid)) !== -1) { + this.data.privacyLists[list].splice(index, 1); + } else { + this.data.privacyLists[list].push(jid); + } + return this.data.privacyLists[list]; + }; + /** Function: getPrivacyList * Returns the privacy list of the listname of the param. * * Parameters: @@ -1869,24 +1747,22 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * Returns: * (Array) - Privacy List */ - this.getPrivacyList = function(list) { - if (!this.data.privacyLists[list]) { - this.data.privacyLists[list] = []; - } - return this.data.privacyLists[list]; - }; - - /** Function: setPrivacyLists + this.getPrivacyList = function(list) { + if (!this.data.privacyLists[list]) { + this.data.privacyLists[list] = []; + } + return this.data.privacyLists[list]; + }; + /** Function: setPrivacyLists * Sets privacy lists. * * Parameters: * (Object) lists - List object */ - this.setPrivacyLists = function(lists) { - this.data.privacyLists = lists; - }; - - /** Function: isInPrivacyList + this.setPrivacyLists = function(lists) { + this.data.privacyLists = lists; + }; + /** Function: isInPrivacyList * Tests if this user ignores the user provided by jid. * * Parameters: @@ -1896,52 +1772,48 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * Returns: * (Boolean) */ - this.isInPrivacyList = function(list, jid) { - if (!this.data.privacyLists[list]) { - return false; - } - return this.data.privacyLists[list].indexOf(jid) !== -1; - }; - - /** Function: setCustomData + this.isInPrivacyList = function(list, jid) { + if (!this.data.privacyLists[list]) { + return false; + } + return this.data.privacyLists[list].indexOf(jid) !== -1; + }; + /** Function: setCustomData * Stores custom data * * Parameter: * (Object) data - Object containing custom data */ - this.setCustomData = function(data) { - this.data.customData = data; - }; - - /** Function: getCustomData + this.setCustomData = function(data) { + this.data.customData = data; + }; + /** Function: getCustomData * Retrieve custom data * * Returns: * (Object) - Object containing custom data */ - this.getCustomData = function() { - return this.data.customData; - }; - - /** Function: setPreviousNick + this.getCustomData = function() { + return this.data.customData; + }; + /** Function: setPreviousNick * If user has nickname changed, set previous nickname. * * Parameters: * (String) previousNick - the previous nickname */ - this.setPreviousNick = function(previousNick) { - this.data.previousNick = previousNick; - }; - - /** Function: hasNicknameChanged + this.setPreviousNick = function(previousNick) { + this.data.previousNick = previousNick; + }; + /** Function: hasNicknameChanged * Gets the previous nickname if available. * * Returns: * (String) - previous nickname */ - this.getPreviousNick = function() { - return this.data.previousNick; - }; + this.getPreviousNick = function() { + return this.data.previousNick; + }; }; /** File: event.js @@ -1955,10 +1827,9 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy, Strophe, jQuery */ - /** Class: Candy.Core.Event * Chat Events * @@ -1967,8 +1838,8 @@ Candy.Core.ChatUser = function(jid, nick, affiliation, role) { * (Strophe) Strophe - Strophe * (jQuery) $ - jQuery */ -Candy.Core.Event = (function(self, Strophe, $) { - /** Function: Login +Candy.Core.Event = function(self, Strophe, $) { + /** Function: Login * Notify view that the login window should be displayed * * Parameters: @@ -1977,21 +1848,22 @@ Candy.Core.Event = (function(self, Strophe, $) { * Triggers: * candy:core.login using {presetJid} */ - self.Login = function(presetJid) { - /** Event: candy:core.login + self.Login = function(presetJid) { + /** Event: candy:core.login * Triggered when the login window should be displayed * * Parameters: * (String) presetJid - Preset user JID */ - $(Candy).triggerHandler('candy:core.login', { presetJid: presetJid } ); - }; - - /** Class: Candy.Core.Event.Strophe + $(Candy).triggerHandler("candy:core.login", { + presetJid: presetJid + }); + }; + /** Class: Candy.Core.Event.Strophe * Strophe-related events */ - self.Strophe = { - /** Function: Connect + self.Strophe = { + /** Function: Connect * Acts on strophe status events and notifies view. * * Parameters: @@ -2000,64 +1872,66 @@ Candy.Core.Event = (function(self, Strophe, $) { * Triggers: * candy:core.chat.connection using {status} */ - Connect: function(status) { - Candy.Core.setStropheStatus(status); - switch(status) { - case Strophe.Status.CONNECTED: - Candy.Core.log('[Connection] Connected'); - Candy.Core.Action.Jabber.GetJidIfAnonymous(); - /* falls through */ - case Strophe.Status.ATTACHED: - Candy.Core.log('[Connection] Attached'); - Candy.Core.Action.Jabber.Presence(); - Candy.Core.Action.Jabber.Autojoin(); - Candy.Core.Action.Jabber.GetIgnoreList(); - break; - - case Strophe.Status.DISCONNECTED: - Candy.Core.log('[Connection] Disconnected'); - break; - - case Strophe.Status.AUTHFAIL: - Candy.Core.log('[Connection] Authentication failed'); - break; - - case Strophe.Status.CONNECTING: - Candy.Core.log('[Connection] Connecting'); - break; - - case Strophe.Status.DISCONNECTING: - Candy.Core.log('[Connection] Disconnecting'); - break; - - case Strophe.Status.AUTHENTICATING: - Candy.Core.log('[Connection] Authenticating'); - break; - - case Strophe.Status.ERROR: - case Strophe.Status.CONNFAIL: - Candy.Core.log('[Connection] Failed (' + status + ')'); - break; - - default: - Candy.Core.log('[Connection] What?!'); - break; - } - /** Event: candy:core.chat.connection + Connect: function(status) { + Candy.Core.setStropheStatus(status); + switch (status) { + case Strophe.Status.CONNECTED: + Candy.Core.log("[Connection] Connected"); + Candy.Core.Action.Jabber.GetJidIfAnonymous(); + + /* falls through */ + case Strophe.Status.ATTACHED: + Candy.Core.log("[Connection] Attached"); + Candy.Core.Action.Jabber.Presence(); + Candy.Core.Action.Jabber.Autojoin(); + Candy.Core.Action.Jabber.GetIgnoreList(); + break; + + case Strophe.Status.DISCONNECTED: + Candy.Core.log("[Connection] Disconnected"); + break; + + case Strophe.Status.AUTHFAIL: + Candy.Core.log("[Connection] Authentication failed"); + break; + + case Strophe.Status.CONNECTING: + Candy.Core.log("[Connection] Connecting"); + break; + + case Strophe.Status.DISCONNECTING: + Candy.Core.log("[Connection] Disconnecting"); + break; + + case Strophe.Status.AUTHENTICATING: + Candy.Core.log("[Connection] Authenticating"); + break; + + case Strophe.Status.ERROR: + case Strophe.Status.CONNFAIL: + Candy.Core.log("[Connection] Failed (" + status + ")"); + break; + + default: + Candy.Core.log("[Connection] What?!"); + break; + } + /** Event: candy:core.chat.connection * Connection status updates * * Parameters: * (Strophe.Status) status - Strophe status */ - $(Candy).triggerHandler('candy:core.chat.connection', { status: status } ); - } - }; - - /** Class: Candy.Core.Event.Jabber + $(Candy).triggerHandler("candy:core.chat.connection", { + status: status + }); + } + }; + /** Class: Candy.Core.Event.Jabber * Jabber related events */ - self.Jabber = { - /** Function: Version + self.Jabber = { + /** Function: Version * Responds to a version request * * Parameters: @@ -2066,13 +1940,12 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Version: function(msg) { - Candy.Core.log('[Jabber] Version'); - Candy.Core.Action.Jabber.Version($(msg)); - return true; - }, - - /** Function: Presence + Version: function(msg) { + Candy.Core.log("[Jabber] Version"); + Candy.Core.Action.Jabber.Version($(msg)); + return true; + }, + /** Function: Presence * Acts on a presence event * * Parameters: @@ -2084,29 +1957,31 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Presence: function(msg) { - Candy.Core.log('[Jabber] Presence'); - msg = $(msg); - if(msg.children('x[xmlns^="' + Strophe.NS.MUC + '"]').length > 0) { - if (msg.attr('type') === 'error') { - self.Jabber.Room.PresenceError(msg); - } else { - self.Jabber.Room.Presence(msg); - } - } else { - /** Event: candy:core.presence + Presence: function(msg) { + Candy.Core.log("[Jabber] Presence"); + msg = $(msg); + if (msg.children('x[xmlns^="' + Strophe.NS.MUC + '"]').length > 0) { + if (msg.attr("type") === "error") { + self.Jabber.Room.PresenceError(msg); + } else { + self.Jabber.Room.Presence(msg); + } + } else { + /** Event: candy:core.presence * Presence updates. Emitted only when not a muc presence. * * Parameters: * (JID) from - From Jid * (String) stanza - Stanza */ - $(Candy).triggerHandler('candy:core.presence', {'from': msg.attr('from'), 'stanza': msg}); - } - return true; - }, - - /** Function: Bookmarks + $(Candy).triggerHandler("candy:core.presence", { + from: msg.attr("from"), + stanza: msg + }); + } + return true; + }, + /** Function: Bookmarks * Acts on a bookmarks event. When a bookmark has the attribute autojoin set, joins this room. * * Parameters: @@ -2115,19 +1990,18 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Bookmarks: function(msg) { - Candy.Core.log('[Jabber] Bookmarks'); - // Autojoin bookmarks (Openfire) - $('conference', msg).each(function() { - var item = $(this); - if(item.attr('autojoin')) { - Candy.Core.Action.Jabber.Room.Join(item.attr('jid')); - } - }); - return true; - }, - - /** Function: PrivacyList + Bookmarks: function(msg) { + Candy.Core.log("[Jabber] Bookmarks"); + // Autojoin bookmarks (Openfire) + $("conference", msg).each(function() { + var item = $(this); + if (item.attr("autojoin")) { + Candy.Core.Action.Jabber.Room.Join(item.attr("jid")); + } + }); + return true; + }, + /** Function: PrivacyList * Acts on a privacy list event and sets up the current privacy list of this user. * * If no privacy list has been added yet, create the privacy list and listen again to this event. @@ -2138,24 +2012,23 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - false to disable the handler after first call. */ - PrivacyList: function(msg) { - Candy.Core.log('[Jabber] PrivacyList'); - var currentUser = Candy.Core.getUser(); - msg = $(msg); - if(msg.attr('type') === 'result') { - $('list[name="ignore"] item', msg).each(function() { - var item = $(this); - if (item.attr('action') === 'deny') { - currentUser.addToOrRemoveFromPrivacyList('ignore', item.attr('value')); - } - }); - Candy.Core.Action.Jabber.SetIgnoreListActive(); - return false; - } - return self.Jabber.PrivacyListError(msg); - }, - - /** Function: PrivacyListError + PrivacyList: function(msg) { + Candy.Core.log("[Jabber] PrivacyList"); + var currentUser = Candy.Core.getUser(); + msg = $(msg); + if (msg.attr("type") === "result") { + $('list[name="ignore"] item', msg).each(function() { + var item = $(this); + if (item.attr("action") === "deny") { + currentUser.addToOrRemoveFromPrivacyList("ignore", item.attr("value")); + } + }); + Candy.Core.Action.Jabber.SetIgnoreListActive(); + return false; + } + return self.Jabber.PrivacyListError(msg); + }, + /** Function: PrivacyListError * Acts when a privacy list error has been received. * * Currently only handles the case, when a privacy list doesn't exist yet and creates one. @@ -2166,17 +2039,16 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - false to disable the handler after first call. */ - PrivacyListError: function(msg) { - Candy.Core.log('[Jabber] PrivacyListError'); - // check if msg says that privacyList doesn't exist - if ($('error[code="404"][type="cancel"] item-not-found', msg)) { - Candy.Core.Action.Jabber.ResetIgnoreList(); - Candy.Core.Action.Jabber.SetIgnoreListActive(); - } - return false; - }, - - /** Function: Message + PrivacyListError: function(msg) { + Candy.Core.log("[Jabber] PrivacyListError"); + // check if msg says that privacyList doesn't exist + if ($('error[code="404"][type="cancel"] item-not-found', msg)) { + Candy.Core.Action.Jabber.ResetIgnoreList(); + Candy.Core.Action.Jabber.SetIgnoreListActive(); + } + return false; + }, + /** Function: Message * Acts on room, admin and server messages and notifies the view if required. * * Parameters: @@ -2189,29 +2061,27 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Message: function(msg) { - Candy.Core.log('[Jabber] Message'); - msg = $(msg); - - var fromJid = msg.attr('from'), - type = msg.attr('type'), - toJid = msg.attr('to'); - // Room message - if(fromJid !== Strophe.getDomainFromJid(fromJid) && (type === 'groupchat' || type === 'chat' || type === 'error' || type === 'normal')) { - self.Jabber.Room.Message(msg); - // Admin message - } else if(!toJid && fromJid === Strophe.getDomainFromJid(fromJid)) { - /** Event: candy:core.chat.message.admin + Message: function(msg) { + Candy.Core.log("[Jabber] Message"); + msg = $(msg); + var fromJid = msg.attr("from"), type = msg.attr("type"), toJid = msg.attr("to"); + // Room message + if (fromJid !== Strophe.getDomainFromJid(fromJid) && (type === "groupchat" || type === "chat" || type === "error" || type === "normal")) { + self.Jabber.Room.Message(msg); + } else if (!toJid && fromJid === Strophe.getDomainFromJid(fromJid)) { + /** Event: candy:core.chat.message.admin * Admin message * * Parameters: * (String) type - Type of the message [default: message] * (String) message - Message text */ - $(Candy).triggerHandler('candy:core.chat.message.admin', { type: (type || 'message'), message: msg.children('body').text() }); - // Server Message - } else if(toJid && fromJid === Strophe.getDomainFromJid(fromJid)) { - /** Event: candy:core.chat.message.server + $(Candy).triggerHandler("candy:core.chat.message.admin", { + type: type || "message", + message: msg.children("body").text() + }); + } else if (toJid && fromJid === Strophe.getDomainFromJid(fromJid)) { + /** Event: candy:core.chat.message.server * Server message (e.g. subject) * * Parameters: @@ -2219,20 +2089,19 @@ Candy.Core.Event = (function(self, Strophe, $) { * (String) subject - Subject text * (String) message - Message text */ - $(Candy).triggerHandler('candy:core.chat.message.server', { - type: (type || 'message'), - subject: msg.children('subject').text(), - message: msg.children('body').text() - }); - } - return true; - }, - - /** Class: Candy.Core.Event.Jabber.Room + $(Candy).triggerHandler("candy:core.chat.message.server", { + type: type || "message", + subject: msg.children("subject").text(), + message: msg.children("body").text() + }); + } + return true; + }, + /** Class: Candy.Core.Event.Jabber.Room * Room specific events */ - Room: { - /** Function: Leave + Room: { + /** Function: Leave * Leaves a room and cleans up related data and notifies view. * * Parameters: @@ -2244,39 +2113,29 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Leave: function(msg) { - Candy.Core.log('[Jabber:Room] Leave'); - msg = $(msg); - var from = Candy.Util.unescapeJid(msg.attr('from')), - roomJid = Strophe.getBareJidFromJid(from); - - // if room is not joined yet, ignore. - if (!Candy.Core.getRoom(roomJid)) { - return true; - } - - var roomName = Candy.Core.getRoom(roomJid).getName(), - item = msg.find('item'), - type = 'leave', - reason, - actor; - - delete Candy.Core.getRooms()[roomJid]; - // if user gets kicked, role is none and there's a status code 307 - if(item.attr('role') === 'none') { - var code = msg.find('status').attr('code'); - if(code === '307') { - type = 'kick'; - } else if(code === '301') { - type = 'ban'; - } - reason = item.find('reason').text(); - actor = item.find('actor').attr('jid'); - } - - var user = new Candy.Core.ChatUser(from, Strophe.getResourceFromJid(from), item.attr('affiliation'), item.attr('role')); - - /** Event: candy:core.presence.leave + Leave: function(msg) { + Candy.Core.log("[Jabber:Room] Leave"); + msg = $(msg); + var from = Candy.Util.unescapeJid(msg.attr("from")), roomJid = Strophe.getBareJidFromJid(from); + // if room is not joined yet, ignore. + if (!Candy.Core.getRoom(roomJid)) { + return true; + } + var roomName = Candy.Core.getRoom(roomJid).getName(), item = msg.find("item"), type = "leave", reason, actor; + delete Candy.Core.getRooms()[roomJid]; + // if user gets kicked, role is none and there's a status code 307 + if (item.attr("role") === "none") { + var code = msg.find("status").attr("code"); + if (code === "307") { + type = "kick"; + } else if (code === "301") { + type = "ban"; + } + reason = item.find("reason").text(); + actor = item.find("actor").attr("jid"); + } + var user = new Candy.Core.ChatUser(from, Strophe.getResourceFromJid(from), item.attr("affiliation"), item.attr("role")); + /** Event: candy:core.presence.leave * When the local client leaves a room * * Also triggered when the local client gets kicked or banned from a room. @@ -2289,18 +2148,17 @@ Candy.Core.Event = (function(self, Strophe, $) { * (String) actor - When type equals kick|ban, this is the moderator which did the kick * (Candy.Core.ChatUser) user - user which leaves the room */ - $(Candy).triggerHandler('candy:core.presence.leave', { - 'roomJid': roomJid, - 'roomName': roomName, - 'type': type, - 'reason': reason, - 'actor': actor, - 'user': user - }); - return true; - }, - - /** Function: Disco + $(Candy).triggerHandler("candy:core.presence.leave", { + roomJid: roomJid, + roomName: roomName, + type: type, + reason: reason, + actor: actor, + user: user + }); + return true; + }, + /** Function: Disco * Sets informations to rooms according to the disco info received. * * Parameters: @@ -2309,31 +2167,25 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Disco: function(msg) { - Candy.Core.log('[Jabber:Room] Disco'); - msg = $(msg); - var roomJid = Strophe.getBareJidFromJid(Candy.Util.unescapeJid(msg.attr('from'))); - - // Client joined a room - if(!Candy.Core.getRooms()[roomJid]) { - Candy.Core.getRooms()[roomJid] = new Candy.Core.ChatRoom(roomJid); - } - // Room existed but room name was unknown - var identity = msg.find('identity'); - if(identity.length) { - var roomName = identity.attr('name'), - room = Candy.Core.getRoom(roomJid); - if(room.getName() === null) { - room.setName(Strophe.unescapeNode(roomName)); - // Room name changed - }/*else if(room.getName() !== roomName && room.getUser() !== null) { - // NOTE: We want to notify the View here but jabber doesn't send anything when the room name changes :-( - }*/ - } - return true; - }, - - /** Function: Presence + Disco: function(msg) { + Candy.Core.log("[Jabber:Room] Disco"); + msg = $(msg); + var roomJid = Strophe.getBareJidFromJid(Candy.Util.unescapeJid(msg.attr("from"))); + // Client joined a room + if (!Candy.Core.getRooms()[roomJid]) { + Candy.Core.getRooms()[roomJid] = new Candy.Core.ChatRoom(roomJid); + } + // Room existed but room name was unknown + var identity = msg.find("identity"); + if (identity.length) { + var roomName = identity.attr("name"), room = Candy.Core.getRoom(roomJid); + if (room.getName() === null) { + room.setName(Strophe.unescapeNode(roomName)); + } + } + return true; + }, + /** Function: Presence * Acts on various presence messages (room leaving, room joining, error presence) and notifies view. * * Parameters: @@ -2345,85 +2197,71 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Presence: function(msg) { - Candy.Core.log('[Jabber:Room] Presence'); - var from = Candy.Util.unescapeJid(msg.attr('from')), - roomJid = Strophe.getBareJidFromJid(from), - presenceType = msg.attr('type'), - status = msg.find('status'), - nickAssign = false, - nickChange = false; - - if(status.length) { - // check if status code indicates a nick assignment or nick change - for(var i = 0, l = status.length; i < l; i++) { - var $status = $(status[i]), - code = $status.attr('code'); - if(code === '303') { - nickChange = true; - } else if(code === '210') { - nickAssign = true; - } - } - } - - // Current User joined a room - var room = Candy.Core.getRoom(roomJid); - if(!room) { - Candy.Core.getRooms()[roomJid] = new Candy.Core.ChatRoom(roomJid); - room = Candy.Core.getRoom(roomJid); - } - - // Current User left a room - var currentUser = room.getUser() ? room.getUser() : Candy.Core.getUser(); - if(Strophe.getResourceFromJid(from) === currentUser.getNick() && presenceType === 'unavailable' && nickChange === false) { - self.Jabber.Room.Leave(msg); - return true; - } - - var roster = room.getRoster(), - action, user, - nick, - item = msg.find('item'); - // User joined a room - if(presenceType !== 'unavailable') { - if (roster.get(from)) { - // user changed nick before - return true; - } - nick = Strophe.getResourceFromJid(from); - user = new Candy.Core.ChatUser(from, nick, item.attr('affiliation'), item.attr('role')); - // Room existed but client (myself) is not yet registered - if(room.getUser() === null && (Candy.Core.getUser().getNick() === nick || nickAssign)) { - room.setUser(user); - currentUser = user; - } - roster.add(user); - action = 'join'; - // User left a room - } else { - user = roster.get(from); - roster.remove(from); - if(nickChange) { - // user changed nick - nick = item.attr('nick'); - action = 'nickchange'; - user.setPreviousNick(user.getNick()); - user.setNick(nick); - user.setJid(Strophe.getBareJidFromJid(from) + '/' + nick); - roster.add(user); - } else { - action = 'leave'; - if(item.attr('role') === 'none') { - if(msg.find('status').attr('code') === '307') { - action = 'kick'; - } else if(msg.find('status').attr('code') === '301') { - action = 'ban'; - } - } - } - } - /** Event: candy:core.presence.room + Presence: function(msg) { + Candy.Core.log("[Jabber:Room] Presence"); + var from = Candy.Util.unescapeJid(msg.attr("from")), roomJid = Strophe.getBareJidFromJid(from), presenceType = msg.attr("type"), status = msg.find("status"), nickAssign = false, nickChange = false; + if (status.length) { + // check if status code indicates a nick assignment or nick change + for (var i = 0, l = status.length; i < l; i++) { + var $status = $(status[i]), code = $status.attr("code"); + if (code === "303") { + nickChange = true; + } else if (code === "210") { + nickAssign = true; + } + } + } + // Current User joined a room + var room = Candy.Core.getRoom(roomJid); + if (!room) { + Candy.Core.getRooms()[roomJid] = new Candy.Core.ChatRoom(roomJid); + room = Candy.Core.getRoom(roomJid); + } + // Current User left a room + var currentUser = room.getUser() ? room.getUser() : Candy.Core.getUser(); + if (Strophe.getResourceFromJid(from) === currentUser.getNick() && presenceType === "unavailable" && nickChange === false) { + self.Jabber.Room.Leave(msg); + return true; + } + var roster = room.getRoster(), action, user, nick, item = msg.find("item"); + // User joined a room + if (presenceType !== "unavailable") { + if (roster.get(from)) { + // user changed nick before + return true; + } + nick = Strophe.getResourceFromJid(from); + user = new Candy.Core.ChatUser(from, nick, item.attr("affiliation"), item.attr("role")); + // Room existed but client (myself) is not yet registered + if (room.getUser() === null && (Candy.Core.getUser().getNick() === nick || nickAssign)) { + room.setUser(user); + currentUser = user; + } + roster.add(user); + action = "join"; + } else { + user = roster.get(from); + roster.remove(from); + if (nickChange) { + // user changed nick + nick = item.attr("nick"); + action = "nickchange"; + user.setPreviousNick(user.getNick()); + user.setNick(nick); + user.setJid(Strophe.getBareJidFromJid(from) + "/" + nick); + roster.add(user); + } else { + action = "leave"; + if (item.attr("role") === "none") { + if (msg.find("status").attr("code") === "307") { + action = "kick"; + } else if (msg.find("status").attr("code") === "301") { + action = "ban"; + } + } + } + } + /** Event: candy:core.presence.room * Room presence updates * * Parameters: @@ -2433,17 +2271,16 @@ Candy.Core.Event = (function(self, Strophe, $) { * (String) action - Action [kick, ban, leave, join] * (Candy.Core.ChatUser) currentUser - Current local user */ - $(Candy).triggerHandler('candy:core.presence.room', { - 'roomJid': roomJid, - 'roomName': room.getName(), - 'user': user, - 'action': action, - 'currentUser': currentUser - }); - return true; - }, - - /** Function: PresenceError + $(Candy).triggerHandler("candy:core.presence.room", { + roomJid: roomJid, + roomName: room.getName(), + user: user, + action: action, + currentUser: currentUser + }); + return true; + }, + /** Function: PresenceError * Acts when a presence of type error has been retrieved. * * Parameters: @@ -2455,18 +2292,13 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - PresenceError: function(msg) { - Candy.Core.log('[Jabber:Room] Presence Error'); - var from = Candy.Util.unescapeJid(msg.attr('from')), - roomJid = Strophe.getBareJidFromJid(from), - room = Candy.Core.getRooms()[roomJid], - roomName = room.getName(); - - // Presence error: Remove room from array to prevent error when disconnecting - Candy.Core.removeRoom(roomJid); - room = undefined; - - /** Event: candy:core.presence.error + PresenceError: function(msg) { + Candy.Core.log("[Jabber:Room] Presence Error"); + var from = Candy.Util.unescapeJid(msg.attr("from")), roomJid = Strophe.getBareJidFromJid(from), room = Candy.Core.getRooms()[roomJid], roomName = room.getName(); + // Presence error: Remove room from array to prevent error when disconnecting + Candy.Core.removeRoom(roomJid); + room = undefined; + /** Event: candy:core.presence.error * Triggered when a presence error happened * * Parameters: @@ -2475,16 +2307,15 @@ Candy.Core.Event = (function(self, Strophe, $) { * (String) roomJid - Room jid * (String) roomName - Room name */ - $(Candy).triggerHandler('candy:core.presence.error', { - 'msg' : msg, - 'type': msg.children('error').children()[0].tagName.toLowerCase(), - 'roomJid': roomJid, - 'roomName': roomName - }); - return true; - }, - - /** Function: Message + $(Candy).triggerHandler("candy:core.presence.error", { + msg: msg, + type: msg.children("error").children()[0].tagName.toLowerCase(), + roomJid: roomJid, + roomName: roomName + }); + return true; + }, + /** Function: Message * Acts on various message events (subject changed, private chat message, multi-user chat message) * and notifies view. * @@ -2497,58 +2328,68 @@ Candy.Core.Event = (function(self, Strophe, $) { * Returns: * (Boolean) - true */ - Message: function(msg) { - Candy.Core.log('[Jabber:Room] Message'); - // Room subject - var roomJid, message; - if(msg.children('subject').length > 0) { - roomJid = Candy.Util.unescapeJid(Strophe.getBareJidFromJid(msg.attr('from'))); - message = { name: Strophe.getNodeFromJid(roomJid), body: msg.children('subject').text(), type: 'subject' }; - // Error messsage - } else if(msg.attr('type') === 'error') { - var error = msg.children('error'); - if(error.children('text').length > 0) { - roomJid = msg.attr('from'); - message = { type: 'info', body: error.children('text').text() }; - } - // Chat message - } else if(msg.children('body').length > 0) { - // Private chat message - if(msg.attr('type') === 'chat' || msg.attr('type') === 'normal') { - roomJid = Candy.Util.unescapeJid(msg.attr('from')); - var bareRoomJid = Strophe.getBareJidFromJid(roomJid), - // if a 3rd-party client sends a direct message to this user (not via the room) then the username is the node and not the resource. - isNoConferenceRoomJid = !Candy.Core.getRoom(bareRoomJid), - name = isNoConferenceRoomJid ? Strophe.getNodeFromJid(roomJid) : Strophe.getResourceFromJid(roomJid); - message = { name: name, body: msg.children('body').text(), type: msg.attr('type'), isNoConferenceRoomJid: isNoConferenceRoomJid }; - // Multi-user chat message - } else { - roomJid = Candy.Util.unescapeJid(Strophe.getBareJidFromJid(msg.attr('from'))); - var resource = Strophe.getResourceFromJid(msg.attr('from')); - // Message from a user - if(resource) { - resource = Strophe.unescapeNode(resource); - message = { name: resource, body: msg.children('body').text(), type: msg.attr('type') }; - // Message from server (XEP-0045#registrar-statuscodes) - } else { - // we are not yet present in the room, let's just drop this message (issue #105) - if(!Candy.View.Pane.Chat.rooms[msg.attr('from')]) { - return true; - } - message = { name: '', body: msg.children('body').text(), type: 'info' }; - } - } - // Unhandled message - } else { - return true; - } - - // besides the delayed delivery (XEP-0203), there exists also XEP-0091 which is the legacy delayed delivery. - // the x[xmlns=jabber:x:delay] is the format in XEP-0091. - var delay = msg.children('delay') ? msg.children('delay') : msg.children('x[xmlns="' + Strophe.NS.DELAY +'"]'), - timestamp = delay !== undefined ? delay.attr('stamp') : null; - - /** Event: candy:core.message + Message: function(msg) { + Candy.Core.log("[Jabber:Room] Message"); + // Room subject + var roomJid, message; + if (msg.children("subject").length > 0) { + roomJid = Candy.Util.unescapeJid(Strophe.getBareJidFromJid(msg.attr("from"))); + message = { + name: Strophe.getNodeFromJid(roomJid), + body: msg.children("subject").text(), + type: "subject" + }; + } else if (msg.attr("type") === "error") { + var error = msg.children("error"); + if (error.children("text").length > 0) { + roomJid = msg.attr("from"); + message = { + type: "info", + body: error.children("text").text() + }; + } + } else if (msg.children("body").length > 0) { + // Private chat message + if (msg.attr("type") === "chat" || msg.attr("type") === "normal") { + roomJid = Candy.Util.unescapeJid(msg.attr("from")); + var bareRoomJid = Strophe.getBareJidFromJid(roomJid), // if a 3rd-party client sends a direct message to this user (not via the room) then the username is the node and not the resource. + isNoConferenceRoomJid = !Candy.Core.getRoom(bareRoomJid), name = isNoConferenceRoomJid ? Strophe.getNodeFromJid(roomJid) : Strophe.getResourceFromJid(roomJid); + message = { + name: name, + body: msg.children("body").text(), + type: msg.attr("type"), + isNoConferenceRoomJid: isNoConferenceRoomJid + }; + } else { + roomJid = Candy.Util.unescapeJid(Strophe.getBareJidFromJid(msg.attr("from"))); + var resource = Strophe.getResourceFromJid(msg.attr("from")); + // Message from a user + if (resource) { + resource = Strophe.unescapeNode(resource); + message = { + name: resource, + body: msg.children("body").text(), + type: msg.attr("type") + }; + } else { + // we are not yet present in the room, let's just drop this message (issue #105) + if (!Candy.View.Pane.Chat.rooms[msg.attr("from")]) { + return true; + } + message = { + name: "", + body: msg.children("body").text(), + type: "info" + }; + } + } + } else { + return true; + } + // besides the delayed delivery (XEP-0203), there exists also XEP-0091 which is the legacy delayed delivery. + // the x[xmlns=jabber:x:delay] is the format in XEP-0091. + var delay = msg.children("delay") ? msg.children("delay") : msg.children('x[xmlns="' + Strophe.NS.DELAY + '"]'), timestamp = delay !== undefined ? delay.attr("stamp") : null; + /** Event: candy:core.message * Triggers on various message events (subject changed, private chat message, multi-user chat message). * * The resulting message object can contain different key-value pairs as stated in the documentation @@ -2579,18 +2420,17 @@ Candy.Core.Event = (function(self, Strophe, $) { * TODO: * Streamline those events sent and rename the parameters. */ - $(Candy).triggerHandler('candy:core.message', { - roomJid: roomJid, - message: message, - timestamp: timestamp - }); - return true; - } - } - }; - - return self; -}(Candy.Core.Event || {}, Strophe, jQuery)); + $(Candy).triggerHandler("candy:core.message", { + roomJid: roomJid, + message: message, + timestamp: timestamp + }); + return true; + } + } + }; + return self; +}(Candy.Core.Event || {}, Strophe, jQuery); /** File: observer.js * Candy - Chats are not dead yet. @@ -2603,10 +2443,9 @@ Candy.Core.Event = (function(self, Strophe, $) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel */ -'use strict'; +"use strict"; /* global Candy, Strophe, Mustache, jQuery */ - /** Class: Candy.View.Observer * Observes Candy core events * @@ -2614,18 +2453,17 @@ Candy.Core.Event = (function(self, Strophe, $) { * (Candy.View.Observer) self - itself * (jQuery) $ - jQuery */ -Candy.View.Observer = (function(self, $) { - /** PrivateVariable: _showConnectedMessageModal +Candy.View.Observer = function(self, $) { + /** PrivateVariable: _showConnectedMessageModal * Ugly way to determine if the 'connected' modal should be shown. * Is set to false in case no autojoin param is set. */ - var _showConnectedMessageModal = true; - - /** Class: Candy.View.Observer.Chat + var _showConnectedMessageModal = true; + /** Class: Candy.View.Observer.Chat * Chat events */ - self.Chat = { - /** Function: Connection + self.Chat = { + /** Function: Connection * The update method gets called whenever an event to which "Chat" is subscribed. * * Currently listens for connection status updates @@ -2634,9 +2472,9 @@ Candy.View.Observer = (function(self, $) { * (jQuery.Event) event - jQuery Event object * (Object) args - {status (Strophe.Status.*)} */ - Connection: function(event, args) { - var eventName = 'candy:view.connection.status-' + args.status; - /** Event: candy:view.connection.status- + Connection: function(event, args) { + var eventName = "candy:view.connection.status-" + args.status; + /** Event: candy:view.connection.status- * Using this event, you can alter the default Candy (View) behaviour when reacting * to connection updates. * @@ -2672,66 +2510,64 @@ Candy.View.Observer = (function(self, $) { * }); * (end code) */ - if($(Candy).triggerHandler(eventName) === false) { - return false; - } - - switch(args.status) { - case Strophe.Status.CONNECTING: - case Strophe.Status.AUTHENTICATING: - Candy.View.Pane.Chat.Modal.show($.i18n._('statusConnecting'), false, true); - break; - case Strophe.Status.ATTACHED: - case Strophe.Status.CONNECTED: - if(_showConnectedMessageModal === true) { - // only show 'connected' if the autojoin error is not shown - // which is determined by having a visible modal in this stage. - Candy.View.Pane.Chat.Modal.show($.i18n._('statusConnected')); - Candy.View.Pane.Chat.Modal.hide(); - } - break; - - case Strophe.Status.DISCONNECTING: - Candy.View.Pane.Chat.Modal.show($.i18n._('statusDisconnecting'), false, true); - break; - - case Strophe.Status.DISCONNECTED: - var presetJid = Candy.Core.isAnonymousConnection() ? Strophe.getDomainFromJid(Candy.Core.getUser().getJid()) : null; - Candy.View.Pane.Chat.Modal.showLoginForm($.i18n._('statusDisconnected'), presetJid); - break; - - case Strophe.Status.AUTHFAIL: - Candy.View.Pane.Chat.Modal.showLoginForm($.i18n._('statusAuthfail')); - break; - - default: - Candy.View.Pane.Chat.Modal.show($.i18n._('status', args.status)); - break; - } - }, - - /** Function: Message + if ($(Candy).triggerHandler(eventName) === false) { + return false; + } + switch (args.status) { + case Strophe.Status.CONNECTING: + case Strophe.Status.AUTHENTICATING: + Candy.View.Pane.Chat.Modal.show($.i18n._("statusConnecting"), false, true); + break; + + case Strophe.Status.ATTACHED: + case Strophe.Status.CONNECTED: + if (_showConnectedMessageModal === true) { + // only show 'connected' if the autojoin error is not shown + // which is determined by having a visible modal in this stage. + Candy.View.Pane.Chat.Modal.show($.i18n._("statusConnected")); + Candy.View.Pane.Chat.Modal.hide(); + } + break; + + case Strophe.Status.DISCONNECTING: + Candy.View.Pane.Chat.Modal.show($.i18n._("statusDisconnecting"), false, true); + break; + + case Strophe.Status.DISCONNECTED: + var presetJid = Candy.Core.isAnonymousConnection() ? Strophe.getDomainFromJid(Candy.Core.getUser().getJid()) : null; + Candy.View.Pane.Chat.Modal.showLoginForm($.i18n._("statusDisconnected"), presetJid); + break; + + case Strophe.Status.AUTHFAIL: + Candy.View.Pane.Chat.Modal.showLoginForm($.i18n._("statusAuthfail")); + break; + + default: + Candy.View.Pane.Chat.Modal.show($.i18n._("status", args.status)); + break; + } + }, + /** Function: Message * Dispatches admin and info messages * * Parameters: * (jQuery.Event) event - jQuery Event object * (Object) args - {type (message/chat/groupchat), subject (if type = message), message} */ - Message: function(event, args) { - if(args.type === 'message') { - Candy.View.Pane.Chat.adminMessage((args.subject || ''), args.message); - } else if(args.type === 'chat' || args.type === 'groupchat') { - // use onInfoMessage as infos from the server shouldn't be hidden by the infoMessage switch. - Candy.View.Pane.Chat.onInfoMessage(Candy.View.getCurrent().roomJid, (args.subject || ''), args.message); - } - } - }; - - /** Class: Candy.View.Observer.Presence + Message: function(event, args) { + if (args.type === "message") { + Candy.View.Pane.Chat.adminMessage(args.subject || "", args.message); + } else if (args.type === "chat" || args.type === "groupchat") { + // use onInfoMessage as infos from the server shouldn't be hidden by the infoMessage switch. + Candy.View.Pane.Chat.onInfoMessage(Candy.View.getCurrent().roomJid, args.subject || "", args.message); + } + } + }; + /** Class: Candy.View.Observer.Presence * Presence update events */ - self.Presence = { - /** Function: update + self.Presence = { + /** Function: update * Every presence update gets dispatched from this method. * * Parameters: @@ -2741,45 +2577,44 @@ Candy.View.Observer = (function(self, $) { * Uses: * - */ - update: function(event, args) { - // Client left - if(args.type === 'leave') { - var user = Candy.View.Pane.Room.getUser(args.roomJid); - Candy.View.Pane.Room.close(args.roomJid); - self.Presence.notifyPrivateChats(user, args.type); - // Client has been kicked or banned - } else if (args.type === 'kick' || args.type === 'ban') { - var actorName = args.actor ? Strophe.getNodeFromJid(args.actor) : null, - actionLabel, - translationParams = [args.roomName]; - - if (actorName) { - translationParams.push(actorName); - } - - switch(args.type) { - case 'kick': - actionLabel = $.i18n._((actorName ? 'youHaveBeenKickedBy' : 'youHaveBeenKicked'), translationParams); - break; - case 'ban': - actionLabel = $.i18n._((actorName ? 'youHaveBeenBannedBy' : 'youHaveBeenBanned'), translationParams); - break; - } - Candy.View.Pane.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.adminMessageReason, { - reason: args.reason, - _action: actionLabel, - _reason: $.i18n._('reasonWas', [args.reason]) - })); - setTimeout(function() { - Candy.View.Pane.Chat.Modal.hide(function() { - Candy.View.Pane.Room.close(args.roomJid); - self.Presence.notifyPrivateChats(args.user, args.type); - }); - }, 5000); - - var evtData = { type: args.type, reason: args.reason, roomJid: args.roomJid, user: args.user }; - - /** Event: candy:view.presence + update: function(event, args) { + // Client left + if (args.type === "leave") { + var user = Candy.View.Pane.Room.getUser(args.roomJid); + Candy.View.Pane.Room.close(args.roomJid); + self.Presence.notifyPrivateChats(user, args.type); + } else if (args.type === "kick" || args.type === "ban") { + var actorName = args.actor ? Strophe.getNodeFromJid(args.actor) : null, actionLabel, translationParams = [ args.roomName ]; + if (actorName) { + translationParams.push(actorName); + } + switch (args.type) { + case "kick": + actionLabel = $.i18n._(actorName ? "youHaveBeenKickedBy" : "youHaveBeenKicked", translationParams); + break; + + case "ban": + actionLabel = $.i18n._(actorName ? "youHaveBeenBannedBy" : "youHaveBeenBanned", translationParams); + break; + } + Candy.View.Pane.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.adminMessageReason, { + reason: args.reason, + _action: actionLabel, + _reason: $.i18n._("reasonWas", [ args.reason ]) + })); + setTimeout(function() { + Candy.View.Pane.Chat.Modal.hide(function() { + Candy.View.Pane.Room.close(args.roomJid); + self.Presence.notifyPrivateChats(args.user, args.type); + }); + }, 5e3); + var evtData = { + type: args.type, + reason: args.reason, + roomJid: args.roomJid, + user: args.user + }; + /** Event: candy:view.presence * Presence update when kicked or banned * * Parameters: @@ -2788,120 +2623,115 @@ Candy.View.Observer = (function(self, $) { * (String) roomJid - Room JID * (Candy.Core.ChatUser) user - User which has been kicked or banned */ - $(Candy).triggerHandler('candy:view.presence', [evtData]); - - // A user changed presence - } else if(args.roomJid) { - args.roomJid = Candy.Util.unescapeJid(args.roomJid); - // Initialize room if not yet existing - if(!Candy.View.Pane.Chat.rooms[args.roomJid]) { - Candy.View.Pane.Room.init(args.roomJid, args.roomName); - Candy.View.Pane.Room.show(args.roomJid); - } - Candy.View.Pane.Roster.update(args.roomJid, args.user, args.action, args.currentUser); - // Notify private user chats if existing, but not in case the action is nickchange - // -- this is because the nickchange presence already contains the new - // user jid - if(Candy.View.Pane.Chat.rooms[args.user.getJid()] && args.action !== 'nickchange') { - Candy.View.Pane.Roster.update(args.user.getJid(), args.user, args.action, args.currentUser); - Candy.View.Pane.PrivateRoom.setStatus(args.user.getJid(), args.action); - } - } - }, - - /** Function: notifyPrivateChats + $(Candy).triggerHandler("candy:view.presence", [ evtData ]); + } else if (args.roomJid) { + args.roomJid = Candy.Util.unescapeJid(args.roomJid); + // Initialize room if not yet existing + if (!Candy.View.Pane.Chat.rooms[args.roomJid]) { + Candy.View.Pane.Room.init(args.roomJid, args.roomName); + Candy.View.Pane.Room.show(args.roomJid); + } + Candy.View.Pane.Roster.update(args.roomJid, args.user, args.action, args.currentUser); + // Notify private user chats if existing, but not in case the action is nickchange + // -- this is because the nickchange presence already contains the new + // user jid + if (Candy.View.Pane.Chat.rooms[args.user.getJid()] && args.action !== "nickchange") { + Candy.View.Pane.Roster.update(args.user.getJid(), args.user, args.action, args.currentUser); + Candy.View.Pane.PrivateRoom.setStatus(args.user.getJid(), args.action); + } + } + }, + /** Function: notifyPrivateChats * Notify private user chats if existing * * Parameters: * (Candy.Core.ChatUser) user - User which has done the event * (String) type - Event type (leave, join, kick/ban) */ - notifyPrivateChats: function(user, type) { - Candy.Core.log('[View:Observer] notify Private Chats'); - var roomJid; - for(roomJid in Candy.View.Pane.Chat.rooms) { - if(Candy.View.Pane.Chat.rooms.hasOwnProperty(roomJid) && Candy.View.Pane.Room.getUser(roomJid) && user.getJid() === Candy.View.Pane.Room.getUser(roomJid).getJid()) { - Candy.View.Pane.Roster.update(roomJid, user, type, user); - Candy.View.Pane.PrivateRoom.setStatus(roomJid, type); - } - } - } - }; - - /** Function: Candy.View.Observer.PresenceError + notifyPrivateChats: function(user, type) { + Candy.Core.log("[View:Observer] notify Private Chats"); + var roomJid; + for (roomJid in Candy.View.Pane.Chat.rooms) { + if (Candy.View.Pane.Chat.rooms.hasOwnProperty(roomJid) && Candy.View.Pane.Room.getUser(roomJid) && user.getJid() === Candy.View.Pane.Room.getUser(roomJid).getJid()) { + Candy.View.Pane.Roster.update(roomJid, user, type, user); + Candy.View.Pane.PrivateRoom.setStatus(roomJid, type); + } + } + } + }; + /** Function: Candy.View.Observer.PresenceError * Presence errors get handled in this method * * Parameters: * (jQuery.Event) event - jQuery.Event object * (Object) args - {msg, type, roomJid, roomName} */ - self.PresenceError = function(obj, args) { - switch(args.type) { - case 'not-authorized': - var message; - if (args.msg.children('x').children('password').length > 0) { - message = $.i18n._('passwordEnteredInvalid', [args.roomName]); - } - Candy.View.Pane.Chat.Modal.showEnterPasswordForm(args.roomJid, args.roomName, message); - break; - case 'conflict': - Candy.View.Pane.Chat.Modal.showNicknameConflictForm(args.roomJid); - break; - case 'registration-required': - Candy.View.Pane.Chat.Modal.showError('errorMembersOnly', [args.roomName]); - break; - case 'service-unavailable': - Candy.View.Pane.Chat.Modal.showError('errorMaxOccupantsReached', [args.roomName]); - break; - } - }; - - /** Function: Candy.View.Observer.Message + self.PresenceError = function(obj, args) { + switch (args.type) { + case "not-authorized": + var message; + if (args.msg.children("x").children("password").length > 0) { + message = $.i18n._("passwordEnteredInvalid", [ args.roomName ]); + } + Candy.View.Pane.Chat.Modal.showEnterPasswordForm(args.roomJid, args.roomName, message); + break; + + case "conflict": + Candy.View.Pane.Chat.Modal.showNicknameConflictForm(args.roomJid); + break; + + case "registration-required": + Candy.View.Pane.Chat.Modal.showError("errorMembersOnly", [ args.roomName ]); + break; + + case "service-unavailable": + Candy.View.Pane.Chat.Modal.showError("errorMaxOccupantsReached", [ args.roomName ]); + break; + } + }; + /** Function: Candy.View.Observer.Message * Messages received get dispatched from this method. * * Parameters: * (jQuery.Event) event - jQuery Event object * (Object) args - {message, roomJid} */ - self.Message = function(event, args) { - if(args.message.type === 'subject') { - if (!Candy.View.Pane.Chat.rooms[args.roomJid]) { - Candy.View.Pane.Room.init(args.roomJid, args.message.name); - Candy.View.Pane.Room.show(args.roomJid); - } - Candy.View.Pane.Room.setSubject(args.roomJid, args.message.body); - } else if(args.message.type === 'info') { - Candy.View.Pane.Chat.infoMessage(args.roomJid, args.message.body); - } else { - // Initialize room if it's a message for a new private user chat - if(args.message.type === 'chat' && !Candy.View.Pane.Chat.rooms[args.roomJid]) { - Candy.View.Pane.PrivateRoom.open(args.roomJid, args.message.name, false, args.message.isNoConferenceRoomJid); - } - Candy.View.Pane.Message.show(args.roomJid, args.message.name, args.message.body, args.timestamp); - } - }; - - /** Function: Candy.View.Observer.Login + self.Message = function(event, args) { + if (args.message.type === "subject") { + if (!Candy.View.Pane.Chat.rooms[args.roomJid]) { + Candy.View.Pane.Room.init(args.roomJid, args.message.name); + Candy.View.Pane.Room.show(args.roomJid); + } + Candy.View.Pane.Room.setSubject(args.roomJid, args.message.body); + } else if (args.message.type === "info") { + Candy.View.Pane.Chat.infoMessage(args.roomJid, args.message.body); + } else { + // Initialize room if it's a message for a new private user chat + if (args.message.type === "chat" && !Candy.View.Pane.Chat.rooms[args.roomJid]) { + Candy.View.Pane.PrivateRoom.open(args.roomJid, args.message.name, false, args.message.isNoConferenceRoomJid); + } + Candy.View.Pane.Message.show(args.roomJid, args.message.name, args.message.body, args.timestamp); + } + }; + /** Function: Candy.View.Observer.Login * The login event gets dispatched to this method * * Parameters: * (jQuery.Event) event - jQuery Event object * (Object) args - {presetJid} */ - self.Login = function(event, args) { - Candy.View.Pane.Chat.Modal.showLoginForm(null, args.presetJid); - }; - - /** Class: Candy.View.Observer.AutojoinMissing + self.Login = function(event, args) { + Candy.View.Pane.Chat.Modal.showLoginForm(null, args.presetJid); + }; + /** Class: Candy.View.Observer.AutojoinMissing * Displays an error about missing autojoin information */ - self.AutojoinMissing = function() { - _showConnectedMessageModal = false; - Candy.View.Pane.Chat.Modal.showError('errorAutojoinMissing'); - }; - - return self; -}(Candy.View.Observer || {}, jQuery)); + self.AutojoinMissing = function() { + _showConnectedMessageModal = false; + Candy.View.Pane.Chat.Modal.showError("errorAutojoinMissing"); + }; + return self; +}(Candy.View.Observer || {}, jQuery); /** File: pane.js * Candy - Chats are not dead yet. @@ -2914,10 +2744,9 @@ Candy.View.Observer = (function(self, $) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy, document, Mustache, Strophe, Audio, jQuery */ - /** Class: Candy.View.Pane * Candy view pane handles everything regarding DOM updates etc. * @@ -2925,109 +2754,98 @@ Candy.View.Observer = (function(self, $) { * (Candy.View.Pane) self - itself * (jQuery) $ - jQuery */ -Candy.View.Pane = (function(self, $) { - - /** Class: Candy.View.Pane.Window +Candy.View.Pane = function(self, $) { + /** Class: Candy.View.Pane.Window * Window related view updates */ - self.Window = { - /** PrivateVariable: _hasFocus + self.Window = { + /** PrivateVariable: _hasFocus * Window has focus */ - _hasFocus: true, - /** PrivateVariable: _plainTitle + _hasFocus: true, + /** PrivateVariable: _plainTitle * Document title */ - _plainTitle: document.title, - /** PrivateVariable: _unreadMessagesCount + _plainTitle: document.title, + /** PrivateVariable: _unreadMessagesCount * Unread messages count */ - _unreadMessagesCount: 0, - - /** Variable: autoscroll + _unreadMessagesCount: 0, + /** Variable: autoscroll * Boolean whether autoscroll is enabled */ - autoscroll: true, - - /** Function: hasFocus + autoscroll: true, + /** Function: hasFocus * Checks if window has focus * * Returns: * (Boolean) */ - hasFocus: function() { - return self.Window._hasFocus; - }, - - /** Function: increaseUnreadMessages + hasFocus: function() { + return self.Window._hasFocus; + }, + /** Function: increaseUnreadMessages * Increases unread message count in window title by one. */ - increaseUnreadMessages: function() { - self.Window.renderUnreadMessages(++self.Window._unreadMessagesCount); - }, - - /** Function: reduceUnreadMessages + increaseUnreadMessages: function() { + self.Window.renderUnreadMessages(++self.Window._unreadMessagesCount); + }, + /** Function: reduceUnreadMessages * Reduce unread message count in window title by `num`. * * Parameters: * (Integer) num - Unread message count will be reduced by this value */ - reduceUnreadMessages: function(num) { - self.Window._unreadMessagesCount -= num; - if(self.Window._unreadMessagesCount <= 0) { - self.Window.clearUnreadMessages(); - } else { - self.Window.renderUnreadMessages(self.Window._unreadMessagesCount); - } - }, - - /** Function: clearUnreadMessages + reduceUnreadMessages: function(num) { + self.Window._unreadMessagesCount -= num; + if (self.Window._unreadMessagesCount <= 0) { + self.Window.clearUnreadMessages(); + } else { + self.Window.renderUnreadMessages(self.Window._unreadMessagesCount); + } + }, + /** Function: clearUnreadMessages * Clear unread message count in window title. */ - clearUnreadMessages: function() { - self.Window._unreadMessagesCount = 0; - document.title = self.Window._plainTitle; - }, - - /** Function: renderUnreadMessages + clearUnreadMessages: function() { + self.Window._unreadMessagesCount = 0; + document.title = self.Window._plainTitle; + }, + /** Function: renderUnreadMessages * Update window title to show message count. * * Parameters: * (Integer) count - Number of unread messages to show in window title */ - renderUnreadMessages: function(count) { - document.title = Candy.View.Template.Window.unreadmessages.replace('{{count}}', count).replace('{{title}}', self.Window._plainTitle); - }, - - /** Function: onFocus + renderUnreadMessages: function(count) { + document.title = Candy.View.Template.Window.unreadmessages.replace("{{count}}", count).replace("{{title}}", self.Window._plainTitle); + }, + /** Function: onFocus * Window focus event handler. */ - onFocus: function() { - self.Window._hasFocus = true; - if (Candy.View.getCurrent().roomJid) { - self.Room.setFocusToForm(Candy.View.getCurrent().roomJid); - self.Chat.clearUnreadMessages(Candy.View.getCurrent().roomJid); - } - }, - - /** Function: onBlur + onFocus: function() { + self.Window._hasFocus = true; + if (Candy.View.getCurrent().roomJid) { + self.Room.setFocusToForm(Candy.View.getCurrent().roomJid); + self.Chat.clearUnreadMessages(Candy.View.getCurrent().roomJid); + } + }, + /** Function: onBlur * Window blur event handler. */ - onBlur: function() { - self.Window._hasFocus = false; - } - }; - - /** Class: Candy.View.Pane.Chat + onBlur: function() { + self.Window._hasFocus = false; + } + }; + /** Class: Candy.View.Pane.Chat * Chat-View related view updates */ - self.Chat = { - /** Variable: rooms + self.Chat = { + /** Variable: rooms * Contains opened room elements */ - rooms: [], - - /** Function: addTab + rooms: [], + /** Function: addTab * Add a tab to the chat pane. * * Parameters: @@ -3035,25 +2853,22 @@ Candy.View.Pane = (function(self, $) { * (String) roomName - Tab label * (String) roomType - Type of room: `groupchat` or `chat` */ - addTab: function(roomJid, roomName, roomType) { - var roomId = Candy.Util.jidToId(roomJid), - html = Mustache.to_html(Candy.View.Template.Chat.tab, { - roomJid: roomJid, - roomId: roomId, - name: roomName || Strophe.getNodeFromJid(roomJid), - privateUserChat: function() {return roomType === 'chat';}, - roomType: roomType - }), - tab = $(html).appendTo('#chat-tabs'); - - tab.click(self.Chat.tabClick); - // TODO: maybe we find a better way to get the close element. - $('a.close', tab).click(self.Chat.tabClose); - - self.Chat.fitTabs(); - }, - - /** Function: getTab + addTab: function(roomJid, roomName, roomType) { + var roomId = Candy.Util.jidToId(roomJid), html = Mustache.to_html(Candy.View.Template.Chat.tab, { + roomJid: roomJid, + roomId: roomId, + name: roomName || Strophe.getNodeFromJid(roomJid), + privateUserChat: function() { + return roomType === "chat"; + }, + roomType: roomType + }), tab = $(html).appendTo("#chat-tabs"); + tab.click(self.Chat.tabClick); + // TODO: maybe we find a better way to get the close element. + $("a.close", tab).click(self.Chat.tabClose); + self.Chat.fitTabs(); + }, + /** Function: getTab * Get tab by JID. * * Parameters: @@ -3062,22 +2877,20 @@ Candy.View.Pane = (function(self, $) { * Returns: * (jQuery object) - Tab element */ - getTab: function(roomJid) { - return $('#chat-tabs').children('li[data-roomjid="' + roomJid + '"]'); - }, - - /** Function: removeTab + getTab: function(roomJid) { + return $("#chat-tabs").children('li[data-roomjid="' + roomJid + '"]'); + }, + /** Function: removeTab * Remove tab element. * * Parameters: * (String) roomJid - JID of room */ - removeTab: function(roomJid) { - self.Chat.getTab(roomJid).remove(); - self.Chat.fitTabs(); - }, - - /** Function: setActiveTab + removeTab: function(roomJid) { + self.Chat.getTab(roomJid).remove(); + self.Chat.fitTabs(); + }, + /** Function: setActiveTab * Set the active tab. * * Add CSS classname `active` to the choosen tab and remove `active` from all other. @@ -3085,18 +2898,17 @@ Candy.View.Pane = (function(self, $) { * Parameters: * (String) roomJid - JID of room */ - setActiveTab: function(roomJid) { - $('#chat-tabs').children().each(function() { - var tab = $(this); - if(tab.attr('data-roomjid') === roomJid) { - tab.addClass('active'); - } else { - tab.removeClass('active'); - } - }); - }, - - /** Function: increaseUnreadMessages + setActiveTab: function(roomJid) { + $("#chat-tabs").children().each(function() { + var tab = $(this); + if (tab.attr("data-roomjid") === roomJid) { + tab.addClass("active"); + } else { + tab.removeClass("active"); + } + }); + }, + /** Function: increaseUnreadMessages * Increase unread message count in a tab by one. * * Parameters: @@ -3105,16 +2917,15 @@ Candy.View.Pane = (function(self, $) { * Uses: * - */ - increaseUnreadMessages: function(roomJid) { - var unreadElem = this.getTab(roomJid).find('.unread'); - unreadElem.show().text(unreadElem.text() !== '' ? parseInt(unreadElem.text(), 10) + 1 : 1); - // only increase window unread messages in private chats - if (self.Chat.rooms[roomJid].type === 'chat') { - self.Window.increaseUnreadMessages(); - } - }, - - /** Function: clearUnreadMessages + increaseUnreadMessages: function(roomJid) { + var unreadElem = this.getTab(roomJid).find(".unread"); + unreadElem.show().text(unreadElem.text() !== "" ? parseInt(unreadElem.text(), 10) + 1 : 1); + // only increase window unread messages in private chats + if (self.Chat.rooms[roomJid].type === "chat") { + self.Window.increaseUnreadMessages(); + } + }, + /** Function: clearUnreadMessages * Clear unread message count in a tab. * * Parameters: @@ -3123,25 +2934,22 @@ Candy.View.Pane = (function(self, $) { * Uses: * - */ - clearUnreadMessages: function(roomJid) { - var unreadElem = self.Chat.getTab(roomJid).find('.unread'); - self.Window.reduceUnreadMessages(unreadElem.text()); - unreadElem.hide().text(''); - }, - - /** Function: tabClick + clearUnreadMessages: function(roomJid) { + var unreadElem = self.Chat.getTab(roomJid).find(".unread"); + self.Window.reduceUnreadMessages(unreadElem.text()); + unreadElem.hide().text(""); + }, + /** Function: tabClick * Tab click event: show the room associated with the tab and stops the event from doing the default. */ - tabClick: function(e) { - // remember scroll position of current room - var currentRoomJid = Candy.View.getCurrent().roomJid; - self.Chat.rooms[currentRoomJid].scrollPosition = self.Room.getPane(currentRoomJid, '.message-pane-wrapper').scrollTop(); - - self.Room.show($(this).attr('data-roomjid')); - e.preventDefault(); - }, - - /** Function: tabClose + tabClick: function(e) { + // remember scroll position of current room + var currentRoomJid = Candy.View.getCurrent().roomJid; + self.Chat.rooms[currentRoomJid].scrollPosition = self.Room.getPane(currentRoomJid, ".message-pane-wrapper").scrollTop(); + self.Room.show($(this).attr("data-roomjid")); + e.preventDefault(); + }, + /** Function: tabClose * Tab close (click) event: Leave the room (groupchat) or simply close the tab (chat). * * Parameters: @@ -3150,19 +2958,17 @@ Candy.View.Pane = (function(self, $) { * Returns: * (Boolean) - false, this will stop the event from bubbling */ - tabClose: function() { - var roomJid = $(this).parent().attr('data-roomjid'); - // close private user tab - if(self.Chat.rooms[roomJid].type === 'chat') { - self.Room.close(roomJid); - // close multi-user room tab - } else { - Candy.Core.Action.Jabber.Room.Leave(roomJid); - } - return false; - }, - - /** Function: allTabsClosed + tabClose: function() { + var roomJid = $(this).parent().attr("data-roomjid"); + // close private user tab + if (self.Chat.rooms[roomJid].type === "chat") { + self.Room.close(roomJid); + } else { + Candy.Core.Action.Jabber.Room.Leave(roomJid); + } + return false; + }, + /** Function: allTabsClosed * All tabs closed event: Disconnect from service. Hide sound control. * * TODO: Handle window close @@ -3170,31 +2976,32 @@ Candy.View.Pane = (function(self, $) { * Returns: * (Boolean) - false, this will stop the event from bubbling */ - allTabsClosed: function() { - Candy.Core.disconnect(); - self.Chat.Toolbar.hide(); - return; - }, - - /** Function: fitTabs + allTabsClosed: function() { + Candy.Core.disconnect(); + self.Chat.Toolbar.hide(); + return; + }, + /** Function: fitTabs * Fit tab size according to window size */ - fitTabs: function() { - var availableWidth = $('#chat-tabs').innerWidth(), - tabsWidth = 0, - tabs = $('#chat-tabs').children(); - tabs.each(function() { - tabsWidth += $(this).css({width: 'auto', overflow: 'visible'}).outerWidth(true); - }); - if(tabsWidth > availableWidth) { - // tabs.[outer]Width() measures the first element in `tabs`. It's no very readable but nearly two times faster than using :first - var tabDiffToRealWidth = tabs.outerWidth(true) - tabs.width(), - tabWidth = Math.floor((availableWidth) / tabs.length) - tabDiffToRealWidth; - tabs.css({width: tabWidth, overflow: 'hidden'}); - } - }, - - /** Function: adminMessage + fitTabs: function() { + var availableWidth = $("#chat-tabs").innerWidth(), tabsWidth = 0, tabs = $("#chat-tabs").children(); + tabs.each(function() { + tabsWidth += $(this).css({ + width: "auto", + overflow: "visible" + }).outerWidth(true); + }); + if (tabsWidth > availableWidth) { + // tabs.[outer]Width() measures the first element in `tabs`. It's no very readable but nearly two times faster than using :first + var tabDiffToRealWidth = tabs.outerWidth(true) - tabs.width(), tabWidth = Math.floor(availableWidth / tabs.length) - tabDiffToRealWidth; + tabs.css({ + width: tabWidth, + overflow: "hidden" + }); + } + }, + /** Function: adminMessage * Display admin message * * Parameters: @@ -3204,33 +3011,32 @@ Candy.View.Pane = (function(self, $) { * Triggers: * candy:view.chat.admin-message using {subject, message} */ - adminMessage: function(subject, message) { - if(Candy.View.getCurrent().roomJid) { // Simply dismiss admin message if no room joined so far. TODO: maybe we should show those messages on a dedicated pane? - var html = Mustache.to_html(Candy.View.Template.Chat.adminMessage, { - subject: subject, - message: message, - sender: $.i18n._('administratorMessageSubject'), - time: Candy.Util.localizedTime(new Date().toGMTString()) - }); - $('#chat-rooms').children().each(function() { - self.Room.appendToMessagePane($(this).attr('data-roomjid'), html); - }); - self.Room.scrollToBottom(Candy.View.getCurrent().roomJid); - - /** Event: candy:view.chat.admin-message + adminMessage: function(subject, message) { + if (Candy.View.getCurrent().roomJid) { + // Simply dismiss admin message if no room joined so far. TODO: maybe we should show those messages on a dedicated pane? + var html = Mustache.to_html(Candy.View.Template.Chat.adminMessage, { + subject: subject, + message: message, + sender: $.i18n._("administratorMessageSubject"), + time: Candy.Util.localizedTime(new Date().toGMTString()) + }); + $("#chat-rooms").children().each(function() { + self.Room.appendToMessagePane($(this).attr("data-roomjid"), html); + }); + self.Room.scrollToBottom(Candy.View.getCurrent().roomJid); + /** Event: candy:view.chat.admin-message * After admin message display * * Parameters: * (String) presetJid - Preset user JID */ - $(Candy).triggerHandler('candy:view.chat.admin-message', { - 'subject' : subject, - 'message' : message - }); - } - }, - - /** Function: infoMessage + $(Candy).triggerHandler("candy:view.chat.admin-message", { + subject: subject, + message: message + }); + } + }, + /** Function: infoMessage * Display info message. This is a wrapper for to be able to disable certain info messages. * * Parameters: @@ -3238,11 +3044,10 @@ Candy.View.Pane = (function(self, $) { * (String) subject - Subject * (String) message - Message */ - infoMessage: function(roomJid, subject, message) { - self.Chat.onInfoMessage(roomJid, subject, message); - }, - - /** Function: onInfoMessage + infoMessage: function(roomJid, subject, message) { + self.Chat.onInfoMessage(roomJid, subject, message); + }, + /** Function: onInfoMessage * Display info message. Used by and several other functions which do not wish that their info message * can be disabled (such as kick/ban message or leave/join message in private chats). * @@ -3251,180 +3056,167 @@ Candy.View.Pane = (function(self, $) { * (String) subject - Subject * (String) message - Message */ - onInfoMessage: function(roomJid, subject, message) { - if(Candy.View.getCurrent().roomJid) { // Simply dismiss info message if no room joined so far. TODO: maybe we should show those messages on a dedicated pane? - var html = Mustache.to_html(Candy.View.Template.Chat.infoMessage, { - subject: subject, - message: $.i18n._(message), - time: Candy.Util.localizedTime(new Date().toGMTString()) - }); - self.Room.appendToMessagePane(roomJid, html); - if (Candy.View.getCurrent().roomJid === roomJid) { - self.Room.scrollToBottom(Candy.View.getCurrent().roomJid); - } - } - }, - - /** Class: Candy.View.Pane.Toolbar + onInfoMessage: function(roomJid, subject, message) { + if (Candy.View.getCurrent().roomJid) { + // Simply dismiss info message if no room joined so far. TODO: maybe we should show those messages on a dedicated pane? + var html = Mustache.to_html(Candy.View.Template.Chat.infoMessage, { + subject: subject, + message: $.i18n._(message), + time: Candy.Util.localizedTime(new Date().toGMTString()) + }); + self.Room.appendToMessagePane(roomJid, html); + if (Candy.View.getCurrent().roomJid === roomJid) { + self.Room.scrollToBottom(Candy.View.getCurrent().roomJid); + } + } + }, + /** Class: Candy.View.Pane.Toolbar * Chat toolbar for things like emoticons toolbar, room management etc. */ - Toolbar: { - _supportsNativeAudio: false, - - /** Function: init + Toolbar: { + _supportsNativeAudio: false, + /** Function: init * Register handler and enable or disable sound and status messages. */ - init: function() { - $('#emoticons-icon').click(function(e) { - self.Chat.Context.showEmoticonsMenu(e.currentTarget); - e.stopPropagation(); - }); - $('#chat-autoscroll-control').click(self.Chat.Toolbar.onAutoscrollControlClick); - - var a = document.createElement('audio'); - self.Chat.Toolbar._supportsNativeAudio = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, '')); - $('#chat-sound-control').click(self.Chat.Toolbar.onSoundControlClick); - if(Candy.Util.cookieExists('candy-nosound')) { - $('#chat-sound-control').click(); - } - $('#chat-statusmessage-control').click(self.Chat.Toolbar.onStatusMessageControlClick); - if(Candy.Util.cookieExists('candy-nostatusmessages')) { - $('#chat-statusmessage-control').click(); - } - }, - - /** Function: show + init: function() { + $("#emoticons-icon").click(function(e) { + self.Chat.Context.showEmoticonsMenu(e.currentTarget); + e.stopPropagation(); + }); + $("#chat-autoscroll-control").click(self.Chat.Toolbar.onAutoscrollControlClick); + var a = document.createElement("audio"); + self.Chat.Toolbar._supportsNativeAudio = !!(a.canPlayType && a.canPlayType("audio/mpeg;").replace(/no/, "")); + $("#chat-sound-control").click(self.Chat.Toolbar.onSoundControlClick); + if (Candy.Util.cookieExists("candy-nosound")) { + $("#chat-sound-control").click(); + } + $("#chat-statusmessage-control").click(self.Chat.Toolbar.onStatusMessageControlClick); + if (Candy.Util.cookieExists("candy-nostatusmessages")) { + $("#chat-statusmessage-control").click(); + } + }, + /** Function: show * Show toolbar. */ - show: function() { - $('#chat-toolbar').show(); - }, - - /** Function: hide + show: function() { + $("#chat-toolbar").show(); + }, + /** Function: hide * Hide toolbar. */ - hide: function() { - $('#chat-toolbar').hide(); - }, - - /* Function: update + hide: function() { + $("#chat-toolbar").hide(); + }, + /* Function: update * Update toolbar for specific room */ - update: function(roomJid) { - var context = $('#chat-toolbar').find('.context'), - me = self.Room.getUser(roomJid); - if(!me || !me.isModerator()) { - context.hide(); - } else { - context.show().click(function(e) { - self.Chat.Context.show(e.currentTarget, roomJid); - e.stopPropagation(); - }); - } - self.Chat.Toolbar.updateUsercount(self.Chat.rooms[roomJid].usercount); - }, - - /** Function: playSound + update: function(roomJid) { + var context = $("#chat-toolbar").find(".context"), me = self.Room.getUser(roomJid); + if (!me || !me.isModerator()) { + context.hide(); + } else { + context.show().click(function(e) { + self.Chat.Context.show(e.currentTarget, roomJid); + e.stopPropagation(); + }); + } + self.Chat.Toolbar.updateUsercount(self.Chat.rooms[roomJid].usercount); + }, + /** Function: playSound * Play sound (default method). */ - playSound: function() { - self.Chat.Toolbar.onPlaySound(); - }, - - /** Function: onPlaySound + playSound: function() { + self.Chat.Toolbar.onPlaySound(); + }, + /** Function: onPlaySound * Sound play event handler. Uses native (HTML5) audio if supported * * Don't call this method directly. Call `playSound()` instead. * `playSound()` will only call this method if sound is enabled. */ - onPlaySound: function() { - try { - if(self.Chat.Toolbar._supportsNativeAudio) { - new Audio(Candy.View.getOptions().resources + 'notify.mp3').play(); - } else { - var chatSoundPlayer = document.getElementById('chat-sound-player'); - chatSoundPlayer.SetVariable('method:stop', ''); - chatSoundPlayer.SetVariable('method:play', ''); - } - } catch (e) {} - }, - - /** Function: onSoundControlClick + onPlaySound: function() { + try { + if (self.Chat.Toolbar._supportsNativeAudio) { + new Audio(Candy.View.getOptions().resources + "notify.mp3").play(); + } else { + var chatSoundPlayer = document.getElementById("chat-sound-player"); + chatSoundPlayer.SetVariable("method:stop", ""); + chatSoundPlayer.SetVariable("method:play", ""); + } + } catch (e) {} + }, + /** Function: onSoundControlClick * Sound control click event handler. * * Toggle sound (overwrite `playSound()`) and handle cookies. */ - onSoundControlClick: function() { - var control = $('#chat-sound-control'); - if(control.hasClass('checked')) { - self.Chat.Toolbar.playSound = function() {}; - Candy.Util.setCookie('candy-nosound', '1', 365); - } else { - self.Chat.Toolbar.playSound = function() { - self.Chat.Toolbar.onPlaySound(); - }; - Candy.Util.deleteCookie('candy-nosound'); - } - control.toggleClass('checked'); - }, - - /** Function: onAutoscrollControlClick + onSoundControlClick: function() { + var control = $("#chat-sound-control"); + if (control.hasClass("checked")) { + self.Chat.Toolbar.playSound = function() {}; + Candy.Util.setCookie("candy-nosound", "1", 365); + } else { + self.Chat.Toolbar.playSound = function() { + self.Chat.Toolbar.onPlaySound(); + }; + Candy.Util.deleteCookie("candy-nosound"); + } + control.toggleClass("checked"); + }, + /** Function: onAutoscrollControlClick * Autoscroll control event handler. * * Toggle autoscroll */ - onAutoscrollControlClick: function() { - var control = $('#chat-autoscroll-control'); - if(control.hasClass('checked')) { - self.Room.scrollToBottom = function(roomJid) { - self.Room.onScrollToStoredPosition(roomJid); - }; - self.Window.autoscroll = false; - } else { - self.Room.scrollToBottom = function(roomJid) { - self.Room.onScrollToBottom(roomJid); - }; - self.Room.scrollToBottom(Candy.View.getCurrent().roomJid); - self.Window.autoscroll = true; - } - control.toggleClass('checked'); - }, - - /** Function: onStatusMessageControlClick + onAutoscrollControlClick: function() { + var control = $("#chat-autoscroll-control"); + if (control.hasClass("checked")) { + self.Room.scrollToBottom = function(roomJid) { + self.Room.onScrollToStoredPosition(roomJid); + }; + self.Window.autoscroll = false; + } else { + self.Room.scrollToBottom = function(roomJid) { + self.Room.onScrollToBottom(roomJid); + }; + self.Room.scrollToBottom(Candy.View.getCurrent().roomJid); + self.Window.autoscroll = true; + } + control.toggleClass("checked"); + }, + /** Function: onStatusMessageControlClick * Status message control event handler. * * Toggle status message */ - onStatusMessageControlClick: function() { - var control = $('#chat-statusmessage-control'); - if(control.hasClass('checked')) { - self.Chat.infoMessage = function() {}; - Candy.Util.setCookie('candy-nostatusmessages', '1', 365); - } else { - self.Chat.infoMessage = function(roomJid, subject, message) { - self.Chat.onInfoMessage(roomJid, subject, message); - }; - Candy.Util.deleteCookie('candy-nostatusmessages'); - } - control.toggleClass('checked'); - }, - - /** Function: updateUserCount + onStatusMessageControlClick: function() { + var control = $("#chat-statusmessage-control"); + if (control.hasClass("checked")) { + self.Chat.infoMessage = function() {}; + Candy.Util.setCookie("candy-nostatusmessages", "1", 365); + } else { + self.Chat.infoMessage = function(roomJid, subject, message) { + self.Chat.onInfoMessage(roomJid, subject, message); + }; + Candy.Util.deleteCookie("candy-nostatusmessages"); + } + control.toggleClass("checked"); + }, + /** Function: updateUserCount * Update usercount element with count. * * Parameters: * (Integer) count - Current usercount */ - updateUsercount: function(count) { - $('#chat-usercount').text(count); - } - }, - - /** Class: Candy.View.Pane.Modal + updateUsercount: function(count) { + $("#chat-usercount").text(count); + } + }, + /** Class: Candy.View.Pane.Modal * Modal window */ - Modal: { - /** Function: show + Modal: { + /** Function: show * Display modal window * * Parameters: @@ -3432,130 +3224,118 @@ Candy.View.Pane = (function(self, $) { * (Boolean) showCloseControl - set to true if a close button should be displayed [default false] * (Boolean) showSpinner - set to true if a loading spinner should be shown [default false] */ - show: function(html, showCloseControl, showSpinner) { - if(showCloseControl) { - self.Chat.Modal.showCloseControl(); - } else { - self.Chat.Modal.hideCloseControl(); - } - if(showSpinner) { - self.Chat.Modal.showSpinner(); - } else { - self.Chat.Modal.hideSpinner(); - } - $('#chat-modal').stop(false, true); - $('#chat-modal-body').html(html); - $('#chat-modal').fadeIn('fast'); - $('#chat-modal-overlay').show(); - }, - - /** Function: hide + show: function(html, showCloseControl, showSpinner) { + if (showCloseControl) { + self.Chat.Modal.showCloseControl(); + } else { + self.Chat.Modal.hideCloseControl(); + } + if (showSpinner) { + self.Chat.Modal.showSpinner(); + } else { + self.Chat.Modal.hideSpinner(); + } + $("#chat-modal").stop(false, true); + $("#chat-modal-body").html(html); + $("#chat-modal").fadeIn("fast"); + $("#chat-modal-overlay").show(); + }, + /** Function: hide * Hide modal window * * Parameters: * (Function) callback - Calls the specified function after modal window has been hidden. */ - hide: function(callback) { - $('#chat-modal').fadeOut('fast', function() { - $('#chat-modal-body').text(''); - $('#chat-modal-overlay').hide(); - }); - // restore initial esc handling - $(document).keydown(function(e) { - if(e.which === 27) { - e.preventDefault(); - } - }); - if (callback) { - callback(); - } - }, - - /** Function: showSpinner + hide: function(callback) { + $("#chat-modal").fadeOut("fast", function() { + $("#chat-modal-body").text(""); + $("#chat-modal-overlay").hide(); + }); + // restore initial esc handling + $(document).keydown(function(e) { + if (e.which === 27) { + e.preventDefault(); + } + }); + if (callback) { + callback(); + } + }, + /** Function: showSpinner * Show loading spinner */ - showSpinner: function() { - $('#chat-modal-spinner').show(); - }, - - /** Function: hideSpinner + showSpinner: function() { + $("#chat-modal-spinner").show(); + }, + /** Function: hideSpinner * Hide loading spinner */ - hideSpinner: function() { - $('#chat-modal-spinner').hide(); - }, - - /** Function: showCloseControl + hideSpinner: function() { + $("#chat-modal-spinner").hide(); + }, + /** Function: showCloseControl * Show a close button */ - showCloseControl: function() { - $('#admin-message-cancel').show().click(function(e) { - self.Chat.Modal.hide(); - // some strange behaviour on IE7 (and maybe other browsers) triggers onWindowUnload when clicking on the close button. - // prevent this. - e.preventDefault(); - }); - - // enable esc to close modal - $(document).keydown(function(e) { - if(e.which === 27) { - self.Chat.Modal.hide(); - e.preventDefault(); - } - }); - }, - - /** Function: hideCloseControl + showCloseControl: function() { + $("#admin-message-cancel").show().click(function(e) { + self.Chat.Modal.hide(); + // some strange behaviour on IE7 (and maybe other browsers) triggers onWindowUnload when clicking on the close button. + // prevent this. + e.preventDefault(); + }); + // enable esc to close modal + $(document).keydown(function(e) { + if (e.which === 27) { + self.Chat.Modal.hide(); + e.preventDefault(); + } + }); + }, + /** Function: hideCloseControl * Hide the close button */ - hideCloseControl: function() { - $('#admin-message-cancel').hide().click(function() {}); - }, - - /** Function: showLoginForm + hideCloseControl: function() { + $("#admin-message-cancel").hide().click(function() {}); + }, + /** Function: showLoginForm * Show the login form modal * * Parameters: * (String) message - optional message to display above the form * (String) presetJid - optional user jid. if set, the user will only be prompted for password. */ - showLoginForm: function(message, presetJid) { - self.Chat.Modal.show((message ? message : '') + Mustache.to_html(Candy.View.Template.Login.form, { - _labelNickname: $.i18n._('labelNickname'), - _labelUsername: $.i18n._('labelUsername'), - _labelPassword: $.i18n._('labelPassword'), - _loginSubmit: $.i18n._('loginSubmit'), - displayPassword: !Candy.Core.isAnonymousConnection(), - displayUsername: !presetJid, - displayNickname: Candy.Core.isAnonymousConnection(), - presetJid: presetJid ? presetJid : false - })); - $('#login-form').children(':input:first').focus(); - - // register submit handler - $('#login-form').submit(function() { - var username = $('#username').val(), - password = $('#password').val(); - - if (!Candy.Core.isAnonymousConnection()) { - // guess the input and create a jid out of it - var jid = Candy.Core.getUser() && username.indexOf("@") < 0 ? - username + '@' + Strophe.getDomainFromJid(Candy.Core.getUser().getJid()) : username; - - if(jid.indexOf("@") < 0 && !Candy.Core.getUser()) { - Candy.View.Pane.Chat.Modal.showLoginForm($.i18n._('loginInvalid')); - } else { - //Candy.View.Pane.Chat.Modal.hide(); - Candy.Core.connect(jid, password); - } - } else { // anonymous login - Candy.Core.connect(presetJid, null, username); - } - return false; - }); - }, - - /** Function: showEnterPasswordForm + showLoginForm: function(message, presetJid) { + self.Chat.Modal.show((message ? message : "") + Mustache.to_html(Candy.View.Template.Login.form, { + _labelNickname: $.i18n._("labelNickname"), + _labelUsername: $.i18n._("labelUsername"), + _labelPassword: $.i18n._("labelPassword"), + _loginSubmit: $.i18n._("loginSubmit"), + displayPassword: !Candy.Core.isAnonymousConnection(), + displayUsername: !presetJid, + displayNickname: Candy.Core.isAnonymousConnection(), + presetJid: presetJid ? presetJid : false + })); + $("#login-form").children(":input:first").focus(); + // register submit handler + $("#login-form").submit(function() { + var username = $("#username").val(), password = $("#password").val(); + if (!Candy.Core.isAnonymousConnection()) { + // guess the input and create a jid out of it + var jid = Candy.Core.getUser() && username.indexOf("@") < 0 ? username + "@" + Strophe.getDomainFromJid(Candy.Core.getUser().getJid()) : username; + if (jid.indexOf("@") < 0 && !Candy.Core.getUser()) { + Candy.View.Pane.Chat.Modal.showLoginForm($.i18n._("loginInvalid")); + } else { + //Candy.View.Pane.Chat.Modal.hide(); + Candy.Core.connect(jid, password); + } + } else { + // anonymous login + Candy.Core.connect(presetJid, null, username); + } + return false; + }); + }, + /** Function: showEnterPasswordForm * Shows a form for entering room password * * Parameters: @@ -3563,72 +3343,65 @@ Candy.View.Pane = (function(self, $) { * (String) roomName - Room name * (String) message - [optional] Message to show as the label */ - showEnterPasswordForm: function(roomJid, roomName, message) { - self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.enterPasswordForm, { - roomName: roomName, - _labelPassword: $.i18n._('labelPassword'), - _label: (message ? message : $.i18n._('enterRoomPassword', [roomName])), - _joinSubmit: $.i18n._('enterRoomPasswordSubmit') - }), true); - $('#password').focus(); - - // register submit handler - $('#enter-password-form').submit(function() { - var password = $('#password').val(); - - self.Chat.Modal.hide(function() { - Candy.Core.Action.Jabber.Room.Join(roomJid, password); - }); - return false; - }); - }, - - /** Function: showNicknameConflictForm + showEnterPasswordForm: function(roomJid, roomName, message) { + self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.enterPasswordForm, { + roomName: roomName, + _labelPassword: $.i18n._("labelPassword"), + _label: message ? message : $.i18n._("enterRoomPassword", [ roomName ]), + _joinSubmit: $.i18n._("enterRoomPasswordSubmit") + }), true); + $("#password").focus(); + // register submit handler + $("#enter-password-form").submit(function() { + var password = $("#password").val(); + self.Chat.Modal.hide(function() { + Candy.Core.Action.Jabber.Room.Join(roomJid, password); + }); + return false; + }); + }, + /** Function: showNicknameConflictForm * Shows a form indicating that the nickname is already taken and * for chosing a new nickname * * Parameters: * (String) roomJid - Room jid to join */ - showNicknameConflictForm: function(roomJid) { - self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.nicknameConflictForm, { - _labelNickname: $.i18n._('labelNickname'), - _label: $.i18n._('nicknameConflict'), - _loginSubmit: $.i18n._('loginSubmit') - })); - $('#nickname').focus(); - - // register submit handler - $('#nickname-conflict-form').submit(function() { - var nickname = $('#nickname').val(); - - self.Chat.Modal.hide(function() { - Candy.Core.getUser().data.nick = nickname; - Candy.Core.Action.Jabber.Room.Join(roomJid); - }); - return false; - }); - }, - - /** Function: showError + showNicknameConflictForm: function(roomJid) { + self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.nicknameConflictForm, { + _labelNickname: $.i18n._("labelNickname"), + _label: $.i18n._("nicknameConflict"), + _loginSubmit: $.i18n._("loginSubmit") + })); + $("#nickname").focus(); + // register submit handler + $("#nickname-conflict-form").submit(function() { + var nickname = $("#nickname").val(); + self.Chat.Modal.hide(function() { + Candy.Core.getUser().data.nick = nickname; + Candy.Core.Action.Jabber.Room.Join(roomJid); + }); + return false; + }); + }, + /** Function: showError * Show modal containing error message * * Parameters: * (String) message - key of translation to display * (Array) replacements - array containing replacements for translation (%s) */ - showError: function(message, replacements) { - self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.displayError, { - _error: $.i18n._(message, replacements) - }), true); - } - }, - - /** Class: Candy.View.Pane.Tooltip + showError: function(message, replacements) { + self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.displayError, { + _error: $.i18n._(message, replacements) + }), true); + } + }, + /** Class: Candy.View.Pane.Tooltip * Class to display tooltips over specific elements */ - Tooltip: { - /** Function: show + Tooltip: { + /** Function: show * Show a tooltip on event.currentTarget with content specified or content within the target's attribute data-tooltip. * * On mouseleave on the target, hide the tooltip. @@ -3637,60 +3410,52 @@ Candy.View.Pane = (function(self, $) { * (Event) event - Triggered event * (String) content - Content to display [optional] */ - show: function(event, content) { - var tooltip = $('#tooltip'), - target = $(event.currentTarget); - - if(!content) { - content = target.attr('data-tooltip'); - } - - if(tooltip.length === 0) { - var html = Mustache.to_html(Candy.View.Template.Chat.tooltip); - $('#chat-pane').append(html); - tooltip = $('#tooltip'); - } - - $('#context-menu').hide(); - - tooltip.stop(false, true); - tooltip.children('div').html(content); - - var pos = target.offset(), - posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(tooltip, pos.left), - posTop = Candy.Util.getPosTopAccordingToWindowBounds(tooltip, pos.top); - - tooltip - .css({'left': posLeft.px, 'top': posTop.px}) - .removeClass('left-top left-bottom right-top right-bottom') - .addClass(posLeft.backgroundPositionAlignment + '-' + posTop.backgroundPositionAlignment) - .fadeIn('fast'); - - target.mouseleave(function(event) { - event.stopPropagation(); - $('#tooltip').stop(false, true).fadeOut('fast', function() {$(this).css({'top': 0, 'left': 0});}); - }); - } - }, - - /** Class: Candy.View.Pane.Context + show: function(event, content) { + var tooltip = $("#tooltip"), target = $(event.currentTarget); + if (!content) { + content = target.attr("data-tooltip"); + } + if (tooltip.length === 0) { + var html = Mustache.to_html(Candy.View.Template.Chat.tooltip); + $("#chat-pane").append(html); + tooltip = $("#tooltip"); + } + $("#context-menu").hide(); + tooltip.stop(false, true); + tooltip.children("div").html(content); + var pos = target.offset(), posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(tooltip, pos.left), posTop = Candy.Util.getPosTopAccordingToWindowBounds(tooltip, pos.top); + tooltip.css({ + left: posLeft.px, + top: posTop.px + }).removeClass("left-top left-bottom right-top right-bottom").addClass(posLeft.backgroundPositionAlignment + "-" + posTop.backgroundPositionAlignment).fadeIn("fast"); + target.mouseleave(function(event) { + event.stopPropagation(); + $("#tooltip").stop(false, true).fadeOut("fast", function() { + $(this).css({ + top: 0, + left: 0 + }); + }); + }); + } + }, + /** Class: Candy.View.Pane.Context * Context menu for actions and settings */ - Context: { - /** Function: init + Context: { + /** Function: init * Initialize context menu and setup mouseleave handler. */ - init: function() { - if ($('#context-menu').length === 0) { - var html = Mustache.to_html(Candy.View.Template.Chat.Context.menu); - $('#chat-pane').append(html); - $('#context-menu').mouseleave(function() { - $(this).fadeOut('fast'); - }); - } - }, - - /** Function: show + init: function() { + if ($("#context-menu").length === 0) { + var html = Mustache.to_html(Candy.View.Template.Chat.Context.menu); + $("#chat-pane").append(html); + $("#context-menu").mouseleave(function() { + $(this).fadeOut("fast"); + }); + } + }, + /** Function: show * Show context menu (positions it according to the window height/width) * * Parameters: @@ -3706,56 +3471,41 @@ Candy.View.Pane = (function(self, $) { * Triggers: * candy:view.roster.after-context-menu using {roomJid, user, elements} */ - show: function(elem, roomJid, user) { - elem = $(elem); - var roomId = self.Chat.rooms[roomJid].id, - menu = $('#context-menu'), - links = $('ul li', menu); - - $('#tooltip').hide(); - - // add specific context-user class if a user is available (when context menu should be opened next to a user) - if(!user) { - user = Candy.Core.getUser(); - } - - links.remove(); - - var menulinks = this.getMenuLinks(roomJid, user, elem), - id, - clickHandler = function(roomJid, user) { - return function(event) { - event.data.callback(event, roomJid, user); - $('#context-menu').hide(); - }; - }; - - for(id in menulinks) { - if(menulinks.hasOwnProperty(id)) { - var link = menulinks[id], - html = Mustache.to_html(Candy.View.Template.Chat.Context.menulinks, { - 'roomId' : roomId, - 'class' : link['class'], - 'id' : id, - 'label' : link.label - }); - $('ul', menu).append(html); - $('#context-menu-' + id).bind('click', link, clickHandler(roomJid, user)); - } - } - // if `id` is set the menu is not empty - if(id) { - var pos = elem.offset(), - posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(menu, pos.left), - posTop = Candy.Util.getPosTopAccordingToWindowBounds(menu, pos.top); - - menu - .css({'left': posLeft.px, 'top': posTop.px}) - .removeClass('left-top left-bottom right-top right-bottom') - .addClass(posLeft.backgroundPositionAlignment + '-' + posTop.backgroundPositionAlignment) - .fadeIn('fast'); - - /** Event: candy:view.roster.after-context-menu + show: function(elem, roomJid, user) { + elem = $(elem); + var roomId = self.Chat.rooms[roomJid].id, menu = $("#context-menu"), links = $("ul li", menu); + $("#tooltip").hide(); + // add specific context-user class if a user is available (when context menu should be opened next to a user) + if (!user) { + user = Candy.Core.getUser(); + } + links.remove(); + var menulinks = this.getMenuLinks(roomJid, user, elem), id, clickHandler = function(roomJid, user) { + return function(event) { + event.data.callback(event, roomJid, user); + $("#context-menu").hide(); + }; + }; + for (id in menulinks) { + if (menulinks.hasOwnProperty(id)) { + var link = menulinks[id], html = Mustache.to_html(Candy.View.Template.Chat.Context.menulinks, { + roomId: roomId, + "class": link["class"], + id: id, + label: link.label + }); + $("ul", menu).append(html); + $("#context-menu-" + id).bind("click", link, clickHandler(roomJid, user)); + } + } + // if `id` is set the menu is not empty + if (id) { + var pos = elem.offset(), posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(menu, pos.left), posTop = Candy.Util.getPosTopAccordingToWindowBounds(menu, pos.top); + menu.css({ + left: posLeft.px, + top: posTop.px + }).removeClass("left-top left-bottom right-top right-bottom").addClass(posLeft.backgroundPositionAlignment + "-" + posTop.backgroundPositionAlignment).fadeIn("fast"); + /** Event: candy:view.roster.after-context-menu * After context menu display * * Parameters: @@ -3763,17 +3513,15 @@ Candy.View.Pane = (function(self, $) { * (Candy.Core.ChatUser) user - User * (jQuery.Element) element - Menu element */ - $(Candy).triggerHandler('candy:view.roster.after-context-menu', { - 'roomJid' : roomJid, - 'user' : user, - 'element': menu - }); - - return true; - } - }, - - /** Function: getMenuLinks + $(Candy).triggerHandler("candy:view.roster.after-context-menu", { + roomJid: roomJid, + user: user, + element: menu + }); + return true; + } + }, + /** Function: getMenuLinks * Extends with menu links gathered from candy:view.roster.contextmenu * * Parameters: @@ -3787,17 +3535,15 @@ Candy.View.Pane = (function(self, $) { * Returns: * (Object) - object containing the extended menulinks. */ - getMenuLinks: function(roomJid, user, elem) { - var menulinks, id; - - var evtData = { - 'roomJid' : roomJid, - 'user' : user, - 'elem': elem, - 'menulinks': this.initialMenuLinks(elem) - }; - - /** Event: candy:view.roster.context-menu + getMenuLinks: function(roomJid, user, elem) { + var menulinks, id; + var evtData = { + roomJid: roomJid, + user: user, + elem: elem, + menulinks: this.initialMenuLinks(elem) + }; + /** Event: candy:view.roster.context-menu * Modify existing menu links (add links) * * In order to modify the links you need to change the object passed with an additional @@ -3808,19 +3554,16 @@ Candy.View.Pane = (function(self, $) { * (Candy.Core.ChatUser) user - User * (jQuery.Element) elem - Parent element of the context menu */ - $(Candy).triggerHandler('candy:view.roster.context-menu', evtData); - - menulinks = evtData.menulinks; - - for(id in menulinks) { - if(menulinks.hasOwnProperty(id) && menulinks[id].requiredPermission !== undefined && !menulinks[id].requiredPermission(user, self.Room.getUser(roomJid), elem)) { - delete menulinks[id]; - } - } - return menulinks; - }, - - /** Function: initialMenuLinks + $(Candy).triggerHandler("candy:view.roster.context-menu", evtData); + menulinks = evtData.menulinks; + for (id in menulinks) { + if (menulinks.hasOwnProperty(id) && menulinks[id].requiredPermission !== undefined && !menulinks[id].requiredPermission(user, self.Room.getUser(roomJid), elem)) { + delete menulinks[id]; + } + } + return menulinks; + }, + /** Function: initialMenuLinks * Returns initial menulinks. The following are initial: * * - Private Chat @@ -3833,99 +3576,98 @@ Candy.View.Pane = (function(self, $) { * Returns: * (Object) - object containing those menulinks */ - initialMenuLinks: function() { - return { - 'private': { - requiredPermission: function(user, me) { - return me.getNick() !== user.getNick() && Candy.Core.getRoom(Candy.View.getCurrent().roomJid) && !Candy.Core.getUser().isInPrivacyList('ignore', user.getJid()); - }, - 'class' : 'private', - 'label' : $.i18n._('privateActionLabel'), - 'callback' : function(e, roomJid, user) { - $('#user-' + Candy.Util.jidToId(roomJid) + '-' + Candy.Util.jidToId(user.getJid())).click(); - } - }, - 'ignore': { - requiredPermission: function(user, me) { - return me.getNick() !== user.getNick() && !Candy.Core.getUser().isInPrivacyList('ignore', user.getJid()); - }, - 'class' : 'ignore', - 'label' : $.i18n._('ignoreActionLabel'), - 'callback' : function(e, roomJid, user) { - Candy.View.Pane.Room.ignoreUser(roomJid, user.getJid()); - } - }, - 'unignore': { - requiredPermission: function(user, me) { - return me.getNick() !== user.getNick() && Candy.Core.getUser().isInPrivacyList('ignore', user.getJid()); - }, - 'class' : 'unignore', - 'label' : $.i18n._('unignoreActionLabel'), - 'callback' : function(e, roomJid, user) { - Candy.View.Pane.Room.unignoreUser(roomJid, user.getJid()); - } - }, - 'kick': { - requiredPermission: function(user, me) { - return me.getNick() !== user.getNick() && me.isModerator() && !user.isModerator(); - }, - 'class' : 'kick', - 'label' : $.i18n._('kickActionLabel'), - 'callback' : function(e, roomJid, user) { - self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm, { - _label: $.i18n._('reason'), - _submit: $.i18n._('kickActionLabel') - }), true); - $('#context-modal-field').focus(); - $('#context-modal-form').submit(function() { - Candy.Core.Action.Jabber.Room.Admin.UserAction(roomJid, user.getJid(), 'kick', $('#context-modal-field').val()); - self.Chat.Modal.hide(); - return false; // stop propagation & preventDefault, as otherwise you get disconnected (wtf?) - }); - } - }, - 'ban': { - requiredPermission: function(user, me) { - return me.getNick() !== user.getNick() && me.isModerator() && !user.isModerator(); - }, - 'class' : 'ban', - 'label' : $.i18n._('banActionLabel'), - 'callback' : function(e, roomJid, user) { - self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm, { - _label: $.i18n._('reason'), - _submit: $.i18n._('banActionLabel') - }), true); - $('#context-modal-field').focus(); - $('#context-modal-form').submit(function() { - Candy.Core.Action.Jabber.Room.Admin.UserAction(roomJid, user.getJid(), 'ban', $('#context-modal-field').val()); - self.Chat.Modal.hide(); - return false; // stop propagation & preventDefault, as otherwise you get disconnected (wtf?) - }); - } - }, - 'subject': { - requiredPermission: function(user, me) { - return me.getNick() === user.getNick() && me.isModerator(); - }, - 'class': 'subject', - 'label' : $.i18n._('setSubjectActionLabel'), - 'callback': function(e, roomJid) { - self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm, { - _label: $.i18n._('subject'), - _submit: $.i18n._('setSubjectActionLabel') - }), true); - $('#context-modal-field').focus(); - $('#context-modal-form').submit(function(e) { - Candy.Core.Action.Jabber.Room.Admin.SetSubject(roomJid, $('#context-modal-field').val()); - self.Chat.Modal.hide(); - e.preventDefault(); - }); - } - } - }; - }, - - /** Function: showEmoticonsMenu + initialMenuLinks: function() { + return { + "private": { + requiredPermission: function(user, me) { + return me.getNick() !== user.getNick() && Candy.Core.getRoom(Candy.View.getCurrent().roomJid) && !Candy.Core.getUser().isInPrivacyList("ignore", user.getJid()); + }, + "class": "private", + label: $.i18n._("privateActionLabel"), + callback: function(e, roomJid, user) { + $("#user-" + Candy.Util.jidToId(roomJid) + "-" + Candy.Util.jidToId(user.getJid())).click(); + } + }, + ignore: { + requiredPermission: function(user, me) { + return me.getNick() !== user.getNick() && !Candy.Core.getUser().isInPrivacyList("ignore", user.getJid()); + }, + "class": "ignore", + label: $.i18n._("ignoreActionLabel"), + callback: function(e, roomJid, user) { + Candy.View.Pane.Room.ignoreUser(roomJid, user.getJid()); + } + }, + unignore: { + requiredPermission: function(user, me) { + return me.getNick() !== user.getNick() && Candy.Core.getUser().isInPrivacyList("ignore", user.getJid()); + }, + "class": "unignore", + label: $.i18n._("unignoreActionLabel"), + callback: function(e, roomJid, user) { + Candy.View.Pane.Room.unignoreUser(roomJid, user.getJid()); + } + }, + kick: { + requiredPermission: function(user, me) { + return me.getNick() !== user.getNick() && me.isModerator() && !user.isModerator(); + }, + "class": "kick", + label: $.i18n._("kickActionLabel"), + callback: function(e, roomJid, user) { + self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm, { + _label: $.i18n._("reason"), + _submit: $.i18n._("kickActionLabel") + }), true); + $("#context-modal-field").focus(); + $("#context-modal-form").submit(function() { + Candy.Core.Action.Jabber.Room.Admin.UserAction(roomJid, user.getJid(), "kick", $("#context-modal-field").val()); + self.Chat.Modal.hide(); + return false; + }); + } + }, + ban: { + requiredPermission: function(user, me) { + return me.getNick() !== user.getNick() && me.isModerator() && !user.isModerator(); + }, + "class": "ban", + label: $.i18n._("banActionLabel"), + callback: function(e, roomJid, user) { + self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm, { + _label: $.i18n._("reason"), + _submit: $.i18n._("banActionLabel") + }), true); + $("#context-modal-field").focus(); + $("#context-modal-form").submit(function() { + Candy.Core.Action.Jabber.Room.Admin.UserAction(roomJid, user.getJid(), "ban", $("#context-modal-field").val()); + self.Chat.Modal.hide(); + return false; + }); + } + }, + subject: { + requiredPermission: function(user, me) { + return me.getNick() === user.getNick() && me.isModerator(); + }, + "class": "subject", + label: $.i18n._("setSubjectActionLabel"), + callback: function(e, roomJid) { + self.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm, { + _label: $.i18n._("subject"), + _submit: $.i18n._("setSubjectActionLabel") + }), true); + $("#context-modal-field").focus(); + $("#context-modal-form").submit(function(e) { + Candy.Core.Action.Jabber.Room.Admin.SetSubject(roomJid, $("#context-modal-field").val()); + self.Chat.Modal.hide(); + e.preventDefault(); + }); + } + } + }; + }, + /** Function: showEmoticonsMenu * Shows the special emoticons menu * * Parameters: @@ -3934,46 +3676,32 @@ Candy.View.Pane = (function(self, $) { * Returns: * (Boolean) - true */ - showEmoticonsMenu: function(elem) { - elem = $(elem); - var pos = elem.offset(), - menu = $('#context-menu'), - content = $('ul', menu), - emoticons = '', - i; - - $('#tooltip').hide(); - - for(i = Candy.Util.Parser.emoticons.length-1; i >= 0; i--) { - emoticons = '' + Candy.Util.Parser.emoticons[i].plain + '' + emoticons; - } - content.html('
  • ' + emoticons + '
  • '); - content.find('img').click(function() { - var input = Candy.View.Pane.Room.getPane(Candy.View.getCurrent().roomJid, '.message-form').children('.field'), - value = input.val(), - emoticon = $(this).attr('alt') + ' '; - input.val(value ? value + ' ' + emoticon : emoticon).focus(); - }); - - var posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(menu, pos.left), - posTop = Candy.Util.getPosTopAccordingToWindowBounds(menu, pos.top); - - menu - .css({'left': posLeft.px, 'top': posTop.px}) - .removeClass('left-top left-bottom right-top right-bottom') - .addClass(posLeft.backgroundPositionAlignment + '-' + posTop.backgroundPositionAlignment) - .fadeIn('fast'); - - return true; - } - } - }; - - /** Class: Candy.View.Pane.Room + showEmoticonsMenu: function(elem) { + elem = $(elem); + var pos = elem.offset(), menu = $("#context-menu"), content = $("ul", menu), emoticons = "", i; + $("#tooltip").hide(); + for (i = Candy.Util.Parser.emoticons.length - 1; i >= 0; i--) { + emoticons = '' + Candy.Util.Parser.emoticons[i].plain + '' + emoticons; + } + content.html('
  • ' + emoticons + "
  • "); + content.find("img").click(function() { + var input = Candy.View.Pane.Room.getPane(Candy.View.getCurrent().roomJid, ".message-form").children(".field"), value = input.val(), emoticon = $(this).attr("alt") + " "; + input.val(value ? value + " " + emoticon : emoticon).focus(); + }); + var posLeft = Candy.Util.getPosLeftAccordingToWindowBounds(menu, pos.left), posTop = Candy.Util.getPosTopAccordingToWindowBounds(menu, pos.top); + menu.css({ + left: posLeft.px, + top: posTop.px + }).removeClass("left-top left-bottom right-top right-bottom").addClass(posLeft.backgroundPositionAlignment + "-" + posTop.backgroundPositionAlignment).fadeIn("fast"); + return true; + } + } + }; + /** Class: Candy.View.Pane.Room * Everything which belongs to room view things belongs here. */ - self.Room = { - /** Function: init + self.Room = { + /** Function: init * Initialize a new room and inserts the room html into the DOM * * Parameters: @@ -3992,35 +3720,40 @@ Candy.View.Pane = (function(self, $) { * Returns: * (String) - the room id of the element created. */ - init: function(roomJid, roomName, roomType) { - roomType = roomType || 'groupchat'; - // First room, show sound control - if(Candy.Util.isEmptyObject(self.Chat.rooms)) { - self.Chat.Toolbar.show(); - } - roomJid = Candy.Util.unescapeJid(roomJid); - var roomId = Candy.Util.jidToId(roomJid); - self.Chat.rooms[roomJid] = {id: roomId, usercount: 0, name: roomName, type: roomType, messageCount: 0, scrollPosition: -1}; - - $('#chat-rooms').append(Mustache.to_html(Candy.View.Template.Room.pane, { - roomId: roomId, - roomJid: roomJid, - roomType: roomType, - form: { - _messageSubmit: $.i18n._('messageSubmit') - }, - roster: { - _userOnline: $.i18n._('userOnline') - } - }, { - roster: Candy.View.Template.Roster.pane, - messages: Candy.View.Template.Message.pane, - form: Candy.View.Template.Room.form - })); - self.Chat.addTab(roomJid, roomName, roomType); - self.Room.getPane(roomJid, '.message-form').submit(self.Message.submit); - - /** Event: candy:view.room.after-add + init: function(roomJid, roomName, roomType) { + roomType = roomType || "groupchat"; + // First room, show sound control + if (Candy.Util.isEmptyObject(self.Chat.rooms)) { + self.Chat.Toolbar.show(); + } + roomJid = Candy.Util.unescapeJid(roomJid); + var roomId = Candy.Util.jidToId(roomJid); + self.Chat.rooms[roomJid] = { + id: roomId, + usercount: 0, + name: roomName, + type: roomType, + messageCount: 0, + scrollPosition: -1 + }; + $("#chat-rooms").append(Mustache.to_html(Candy.View.Template.Room.pane, { + roomId: roomId, + roomJid: roomJid, + roomType: roomType, + form: { + _messageSubmit: $.i18n._("messageSubmit") + }, + roster: { + _userOnline: $.i18n._("userOnline") + } + }, { + roster: Candy.View.Template.Roster.pane, + messages: Candy.View.Template.Message.pane, + form: Candy.View.Template.Room.form + })); + self.Chat.addTab(roomJid, roomName, roomType); + self.Room.getPane(roomJid, ".message-form").submit(self.Message.submit); + /** Event: candy:view.room.after-add * After initialising a room * * Parameters: @@ -4028,16 +3761,14 @@ Candy.View.Pane = (function(self, $) { * (String) type - Room Type * (jQuery.Element) element - Room element */ - $(Candy).triggerHandler('candy:view.room.after-add', { - 'roomJid': roomJid, - 'type': roomType, - 'element': self.Room.getPane(roomJid) - }); - - return roomId; - }, - - /** Function: show + $(Candy).triggerHandler("candy:view.room.after-add", { + roomJid: roomJid, + type: roomType, + element: self.Room.getPane(roomJid) + }); + return roomId; + }, + /** Function: show * Show a specific room and hides the other rooms (if there are any) * * Parameters: @@ -4047,48 +3778,44 @@ Candy.View.Pane = (function(self, $) { * candy:view.room.after-show using {roomJid, element} * candy:view.room.after-hide using {roomJid, element} */ - show: function(roomJid) { - var roomId = self.Chat.rooms[roomJid].id, - evtData; - - $('.room-pane').each(function() { - var elem = $(this); - evtData = {'roomJid': roomJid, 'element' : elem}; - - if(elem.attr('id') === ('chat-room-' + roomId)) { - elem.show(); - Candy.View.getCurrent().roomJid = roomJid; - self.Chat.setActiveTab(roomJid); - self.Chat.Toolbar.update(roomJid); - self.Chat.clearUnreadMessages(roomJid); - self.Room.setFocusToForm(roomJid); - self.Room.scrollToBottom(roomJid); - - /** Event: candy:view.room.after-show + show: function(roomJid) { + var roomId = self.Chat.rooms[roomJid].id, evtData; + $(".room-pane").each(function() { + var elem = $(this); + evtData = { + roomJid: roomJid, + element: elem + }; + if (elem.attr("id") === "chat-room-" + roomId) { + elem.show(); + Candy.View.getCurrent().roomJid = roomJid; + self.Chat.setActiveTab(roomJid); + self.Chat.Toolbar.update(roomJid); + self.Chat.clearUnreadMessages(roomJid); + self.Room.setFocusToForm(roomJid); + self.Room.scrollToBottom(roomJid); + /** Event: candy:view.room.after-show * After showing a room * * Parameters: * (String) roomJid - Room JID * (jQuery.Element) element - Room element */ - $(Candy).triggerHandler('candy:view.room.after-show', evtData); - - } else { - elem.hide(); - - /** Event: candy:view.room.after-hide + $(Candy).triggerHandler("candy:view.room.after-show", evtData); + } else { + elem.hide(); + /** Event: candy:view.room.after-hide * After hiding a room * * Parameters: * (String) roomJid - Room JID * (jQuery.Element) element - Room element */ - $(Candy).triggerHandler('candy:view.room.after-hide', evtData); - } - }); - }, - - /** Function: setSubject + $(Candy).triggerHandler("candy:view.room.after-hide", evtData); + } + }); + }, + /** Function: setSubject * Called when someone changes the subject in the channel * * Triggers: @@ -4098,18 +3825,17 @@ Candy.View.Pane = (function(self, $) { * (String) roomJid - Room Jid * (String) subject - The new subject */ - setSubject: function(roomJid, subject) { - subject = Candy.Util.Parser.linkify(Candy.Util.Parser.escape(subject)); - var html = Mustache.to_html(Candy.View.Template.Room.subject, { - subject: subject, - roomName: self.Chat.rooms[roomJid].name, - _roomSubject: $.i18n._('roomSubject'), - time: Candy.Util.localizedTime(new Date().toGMTString()) - }); - self.Room.appendToMessagePane(roomJid, html); - self.Room.scrollToBottom(roomJid); - - /** Event: candy:view.room.after-subject-change + setSubject: function(roomJid, subject) { + subject = Candy.Util.Parser.linkify(Candy.Util.Parser.escape(subject)); + var html = Mustache.to_html(Candy.View.Template.Room.subject, { + subject: subject, + roomName: self.Chat.rooms[roomJid].name, + _roomSubject: $.i18n._("roomSubject"), + time: Candy.Util.localizedTime(new Date().toGMTString()) + }); + self.Room.appendToMessagePane(roomJid, html); + self.Room.scrollToBottom(roomJid); + /** Event: candy:view.room.after-subject-change * After changing the subject of a room * * Parameters: @@ -4117,14 +3843,13 @@ Candy.View.Pane = (function(self, $) { * (jQuery.Element) element - Room element * (String) subject - New subject */ - $(Candy).triggerHandler('candy:view.room.after-subject-change', { - 'roomJid': roomJid, - 'element' : self.Room.getPane(roomJid), - 'subject' : subject - }); - }, - - /** Function: close + $(Candy).triggerHandler("candy:view.room.after-subject-change", { + roomJid: roomJid, + element: self.Room.getPane(roomJid), + subject: subject + }); + }, + /** Function: close * Close a room and remove everything in the DOM belonging to this room. * * NOTICE: There's a rendering bug in Opera when all rooms have been closed. @@ -4136,52 +3861,48 @@ Candy.View.Pane = (function(self, $) { * Parameters: * (String) roomJid - Room to close */ - close: function(roomJid) { - self.Chat.removeTab(roomJid); - self.Window.clearUnreadMessages(); - - /* TODO: + close: function(roomJid) { + self.Chat.removeTab(roomJid); + self.Window.clearUnreadMessages(); + /* TODO: There's a rendering bug in Opera which doesn't redraw (remove) the message form. Only a cosmetical issue (when all tabs are closed) but it's annoying... This happens when form has no focus too. Maybe it's because of CSS positioning. */ - self.Room.getPane(roomJid).remove(); - var openRooms = $('#chat-rooms').children(); - if(Candy.View.getCurrent().roomJid === roomJid) { - Candy.View.getCurrent().roomJid = null; - if(openRooms.length === 0) { - self.Chat.allTabsClosed(); - } else { - self.Room.show(openRooms.last().attr('data-roomjid')); - } - } - delete self.Chat.rooms[roomJid]; - - /** Event: candy:view.room.after-close + self.Room.getPane(roomJid).remove(); + var openRooms = $("#chat-rooms").children(); + if (Candy.View.getCurrent().roomJid === roomJid) { + Candy.View.getCurrent().roomJid = null; + if (openRooms.length === 0) { + self.Chat.allTabsClosed(); + } else { + self.Room.show(openRooms.last().attr("data-roomjid")); + } + } + delete self.Chat.rooms[roomJid]; + /** Event: candy:view.room.after-close * After closing a room * * Parameters: * (String) roomJid - Room JID */ - $(Candy).triggerHandler('candy:view.room.after-close', { - 'roomJid' : roomJid - }); - }, - - /** Function: appendToMessagePane + $(Candy).triggerHandler("candy:view.room.after-close", { + roomJid: roomJid + }); + }, + /** Function: appendToMessagePane * Append a new message to the message pane. * * Parameters: * (String) roomJid - Room JID * (String) html - rendered message html */ - appendToMessagePane: function(roomJid, html) { - self.Room.getPane(roomJid, '.message-pane').append(html); - self.Chat.rooms[roomJid].messageCount++; - self.Room.sliceMessagePane(roomJid); - }, - - /** Function: sliceMessagePane + appendToMessagePane: function(roomJid, html) { + self.Room.getPane(roomJid, ".message-pane").append(html); + self.Chat.rooms[roomJid].messageCount++; + self.Room.sliceMessagePane(roomJid); + }, + /** Function: sliceMessagePane * Slices the message pane after the max amount of messages specified in the Candy View options (limit setting). * * This is done to hopefully prevent browsers from getting slow after a certain amount of messages in the DOM. @@ -4191,18 +3912,17 @@ Candy.View.Pane = (function(self, $) { * Parameters: * (String) roomJid - Room JID */ - sliceMessagePane: function(roomJid) { - // Only clean if autoscroll is enabled - if(self.Window.autoscroll) { - var options = Candy.View.getOptions().messages; - if(self.Chat.rooms[roomJid].messageCount > options.limit) { - self.Room.getPane(roomJid, '.message-pane').children().slice(0, options.remove).remove(); - self.Chat.rooms[roomJid].messageCount -= options.remove; - } - } - }, - - /** Function: scrollToBottom + sliceMessagePane: function(roomJid) { + // Only clean if autoscroll is enabled + if (self.Window.autoscroll) { + var options = Candy.View.getOptions().messages; + if (self.Chat.rooms[roomJid].messageCount > options.limit) { + self.Room.getPane(roomJid, ".message-pane").children().slice(0, options.remove).remove(); + self.Chat.rooms[roomJid].messageCount -= options.remove; + } + } + }, + /** Function: scrollToBottom * Scroll to bottom wrapper for to be able to disable it by overwriting the function. * * Parameters: @@ -4211,57 +3931,51 @@ Candy.View.Pane = (function(self, $) { * Uses: * - */ - scrollToBottom: function(roomJid) { - self.Room.onScrollToBottom(roomJid); - }, - - /** Function: onScrollToBottom + scrollToBottom: function(roomJid) { + self.Room.onScrollToBottom(roomJid); + }, + /** Function: onScrollToBottom * Scrolls to the latest message received/sent. * * Parameters: * (String) roomJid - Room JID */ - onScrollToBottom: function(roomJid) { - var messagePane = self.Room.getPane(roomJid, '.message-pane-wrapper'); - messagePane.scrollTop(messagePane.prop('scrollHeight')); - }, - - /** Function: onScrollToStoredPosition + onScrollToBottom: function(roomJid) { + var messagePane = self.Room.getPane(roomJid, ".message-pane-wrapper"); + messagePane.scrollTop(messagePane.prop("scrollHeight")); + }, + /** Function: onScrollToStoredPosition * When autoscroll is off, the position where the scrollbar is has to be stored for each room, because it otherwise * goes to the top in the message window. * * Parameters: * (String) roomJid - Room JID */ - onScrollToStoredPosition: function(roomJid) { - // This should only apply when entering a room... - // ... therefore we set scrollPosition to -1 after execution. - if(self.Chat.rooms[roomJid].scrollPosition > -1) { - var messagePane = self.Room.getPane(roomJid, '.message-pane-wrapper'); - messagePane.scrollTop(self.Chat.rooms[roomJid].scrollPosition); - self.Chat.rooms[roomJid].scrollPosition = -1; - } - }, - - /** Function: setFocusToForm + onScrollToStoredPosition: function(roomJid) { + // This should only apply when entering a room... + // ... therefore we set scrollPosition to -1 after execution. + if (self.Chat.rooms[roomJid].scrollPosition > -1) { + var messagePane = self.Room.getPane(roomJid, ".message-pane-wrapper"); + messagePane.scrollTop(self.Chat.rooms[roomJid].scrollPosition); + self.Chat.rooms[roomJid].scrollPosition = -1; + } + }, + /** Function: setFocusToForm * Set focus to the message input field within the message form. * * Parameters: * (String) roomJid - Room JID */ - setFocusToForm: function(roomJid) { - var pane = self.Room.getPane(roomJid, '.message-form'); - if (pane) { - // IE8 will fail maybe, because the field isn't there yet. - try { - pane.children('.field')[0].focus(); - } catch(e) { - // fail silently - } - } - }, - - /** Function: setUser + setFocusToForm: function(roomJid) { + var pane = self.Room.getPane(roomJid, ".message-form"); + if (pane) { + // IE8 will fail maybe, because the field isn't there yet. + try { + pane.children(".field")[0].focus(); + } catch (e) {} + } + }, + /** Function: setUser * Sets or updates the current user in the specified room (called by ) and set specific informations * (roles and affiliations) on the room tab (chat-pane). * @@ -4269,27 +3983,24 @@ Candy.View.Pane = (function(self, $) { * (String) roomJid - Room in which the user is set to. * (Candy.Core.ChatUser) user - The user */ - setUser: function(roomJid, user) { - self.Chat.rooms[roomJid].user = user; - var roomPane = self.Room.getPane(roomJid), - chatPane = $('#chat-pane'); - - roomPane.attr('data-userjid', user.getJid()); - // Set classes based on user role / affiliation - if(user.isModerator()) { - if (user.getRole() === user.ROLE_MODERATOR) { - chatPane.addClass('role-moderator'); - } - if (user.getAffiliation() === user.AFFILIATION_OWNER) { - chatPane.addClass('affiliation-owner'); - } - } else { - chatPane.removeClass('role-moderator affiliation-owner'); - } - self.Chat.Context.init(); - }, - - /** Function: getUser + setUser: function(roomJid, user) { + self.Chat.rooms[roomJid].user = user; + var roomPane = self.Room.getPane(roomJid), chatPane = $("#chat-pane"); + roomPane.attr("data-userjid", user.getJid()); + // Set classes based on user role / affiliation + if (user.isModerator()) { + if (user.getRole() === user.ROLE_MODERATOR) { + chatPane.addClass("role-moderator"); + } + if (user.getAffiliation() === user.AFFILIATION_OWNER) { + chatPane.addClass("affiliation-owner"); + } + } else { + chatPane.removeClass("role-moderator affiliation-owner"); + } + self.Chat.Context.init(); + }, + /** Function: getUser * Get the current user in the room specified with the jid * * Parameters: @@ -4298,108 +4009,101 @@ Candy.View.Pane = (function(self, $) { * Returns: * (Candy.Core.ChatUser) - user */ - getUser: function(roomJid) { - return self.Chat.rooms[roomJid].user; - }, - - /** Function: ignoreUser + getUser: function(roomJid) { + return self.Chat.rooms[roomJid].user; + }, + /** Function: ignoreUser * Ignore specified user and add the ignore icon to the roster item of the user * * Parameters: * (String) roomJid - Room in which the user should be ignored * (String) userJid - User which should be ignored */ - ignoreUser: function(roomJid, userJid) { - Candy.Core.Action.Jabber.Room.IgnoreUnignore(userJid); - Candy.View.Pane.Room.addIgnoreIcon(roomJid, userJid); - }, - - /** Function: unignoreUser + ignoreUser: function(roomJid, userJid) { + Candy.Core.Action.Jabber.Room.IgnoreUnignore(userJid); + Candy.View.Pane.Room.addIgnoreIcon(roomJid, userJid); + }, + /** Function: unignoreUser * Unignore an ignored user and remove the ignore icon of the roster item. * * Parameters: * (String) roomJid - Room in which the user should be unignored * (String) userJid - User which should be unignored */ - unignoreUser: function(roomJid, userJid) { - Candy.Core.Action.Jabber.Room.IgnoreUnignore(userJid); - Candy.View.Pane.Room.removeIgnoreIcon(roomJid, userJid); - }, - - /** Function: addIgnoreIcon + unignoreUser: function(roomJid, userJid) { + Candy.Core.Action.Jabber.Room.IgnoreUnignore(userJid); + Candy.View.Pane.Room.removeIgnoreIcon(roomJid, userJid); + }, + /** Function: addIgnoreIcon * Add the ignore icon to the roster item of the specified user * * Parameters: * (String) roomJid - Room in which the roster item should be updated * (String) userJid - User of which the roster item should be updated */ - addIgnoreIcon: function(roomJid, userJid) { - if (Candy.View.Pane.Chat.rooms[userJid]) { - $('#user-' + Candy.View.Pane.Chat.rooms[userJid].id + '-' + Candy.Util.jidToId(userJid)).addClass('status-ignored'); - } - if (Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)]) { - $('#user-' + Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)].id + '-' + Candy.Util.jidToId(userJid)).addClass('status-ignored'); - } - }, - - /** Function: removeIgnoreIcon + addIgnoreIcon: function(roomJid, userJid) { + if (Candy.View.Pane.Chat.rooms[userJid]) { + $("#user-" + Candy.View.Pane.Chat.rooms[userJid].id + "-" + Candy.Util.jidToId(userJid)).addClass("status-ignored"); + } + if (Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)]) { + $("#user-" + Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)].id + "-" + Candy.Util.jidToId(userJid)).addClass("status-ignored"); + } + }, + /** Function: removeIgnoreIcon * Remove the ignore icon to the roster item of the specified user * * Parameters: * (String) roomJid - Room in which the roster item should be updated * (String) userJid - User of which the roster item should be updated */ - removeIgnoreIcon: function(roomJid, userJid) { - if (Candy.View.Pane.Chat.rooms[userJid]) { - $('#user-' + Candy.View.Pane.Chat.rooms[userJid].id + '-' + Candy.Util.jidToId(userJid)).removeClass('status-ignored'); - } - if (Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)]) { - $('#user-' + Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)].id + '-' + Candy.Util.jidToId(userJid)).removeClass('status-ignored'); - } - }, - - /** Function: getPane + removeIgnoreIcon: function(roomJid, userJid) { + if (Candy.View.Pane.Chat.rooms[userJid]) { + $("#user-" + Candy.View.Pane.Chat.rooms[userJid].id + "-" + Candy.Util.jidToId(userJid)).removeClass("status-ignored"); + } + if (Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)]) { + $("#user-" + Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(roomJid)].id + "-" + Candy.Util.jidToId(userJid)).removeClass("status-ignored"); + } + }, + /** Function: getPane * Get the chat room pane or a subPane of it (if subPane is specified) * * Parameters: * (String) roomJid - Room in which the pane lies * (String) subPane - Sub pane of the chat room pane if needed [optional] */ - getPane: function(roomJid, subPane) { - if (self.Chat.rooms[roomJid]) { - if(subPane) { - if(self.Chat.rooms[roomJid]['pane-' + subPane]) { - return self.Chat.rooms[roomJid]['pane-' + subPane]; - } else { - self.Chat.rooms[roomJid]['pane-' + subPane] = $('#chat-room-' + self.Chat.rooms[roomJid].id).find(subPane); - return self.Chat.rooms[roomJid]['pane-' + subPane]; - } - } else { - return $('#chat-room-' + self.Chat.rooms[roomJid].id); - } - } - }, - - /** Function: changeDataUserJidIfUserIsMe + getPane: function(roomJid, subPane) { + if (self.Chat.rooms[roomJid]) { + if (subPane) { + if (self.Chat.rooms[roomJid]["pane-" + subPane]) { + return self.Chat.rooms[roomJid]["pane-" + subPane]; + } else { + self.Chat.rooms[roomJid]["pane-" + subPane] = $("#chat-room-" + self.Chat.rooms[roomJid].id).find(subPane); + return self.Chat.rooms[roomJid]["pane-" + subPane]; + } + } else { + return $("#chat-room-" + self.Chat.rooms[roomJid].id); + } + } + }, + /** Function: changeDataUserJidIfUserIsMe * Changes the room's data-userjid attribute if the specified user is the current user. * * Parameters: * (String) roomId - Id of the room * (Candy.Core.ChatUser) user - User */ - changeDataUserJidIfUserIsMe: function(roomId, user) { - if (user.getNick() === Candy.Core.getUser().getNick()) { - var roomElement = $('#chat-room-' + roomId); - roomElement.attr('data-userjid', Strophe.getBareJidFromJid(roomElement.attr('data-userjid')) + '/' + user.getNick()); - } - } - }; - - /** Class: Candy.View.Pane.PrivateRoom + changeDataUserJidIfUserIsMe: function(roomId, user) { + if (user.getNick() === Candy.Core.getUser().getNick()) { + var roomElement = $("#chat-room-" + roomId); + roomElement.attr("data-userjid", Strophe.getBareJidFromJid(roomElement.attr("data-userjid")) + "/" + user.getNick()); + } + } + }; + /** Class: Candy.View.Pane.PrivateRoom * Private room handling */ - self.PrivateRoom = { - /** Function: open + self.PrivateRoom = { + /** Function: open * Opens a new private room * * Parameters: @@ -4413,31 +4117,26 @@ Candy.View.Pane = (function(self, $) { * Triggers: * candy:view.private-room.after-open using {roomJid, type, element} */ - open: function(roomJid, roomName, switchToRoom, isNoConferenceRoomJid) { - var user = isNoConferenceRoomJid ? Candy.Core.getUser() : self.Room.getUser(Strophe.getBareJidFromJid(roomJid)); - // if target user is in privacy list, don't open the private chat. - if (Candy.Core.getUser().isInPrivacyList('ignore', roomJid)) { - return false; - } - if(!self.Chat.rooms[roomJid]) { - self.Room.init(roomJid, roomName, 'chat'); - } - if(switchToRoom) { - self.Room.show(roomJid); - } - - self.Roster.update(roomJid, new Candy.Core.ChatUser(roomJid, roomName), 'join', user); - self.Roster.update(roomJid, user, 'join', user); - self.PrivateRoom.setStatus(roomJid, 'join'); - - - - // We can't track the presence of a user if it's not a conference jid - if(isNoConferenceRoomJid) { - self.Chat.infoMessage(roomJid, $.i18n._('presenceUnknownWarningSubject'), $.i18n._('presenceUnknownWarning')); - } - - /** Event: candy:view.private-room.after-open + open: function(roomJid, roomName, switchToRoom, isNoConferenceRoomJid) { + var user = isNoConferenceRoomJid ? Candy.Core.getUser() : self.Room.getUser(Strophe.getBareJidFromJid(roomJid)); + // if target user is in privacy list, don't open the private chat. + if (Candy.Core.getUser().isInPrivacyList("ignore", roomJid)) { + return false; + } + if (!self.Chat.rooms[roomJid]) { + self.Room.init(roomJid, roomName, "chat"); + } + if (switchToRoom) { + self.Room.show(roomJid); + } + self.Roster.update(roomJid, new Candy.Core.ChatUser(roomJid, roomName), "join", user); + self.Roster.update(roomJid, user, "join", user); + self.PrivateRoom.setStatus(roomJid, "join"); + // We can't track the presence of a user if it's not a conference jid + if (isNoConferenceRoomJid) { + self.Chat.infoMessage(roomJid, $.i18n._("presenceUnknownWarningSubject"), $.i18n._("presenceUnknownWarning")); + } + /** Event: candy:view.private-room.after-open * After opening a new private room * * Parameters: @@ -4445,103 +4144,85 @@ Candy.View.Pane = (function(self, $) { * (String) type - 'chat' * (jQuery.Element) element - User element */ - $(Candy).triggerHandler('candy:view.private-room.after-open', { - 'roomJid': roomJid, - 'type': 'chat', - 'element': self.Room.getPane(roomJid) - }); - }, - - /** Function: setStatus + $(Candy).triggerHandler("candy:view.private-room.after-open", { + roomJid: roomJid, + type: "chat", + element: self.Room.getPane(roomJid) + }); + }, + /** Function: setStatus * Set offline or online status for private rooms (when one of the participants leaves the room) * * Parameters: * (String) roomJid - Private room jid * (String) status - "leave"/"join" */ - setStatus: function(roomJid, status) { - var messageForm = self.Room.getPane(roomJid, '.message-form'); - if(status === 'join') { - self.Chat.getTab(roomJid).addClass('online').removeClass('offline'); - - messageForm.children('.field').removeAttr('disabled'); - messageForm.children('.submit').removeAttr('disabled'); - - self.Chat.getTab(roomJid); - } else if(status === 'leave') { - self.Chat.getTab(roomJid).addClass('offline').removeClass('online'); - - messageForm.children('.field').attr('disabled', true); - messageForm.children('.submit').attr('disabled', true); - } - }, - - /** Function: changeNick + setStatus: function(roomJid, status) { + var messageForm = self.Room.getPane(roomJid, ".message-form"); + if (status === "join") { + self.Chat.getTab(roomJid).addClass("online").removeClass("offline"); + messageForm.children(".field").removeAttr("disabled"); + messageForm.children(".submit").removeAttr("disabled"); + self.Chat.getTab(roomJid); + } else if (status === "leave") { + self.Chat.getTab(roomJid).addClass("offline").removeClass("online"); + messageForm.children(".field").attr("disabled", true); + messageForm.children(".submit").attr("disabled", true); + } + }, + /** Function: changeNick * Changes the nick for every private room opened with this roomJid. * * Parameters: * (String) roomJid - Public room jid * (Candy.Core.ChatUser) user - User which changes his nick */ - changeNick: function changeNick(roomJid, user) { - Candy.Core.log('[View:Pane:PrivateRoom] changeNick'); - - var previousPrivateRoomJid = roomJid + '/' + user.getPreviousNick(), - newPrivateRoomJid = roomJid + '/' + user.getNick(), - previousPrivateRoomId = Candy.Util.jidToId(previousPrivateRoomJid), - newPrivateRoomId = Candy.Util.jidToId(newPrivateRoomJid), - room = self.Chat.rooms[previousPrivateRoomJid], - roomElement, - roomTabElement; - - // it could happen that the new private room is already existing -> close it first. - // if this is not done, errors appear as two rooms would have the same id - if (self.Chat.rooms[newPrivateRoomJid]) { - self.Room.close(newPrivateRoomJid); - } - - if (room) { /* someone I talk with, changed nick */ - room.name = user.getNick(); - room.id = newPrivateRoomId; - - self.Chat.rooms[newPrivateRoomJid] = room; - delete self.Chat.rooms[previousPrivateRoomJid]; - - roomElement = $('#chat-room-' + previousPrivateRoomId); - if (roomElement) { - roomElement.attr('data-roomjid', newPrivateRoomJid); - roomElement.attr('id', 'chat-room-' + newPrivateRoomId); - - roomTabElement = $('#chat-tabs li[data-roomjid="' + previousPrivateRoomJid + '"]'); - roomTabElement.attr('data-roomjid', newPrivateRoomJid); - - /* TODO: The '@' is defined in the template. Somehow we should + changeNick: function changeNick(roomJid, user) { + Candy.Core.log("[View:Pane:PrivateRoom] changeNick"); + var previousPrivateRoomJid = roomJid + "/" + user.getPreviousNick(), newPrivateRoomJid = roomJid + "/" + user.getNick(), previousPrivateRoomId = Candy.Util.jidToId(previousPrivateRoomJid), newPrivateRoomId = Candy.Util.jidToId(newPrivateRoomJid), room = self.Chat.rooms[previousPrivateRoomJid], roomElement, roomTabElement; + // it could happen that the new private room is already existing -> close it first. + // if this is not done, errors appear as two rooms would have the same id + if (self.Chat.rooms[newPrivateRoomJid]) { + self.Room.close(newPrivateRoomJid); + } + if (room) { + /* someone I talk with, changed nick */ + room.name = user.getNick(); + room.id = newPrivateRoomId; + self.Chat.rooms[newPrivateRoomJid] = room; + delete self.Chat.rooms[previousPrivateRoomJid]; + roomElement = $("#chat-room-" + previousPrivateRoomId); + if (roomElement) { + roomElement.attr("data-roomjid", newPrivateRoomJid); + roomElement.attr("id", "chat-room-" + newPrivateRoomId); + roomTabElement = $('#chat-tabs li[data-roomjid="' + previousPrivateRoomJid + '"]'); + roomTabElement.attr("data-roomjid", newPrivateRoomJid); + /* TODO: The '@' is defined in the template. Somehow we should * extract both things into our CSS or do something else to prevent that. */ - roomTabElement.children('a.label').text('@' + user.getNick()); - - if (Candy.View.getCurrent().roomJid === previousPrivateRoomJid) { - Candy.View.getCurrent().roomJid = newPrivateRoomJid; - } - } - } else { /* I changed the nick */ - roomElement = $('.room-pane.roomtype-chat[data-userjid="' + previousPrivateRoomJid + '"]'); - if (roomElement.length) { - previousPrivateRoomId = Candy.Util.jidToId(roomElement.attr('data-roomjid')); - roomElement.attr('data-userjid', newPrivateRoomJid); - } - } - if (roomElement && roomElement.length) { - self.Roster.changeNick(previousPrivateRoomId, user); - } - } - }; - - /** Class Candy.View.Pane.Roster + roomTabElement.children("a.label").text("@" + user.getNick()); + if (Candy.View.getCurrent().roomJid === previousPrivateRoomJid) { + Candy.View.getCurrent().roomJid = newPrivateRoomJid; + } + } + } else { + /* I changed the nick */ + roomElement = $('.room-pane.roomtype-chat[data-userjid="' + previousPrivateRoomJid + '"]'); + if (roomElement.length) { + previousPrivateRoomId = Candy.Util.jidToId(roomElement.attr("data-roomjid")); + roomElement.attr("data-userjid", newPrivateRoomJid); + } + } + if (roomElement && roomElement.length) { + self.Roster.changeNick(previousPrivateRoomId, user); + } + } + }; + /** Class Candy.View.Pane.Roster * Handles everyhing regarding roster updates. */ - self.Roster = { - /** Function: update + self.Roster = { + /** Function: update * Called by to update the roster if needed. * Adds/removes users from the roster list or updates informations on their items (roles, affiliations etc.) * @@ -4557,14 +4238,10 @@ Candy.View.Pane = (function(self, $) { * candy:view.roster.before-update using {roomJid, user, action, element} * candy:view.roster.after-update using {roomJid, user, action, element} */ - update: function(roomJid, user, action, currentUser) { - Candy.Core.log('[View:Pane:Roster] ' + action); - var roomId = self.Chat.rooms[roomJid].id, - userId = Candy.Util.jidToId(user.getJid()), - usercountDiff = -1, - userElem = $('#user-' + roomId + '-' + userId); - - /** Event: candy:view.roster.before-update + update: function(roomJid, user, action, currentUser) { + Candy.Core.log("[View:Pane:Roster] " + action); + var roomId = self.Chat.rooms[roomJid].id, userId = Candy.Util.jidToId(user.getJid()), usercountDiff = -1, userElem = $("#user-" + roomId + "-" + userId); + /** Event: candy:view.roster.before-update * Before updating the roster of a room * * Parameters: @@ -4573,117 +4250,101 @@ Candy.View.Pane = (function(self, $) { * (String) action - [join, leave, kick, ban] * (jQuery.Element) element - User element */ - $(Candy).triggerHandler('candy:view.roster.before-update', { - 'roomJid' : roomJid, - 'user' : user, - 'action': action, - 'element': userElem - }); - - // a user joined the room - if(action === 'join') { - usercountDiff = 1; - var html = Mustache.to_html(Candy.View.Template.Roster.user, { - roomId: roomId, - userId : userId, - userJid: user.getJid(), - nick: user.getNick(), - displayNick: Candy.Util.crop(user.getNick(), Candy.View.getOptions().crop.roster.nickname), - role: user.getRole(), - affiliation: user.getAffiliation(), - me: currentUser !== undefined && user.getNick() === currentUser.getNick(), - tooltipRole: $.i18n._('tooltipRole'), - tooltipIgnored: $.i18n._('tooltipIgnored') - }); - - if(userElem.length < 1) { - var userInserted = false, - rosterPane = self.Room.getPane(roomJid, '.roster-pane'); - - // there are already users in the roster - if(rosterPane.children().length > 0) { - // insert alphabetically - var userSortCompare = user.getNick().toUpperCase(); - rosterPane.children().each(function() { - var elem = $(this); - if(elem.attr('data-nick').toUpperCase() > userSortCompare) { - elem.before(html); - userInserted = true; - return false; - } - return true; - }); - } - // first user in roster - if(!userInserted) { - rosterPane.append(html); - } - - self.Roster.showJoinAnimation(user, userId, roomId, roomJid, currentUser); - // user is in room but maybe the affiliation/role has changed - } else { - usercountDiff = 0; - userElem.replaceWith(html); - $('#user-' + roomId + '-' + userId).css({opacity: 1}).show(); - // it's me, update the toolbar - if(currentUser !== undefined && user.getNick() === currentUser.getNick() && self.Room.getUser(roomJid)) { - self.Chat.Toolbar.update(roomJid); - } - } - - // Presence of client - if (currentUser !== undefined && currentUser.getNick() === user.getNick()) { - self.Room.setUser(roomJid, user); - // add click handler for private chat - } else { - $('#user-' + roomId + '-' + userId).click(self.Roster.userClick); - } - - $('#user-' + roomId + '-' + userId + ' .context').click(function(e) { - self.Chat.Context.show(e.currentTarget, roomJid, user); - e.stopPropagation(); - }); - - // check if current user is ignoring the user who has joined. - if (currentUser !== undefined && currentUser.isInPrivacyList('ignore', user.getJid())) { - Candy.View.Pane.Room.addIgnoreIcon(roomJid, user.getJid()); - } - - // a user left the room - } else if(action === 'leave') { - self.Roster.leaveAnimation('user-' + roomId + '-' + userId); - // always show leave message in private room, even if status messages have been disabled - if (self.Chat.rooms[roomJid].type === 'chat') { - self.Chat.onInfoMessage(roomJid, $.i18n._('userLeftRoom', [user.getNick()])); - } else { - self.Chat.infoMessage(roomJid, $.i18n._('userLeftRoom', [user.getNick()])); - } - - } else if(action === 'nickchange') { - usercountDiff = 0; - self.Roster.changeNick(roomId, user); - self.Room.changeDataUserJidIfUserIsMe(roomId, user); - self.PrivateRoom.changeNick(roomJid, user); - var infoMessage = $.i18n._('userChangedNick', [user.getPreviousNick(), user.getNick()]); - self.Chat.onInfoMessage(roomJid, infoMessage); - // user has been kicked - } else if(action === 'kick') { - self.Roster.leaveAnimation('user-' + roomId + '-' + userId); - self.Chat.onInfoMessage(roomJid, $.i18n._('userHasBeenKickedFromRoom', [user.getNick()])); - // user has been banned - } else if(action === 'ban') { - self.Roster.leaveAnimation('user-' + roomId + '-' + userId); - self.Chat.onInfoMessage(roomJid, $.i18n._('userHasBeenBannedFromRoom', [user.getNick()])); - } - - // Update user count - Candy.View.Pane.Chat.rooms[roomJid].usercount += usercountDiff; - - if(roomJid === Candy.View.getCurrent().roomJid) { - Candy.View.Pane.Chat.Toolbar.updateUsercount(Candy.View.Pane.Chat.rooms[roomJid].usercount); - } - - /** Event: candy:view.roster.after-update + $(Candy).triggerHandler("candy:view.roster.before-update", { + roomJid: roomJid, + user: user, + action: action, + element: userElem + }); + // a user joined the room + if (action === "join") { + usercountDiff = 1; + var html = Mustache.to_html(Candy.View.Template.Roster.user, { + roomId: roomId, + userId: userId, + userJid: user.getJid(), + nick: user.getNick(), + displayNick: Candy.Util.crop(user.getNick(), Candy.View.getOptions().crop.roster.nickname), + role: user.getRole(), + affiliation: user.getAffiliation(), + me: currentUser !== undefined && user.getNick() === currentUser.getNick(), + tooltipRole: $.i18n._("tooltipRole"), + tooltipIgnored: $.i18n._("tooltipIgnored") + }); + if (userElem.length < 1) { + var userInserted = false, rosterPane = self.Room.getPane(roomJid, ".roster-pane"); + // there are already users in the roster + if (rosterPane.children().length > 0) { + // insert alphabetically + var userSortCompare = user.getNick().toUpperCase(); + rosterPane.children().each(function() { + var elem = $(this); + if (elem.attr("data-nick").toUpperCase() > userSortCompare) { + elem.before(html); + userInserted = true; + return false; + } + return true; + }); + } + // first user in roster + if (!userInserted) { + rosterPane.append(html); + } + self.Roster.showJoinAnimation(user, userId, roomId, roomJid, currentUser); + } else { + usercountDiff = 0; + userElem.replaceWith(html); + $("#user-" + roomId + "-" + userId).css({ + opacity: 1 + }).show(); + // it's me, update the toolbar + if (currentUser !== undefined && user.getNick() === currentUser.getNick() && self.Room.getUser(roomJid)) { + self.Chat.Toolbar.update(roomJid); + } + } + // Presence of client + if (currentUser !== undefined && currentUser.getNick() === user.getNick()) { + self.Room.setUser(roomJid, user); + } else { + $("#user-" + roomId + "-" + userId).click(self.Roster.userClick); + } + $("#user-" + roomId + "-" + userId + " .context").click(function(e) { + self.Chat.Context.show(e.currentTarget, roomJid, user); + e.stopPropagation(); + }); + // check if current user is ignoring the user who has joined. + if (currentUser !== undefined && currentUser.isInPrivacyList("ignore", user.getJid())) { + Candy.View.Pane.Room.addIgnoreIcon(roomJid, user.getJid()); + } + } else if (action === "leave") { + self.Roster.leaveAnimation("user-" + roomId + "-" + userId); + // always show leave message in private room, even if status messages have been disabled + if (self.Chat.rooms[roomJid].type === "chat") { + self.Chat.onInfoMessage(roomJid, $.i18n._("userLeftRoom", [ user.getNick() ])); + } else { + self.Chat.infoMessage(roomJid, $.i18n._("userLeftRoom", [ user.getNick() ])); + } + } else if (action === "nickchange") { + usercountDiff = 0; + self.Roster.changeNick(roomId, user); + self.Room.changeDataUserJidIfUserIsMe(roomId, user); + self.PrivateRoom.changeNick(roomJid, user); + var infoMessage = $.i18n._("userChangedNick", [ user.getPreviousNick(), user.getNick() ]); + self.Chat.onInfoMessage(roomJid, infoMessage); + } else if (action === "kick") { + self.Roster.leaveAnimation("user-" + roomId + "-" + userId); + self.Chat.onInfoMessage(roomJid, $.i18n._("userHasBeenKickedFromRoom", [ user.getNick() ])); + } else if (action === "ban") { + self.Roster.leaveAnimation("user-" + roomId + "-" + userId); + self.Chat.onInfoMessage(roomJid, $.i18n._("userHasBeenBannedFromRoom", [ user.getNick() ])); + } + // Update user count + Candy.View.Pane.Chat.rooms[roomJid].usercount += usercountDiff; + if (roomJid === Candy.View.getCurrent().roomJid) { + Candy.View.Pane.Chat.Toolbar.updateUsercount(Candy.View.Pane.Chat.rooms[roomJid].usercount); + } + /** Event: candy:view.roster.after-update * After updating a room's roster * * Parameters: @@ -4692,74 +4353,72 @@ Candy.View.Pane = (function(self, $) { * (String) action - [join, leave, kick, ban] * (jQuery.Element) element - User element */ - $(Candy).triggerHandler('candy:view.roster.after-update', { - 'roomJid' : roomJid, - 'user' : user, - 'action': action, - 'element': $('#user-' + roomId + '-' + userId) - }); - }, - - /** Function: userClick + $(Candy).triggerHandler("candy:view.roster.after-update", { + roomJid: roomJid, + user: user, + action: action, + element: $("#user-" + roomId + "-" + userId) + }); + }, + /** Function: userClick * Click handler for opening a private room */ - userClick: function() { - var elem = $(this); - self.PrivateRoom.open(elem.attr('data-jid'), elem.attr('data-nick'), true); - }, - - /** Function: showJoinAnimation + userClick: function() { + var elem = $(this); + self.PrivateRoom.open(elem.attr("data-jid"), elem.attr("data-nick"), true); + }, + /** Function: showJoinAnimation * Shows join animation if needed * * FIXME: Refactor. Part of this will be done by the big room improvements */ - showJoinAnimation: function(user, userId, roomId, roomJid, currentUser) { - // don't show if the user has recently changed the nickname. - var rosterUserId = 'user-' + roomId + '-' + userId, - $rosterUserElem = $('#' + rosterUserId); - if (!user.getPreviousNick() || !$rosterUserElem || $rosterUserElem.is(':visible') === false) { - self.Roster.joinAnimation(rosterUserId); - // only show other users joining & don't show if there's no message in the room. - if(currentUser !== undefined && user.getNick() !== currentUser.getNick() && self.Room.getUser(roomJid)) { - // always show join message in private room, even if status messages have been disabled - if (self.Chat.rooms[roomJid].type === 'chat') { - self.Chat.onInfoMessage(roomJid, $.i18n._('userJoinedRoom', [user.getNick()])); - } else { - self.Chat.infoMessage(roomJid, $.i18n._('userJoinedRoom', [user.getNick()])); - } - } - } - }, - - /** Function: joinAnimation + showJoinAnimation: function(user, userId, roomId, roomJid, currentUser) { + // don't show if the user has recently changed the nickname. + var rosterUserId = "user-" + roomId + "-" + userId, $rosterUserElem = $("#" + rosterUserId); + if (!user.getPreviousNick() || !$rosterUserElem || $rosterUserElem.is(":visible") === false) { + self.Roster.joinAnimation(rosterUserId); + // only show other users joining & don't show if there's no message in the room. + if (currentUser !== undefined && user.getNick() !== currentUser.getNick() && self.Room.getUser(roomJid)) { + // always show join message in private room, even if status messages have been disabled + if (self.Chat.rooms[roomJid].type === "chat") { + self.Chat.onInfoMessage(roomJid, $.i18n._("userJoinedRoom", [ user.getNick() ])); + } else { + self.Chat.infoMessage(roomJid, $.i18n._("userJoinedRoom", [ user.getNick() ])); + } + } + } + }, + /** Function: joinAnimation * Animates specified elementId on join * * Parameters: * (String) elementId - Specific element to do the animation on */ - joinAnimation: function(elementId) { - $('#' + elementId).stop(true).slideDown('normal', function() { - $(this).animate({opacity: 1}); - }); - }, - - /** Function: leaveAnimation + joinAnimation: function(elementId) { + $("#" + elementId).stop(true).slideDown("normal", function() { + $(this).animate({ + opacity: 1 + }); + }); + }, + /** Function: leaveAnimation * Leave animation for specified element id and removes the DOM element on completion. * * Parameters: * (String) elementId - Specific element to do the animation on */ - leaveAnimation: function(elementId) { - $('#' + elementId).stop(true).attr('id', '#' + elementId + '-leaving').animate({opacity: 0}, { - complete: function() { - $(this).slideUp('normal', function() { - $(this).remove(); - }); - } - }); - }, - - /** Function: changeNick + leaveAnimation: function(elementId) { + $("#" + elementId).stop(true).attr("id", "#" + elementId + "-leaving").animate({ + opacity: 0 + }, { + complete: function() { + $(this).slideUp("normal", function() { + $(this).remove(); + }); + } + }); + }, + /** Function: changeNick * Change nick of an existing user in the roster * * UserId has to be recalculated from the user because at the time of this call, @@ -4769,24 +4428,20 @@ Candy.View.Pane = (function(self, $) { * (String) roomId - Id of the room * (Candy.Core.ChatUser) user - User object */ - changeNick: function(roomId, user) { - Candy.Core.log('[View:Pane:Roster] changeNick'); - var previousUserJid = Strophe.getBareJidFromJid(user.getJid()) + '/' + user.getPreviousNick(), - elementId = 'user-' + roomId + '-' + Candy.Util.jidToId(previousUserJid), - el = $('#' + elementId); - - el.attr('data-nick', user.getNick()); - el.attr('data-jid', user.getJid()); - el.children('div.label').text(user.getNick()); - el.attr('id', 'user-' + roomId + '-' + Candy.Util.jidToId(user.getJid())); - } - }; - - /** Class: Candy.View.Pane.Message + changeNick: function(roomId, user) { + Candy.Core.log("[View:Pane:Roster] changeNick"); + var previousUserJid = Strophe.getBareJidFromJid(user.getJid()) + "/" + user.getPreviousNick(), elementId = "user-" + roomId + "-" + Candy.Util.jidToId(previousUserJid), el = $("#" + elementId); + el.attr("data-nick", user.getNick()); + el.attr("data-jid", user.getJid()); + el.children("div.label").text(user.getNick()); + el.attr("id", "user-" + roomId + "-" + Candy.Util.jidToId(user.getJid())); + } + }; + /** Class: Candy.View.Pane.Message * Message submit/show handling */ - self.Message = { - /** Function: submit + self.Message = { + /** Function: submit * on submit handler for message field sends the message to the server and if it's a private chat, shows the message * immediately because the server doesn't send back those message. * @@ -4796,33 +4451,29 @@ Candy.View.Pane = (function(self, $) { * Triggers: * candy:view.message.before-send using {message} */ - submit: function(event) { - var roomType = Candy.View.Pane.Chat.rooms[Candy.View.getCurrent().roomJid].type, - message = $(this).children('.field').val().substring(0, Candy.View.getOptions().crop.message.body); - - var evtData = {message: message}; - - /** Event: candy:view.message.before-send + submit: function(event) { + var roomType = Candy.View.Pane.Chat.rooms[Candy.View.getCurrent().roomJid].type, message = $(this).children(".field").val().substring(0, Candy.View.getOptions().crop.message.body); + var evtData = { + message: message + }; + /** Event: candy:view.message.before-send * Before sending a message * * Parameters: * (String) message - Message text */ - $(Candy).triggerHandler('candy:view.message.before-send', evtData); - - message = evtData.message; - - Candy.Core.Action.Jabber.Room.Message(Candy.View.getCurrent().roomJid, message, roomType); - // Private user chat. Jabber won't notify the user who has sent the message. Just show it as the user hits the button... - if(roomType === 'chat' && message) { - self.Message.show(Candy.View.getCurrent().roomJid, self.Room.getUser(Candy.View.getCurrent().roomJid).getNick(), message); - } - // Clear input and set focus to it - $(this).children('.field').val('').focus(); - event.preventDefault(); - }, - - /** Function: show + $(Candy).triggerHandler("candy:view.message.before-send", evtData); + message = evtData.message; + Candy.Core.Action.Jabber.Room.Message(Candy.View.getCurrent().roomJid, message, roomType); + // Private user chat. Jabber won't notify the user who has sent the message. Just show it as the user hits the button... + if (roomType === "chat" && message) { + self.Message.show(Candy.View.getCurrent().roomJid, self.Room.getUser(Candy.View.getCurrent().roomJid).getNick(), message); + } + // Clear input and set focus to it + $(this).children(".field").val("").focus(); + event.preventDefault(); + }, + /** Function: show * Show a message in the message pane * * Parameters: @@ -4836,12 +4487,14 @@ Candy.View.Pane = (function(self, $) { * candy.view.message.before-render using {template, templateData} * candy:view.message.after-show using {roomJid, name, message, element} */ - show: function(roomJid, name, message, timestamp) { - message = Candy.Util.Parser.all(message.substring(0, Candy.View.getOptions().crop.message.body)); - - var evtData = {'roomJid': roomJid, 'name': name, 'message': message}; - - /** Event: candy:view.message.before-show + show: function(roomJid, name, message, timestamp) { + message = Candy.Util.Parser.all(message.substring(0, Candy.View.getOptions().crop.message.body)); + var evtData = { + roomJid: roomJid, + name: name, + message: message + }; + /** Event: candy:view.message.before-show * Before showing a new message * * Parameters: @@ -4849,25 +4502,21 @@ Candy.View.Pane = (function(self, $) { * (String) name - Name of the sending user * (String) message - Message text */ - $(Candy).triggerHandler('candy:view.message.before-show', evtData); - - message = evtData.message; - - if(!message) { - return; - } - - var renderEvtData = { - template: Candy.View.Template.Message.item, - templateData: { - name: name, - displayName: Candy.Util.crop(name, Candy.View.getOptions().crop.message.nickname), - message: message, - time: Candy.Util.localizedTime(timestamp || new Date().toGMTString()) - } - }; - - /** Event: candy:view.message.before-render + $(Candy).triggerHandler("candy:view.message.before-show", evtData); + message = evtData.message; + if (!message) { + return; + } + var renderEvtData = { + template: Candy.View.Template.Message.item, + templateData: { + name: name, + displayName: Candy.Util.crop(name, Candy.View.getOptions().crop.message.nickname), + message: message, + time: Candy.Util.localizedTime(timestamp || new Date().toGMTString()) + } + }; + /** Event: candy:view.message.before-render * Before rendering the message element * * Parameters: @@ -4878,40 +4527,36 @@ Candy.View.Pane = (function(self, $) { * - (String) message - Message text * - (String) time - Localized time */ - $(Candy).triggerHandler('candy:view.message.before-render', renderEvtData); - - var html = Mustache.to_html(renderEvtData.template, renderEvtData.templateData); - self.Room.appendToMessagePane(roomJid, html); - var elem = self.Room.getPane(roomJid, '.message-pane').children().last(); - // click on username opens private chat - elem.find('a.label').click(function(event) { - event.preventDefault(); - // Check if user is online and not myself - var room = Candy.Core.getRoom(roomJid); - if(room && name !== self.Room.getUser(Candy.View.getCurrent().roomJid).getNick() && room.getRoster().get(roomJid + '/' + name)) { - Candy.View.Pane.PrivateRoom.open(roomJid + '/' + name, name, true); - } - }); - - // Notify the user about a new private message - if(Candy.View.getCurrent().roomJid !== roomJid || !self.Window.hasFocus()) { - self.Chat.increaseUnreadMessages(roomJid); - if(Candy.View.Pane.Chat.rooms[roomJid].type === 'chat' && !self.Window.hasFocus()) { - self.Chat.Toolbar.playSound(); - } - } - if(Candy.View.getCurrent().roomJid === roomJid) { - self.Room.scrollToBottom(roomJid); - } - - evtData = { - 'roomJid': roomJid, - 'element': elem, - 'name': name, - 'message': message - }; - - /** Event: candy:view.message.after-show + $(Candy).triggerHandler("candy:view.message.before-render", renderEvtData); + var html = Mustache.to_html(renderEvtData.template, renderEvtData.templateData); + self.Room.appendToMessagePane(roomJid, html); + var elem = self.Room.getPane(roomJid, ".message-pane").children().last(); + // click on username opens private chat + elem.find("a.label").click(function(event) { + event.preventDefault(); + // Check if user is online and not myself + var room = Candy.Core.getRoom(roomJid); + if (room && name !== self.Room.getUser(Candy.View.getCurrent().roomJid).getNick() && room.getRoster().get(roomJid + "/" + name)) { + Candy.View.Pane.PrivateRoom.open(roomJid + "/" + name, name, true); + } + }); + // Notify the user about a new private message + if (Candy.View.getCurrent().roomJid !== roomJid || !self.Window.hasFocus()) { + self.Chat.increaseUnreadMessages(roomJid); + if (Candy.View.Pane.Chat.rooms[roomJid].type === "chat" && !self.Window.hasFocus()) { + self.Chat.Toolbar.playSound(); + } + } + if (Candy.View.getCurrent().roomJid === roomJid) { + self.Room.scrollToBottom(roomJid); + } + evtData = { + roomJid: roomJid, + element: elem, + name: name, + message: message + }; + /** Event: candy:view.message.after-show * Triggered after showing a message * * Parameters: @@ -4920,12 +4565,11 @@ Candy.View.Pane = (function(self, $) { * (String) name - Name of the sending user * (String) message - Message text */ - $(Candy).triggerHandler('candy:view.message.after-show', evtData); - } - }; - - return self; -}(Candy.View.Pane || {}, jQuery)); + $(Candy).triggerHandler("candy:view.message.after-show", evtData); + } + }; + return self; +}(Candy.View.Pane || {}, jQuery); /** File: template.js * Candy - Chats are not dead yet. @@ -4938,122 +4582,60 @@ Candy.View.Pane = (function(self, $) { * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy */ - /** Class: Candy.View.Template * Contains mustache.js templates */ -Candy.View.Template = (function(self){ - self.Window = { - /** +Candy.View.Template = function(self) { + self.Window = { + /** * Unread messages - used to extend the window title */ - unreadmessages: '({{count}}) {{title}}' - }; - - self.Chat = { - pane: '
    {{> tabs}}{{> toolbar}}{{> rooms}}
    {{> modal}}', - rooms: '
    ', - tabs: '
      ', - tab: '
    • ' + - '{{#privateUserChat}}@{{/privateUserChat}}{{name}}' + - '\u00D7' + - '
    • ', - modal: '
      \u00D7' + - '' + - '' + - '
      ', - adminMessage: '
    • {{time}}
      ' + - '{{sender}}' + - '{{subject}} {{message}}
    • ', - infoMessage: '
    • {{time}}
      ' + - '{{subject}} {{message}}
    • ', - toolbar: '
        ' + - '
      • ' + - '
      • {{> soundcontrol}}
      • ' + - '
      • ' + - '
      • ' + - '
      • ' + - '
      • ' + - '
      ', - soundcontrol: '' + - '', - Context: { - menu: '
      ' + - '
        ', - menulinks: '
      • {{label}}
      • ', - contextModalForm: '
        ' + - '' + - '' + - '
        ', - adminMessageReason: '×' + - '

        {{_action}}

        {{#reason}}

        {{_reason}}

        {{/reason}}' - }, - tooltip: '
        ' + - '
        ' - }; - - self.Room = { - pane: '
        ' + - '{{> roster}}{{> messages}}{{> form}}
        ', - subject: '
      • {{time}}
        ' + - '{{roomName}}' + - '{{_roomSubject}} {{{subject}}}
      • ', - form: '
        ' + - '
        ' + - '' + - '
        ' - }; - - self.Roster = { - pane: '
        ', - user: '
        ' + - '
        {{displayNick}}
          ' + - '
        • ' + - '
        • ' + - '
        ' - }; - - self.Message = { - pane: '
          ', - item: '
        • {{time}}
          ' + - '{{displayName}}' + - '{{{message}}}
        • ' - }; - - self.Login = { - form: '' - }; - - self.PresenceError = { - enterPasswordForm: '{{_label}}' + - '
          ' + - '' + - '
          ', - nicknameConflictForm: '{{_label}}' + - '
          ' + - '' + - '
          ', - displayError: '{{_error}}' - }; - - return self; -}(Candy.View.Template || {})); + unreadmessages: "({{count}}) {{title}}" + }; + self.Chat = { + pane: '
          {{> tabs}}{{> toolbar}}{{> rooms}}
          {{> modal}}', + rooms: '
          ', + tabs: '
            ', + tab: '
          • ' + '{{#privateUserChat}}@{{/privateUserChat}}{{name}}' + '×' + '
          • ', + modal: '
            ×' + '' + '' + '
            ', + adminMessage: '
          • {{time}}
            ' + '{{sender}}' + '{{subject}} {{message}}
          • ', + infoMessage: '
          • {{time}}
            ' + '{{subject}} {{message}}
          • ', + toolbar: '
              ' + '
            • ' + '
            • {{> soundcontrol}}
            • ' + '
            • ' + '
            • ' + '
            • ' + '
            • ' + '
            ', + soundcontrol: '' + "", + Context: { + menu: '
            ' + '
              ', + menulinks: '
            • {{label}}
            • ', + contextModalForm: '
              ' + '' + '' + '
              ', + adminMessageReason: '×' + "

              {{_action}}

              {{#reason}}

              {{_reason}}

              {{/reason}}" + }, + tooltip: '
              ' + '
              ' + }; + self.Room = { + pane: '
              ' + "{{> roster}}{{> messages}}{{> form}}
              ", + subject: '
            • {{time}}
              ' + '{{roomName}}' + '{{_roomSubject}} {{{subject}}}
            • ', + form: '
              ' + '
              ' + '' + '
              ' + }; + self.Roster = { + pane: '
              ', + user: '
              ' + '
              {{displayNick}}
                ' + '
              • ' + '
              • ' + '
              ' + }; + self.Message = { + pane: '
                ', + item: "
              • {{time}}
                " + '{{displayName}}' + '{{{message}}}
              • ' + }; + self.Login = { + form: '' + }; + self.PresenceError = { + enterPasswordForm: "{{_label}}" + '
                ' + '' + '
                ', + nicknameConflictForm: "{{_label}}" + '
                ' + '' + '
                ', + displayError: "{{_error}}" + }; + return self; +}(Candy.View.Template || {}); /** File: translation.js * Candy - Chats are not dead yet. @@ -5066,860 +4648,678 @@ Candy.View.Template = (function(self){ * (c) 2011 Amiado Group AG. All rights reserved. * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. */ -'use strict'; +"use strict"; /* global Candy */ - /** Class: Candy.View.Translation * Contains translations */ Candy.View.Translation = { - 'en' : { - 'status': 'Status: %s', - 'statusConnecting': 'Connecting...', - 'statusConnected' : 'Connected', - 'statusDisconnecting': 'Disconnecting...', - 'statusDisconnected' : 'Disconnected', - 'statusAuthfail': 'Authentication failed', - - 'roomSubject' : 'Subject:', - 'messageSubmit': 'Send', - - 'labelUsername': 'Username:', - 'labelNickname': 'Nickname:', - 'labelPassword': 'Password:', - 'loginSubmit' : 'Login', - 'loginInvalid' : 'Invalid JID', - - 'reason' : 'Reason:', - 'subject' : 'Subject:', - 'reasonWas' : 'Reason was: %s.', - 'kickActionLabel' : 'Kick', - 'youHaveBeenKickedBy' : 'You have been kicked from %2$s by %1$s', - 'youHaveBeenKicked' : 'You have been kicked from %s', - 'banActionLabel' : 'Ban', - 'youHaveBeenBannedBy' : 'You have been banned from %1$s by %2$s', - 'youHaveBeenBanned' : 'You have been banned from %s', - - 'privateActionLabel' : 'Private chat', - 'ignoreActionLabel' : 'Ignore', - 'unignoreActionLabel' : 'Unignore', - - 'setSubjectActionLabel': 'Change Subject', - - 'administratorMessageSubject' : 'Administrator', - - 'userJoinedRoom' : '%s joined the room.', - 'userLeftRoom' : '%s left the room.', - 'userHasBeenKickedFromRoom': '%s has been kicked from the room.', - 'userHasBeenBannedFromRoom': '%s has been banned from the room.', - 'userChangedNick': '%1$s has changed his nickname to %2$s.', - - 'presenceUnknownWarningSubject': 'Notice:', - 'presenceUnknownWarning' : 'This user might be offline. We can\'t track his presence.', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderator', - 'tooltipIgnored' : 'You ignore this user', - 'tooltipEmoticons' : 'Emoticons', - 'tooltipSound' : 'Play sound for new private messages', - 'tooltipAutoscroll' : 'Autoscroll', - 'tooltipStatusmessage' : 'Display status messages', - 'tooltipAdministration' : 'Room Administration', - 'tooltipUsercount' : 'Room Occupants', - - 'enterRoomPassword' : 'Room "%s" is password protected.', - 'enterRoomPasswordSubmit' : 'Join room', - 'passwordEnteredInvalid' : 'Invalid password for room "%s".', - - 'nicknameConflict': 'Username already in use. Please choose another one.', - - 'errorMembersOnly': 'You can\'t join room "%s": Insufficient rights.', - 'errorMaxOccupantsReached': 'You can\'t join room "%s": Too many occupants.', - 'errorAutojoinMissing': 'No autojoin parameter set in configuration. Please set one to continue.', - - 'antiSpamMessage' : 'Please do not spam. You have been blocked for a short-time.' - }, - 'de' : { - 'status': 'Status: %s', - 'statusConnecting': 'Verbinden...', - 'statusConnected' : 'Verbunden', - 'statusDisconnecting': 'Verbindung trennen...', - 'statusDisconnected' : 'Verbindung getrennt', - 'statusAuthfail': 'Authentifizierung fehlgeschlagen', - - 'roomSubject' : 'Thema:', - 'messageSubmit': 'Senden', - - 'labelUsername': 'Benutzername:', - 'labelNickname': 'Spitzname:', - 'labelPassword': 'Passwort:', - 'loginSubmit' : 'Anmelden', - 'loginInvalid' : 'Ungültige JID', - - 'reason' : 'Begründung:', - 'subject' : 'Titel:', - 'reasonWas' : 'Begründung: %s.', - 'kickActionLabel' : 'Kick', - 'youHaveBeenKickedBy' : 'Du wurdest soeben aus dem Raum %1$s gekickt (%2$s)', - 'youHaveBeenKicked' : 'Du wurdest soeben aus dem Raum %s gekickt', - 'banActionLabel' : 'Ban', - 'youHaveBeenBannedBy' : 'Du wurdest soeben aus dem Raum %1$s verbannt (%2$s)', - 'youHaveBeenBanned' : 'Du wurdest soeben aus dem Raum %s verbannt', - - 'privateActionLabel' : 'Privater Chat', - 'ignoreActionLabel' : 'Ignorieren', - 'unignoreActionLabel' : 'Nicht mehr ignorieren', - - 'setSubjectActionLabel': 'Thema ändern', - - 'administratorMessageSubject' : 'Administrator', - - 'userJoinedRoom' : '%s hat soeben den Raum betreten.', - 'userLeftRoom' : '%s hat soeben den Raum verlassen.', - 'userHasBeenKickedFromRoom': '%s ist aus dem Raum gekickt worden.', - 'userHasBeenBannedFromRoom': '%s ist aus dem Raum verbannt worden.', - 'userChangedNick': '%1$s hat den Nicknamen zu %2$s geändert.', - - 'presenceUnknownWarningSubject': 'Hinweis:', - 'presenceUnknownWarning' : 'Dieser Benutzer könnte bereits abgemeldet sein. Wir können seine Anwesenheit nicht verfolgen.', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderator', - 'tooltipIgnored' : 'Du ignorierst diesen Benutzer', - 'tooltipEmoticons' : 'Smileys', - 'tooltipSound' : 'Ton abspielen bei neuen privaten Nachrichten', - 'tooltipAutoscroll' : 'Autoscroll', - 'tooltipStatusmessage' : 'Statusnachrichten anzeigen', - 'tooltipAdministration' : 'Raum Administration', - 'tooltipUsercount' : 'Anzahl Benutzer im Raum', - - 'enterRoomPassword' : 'Raum "%s" ist durch ein Passwort geschützt.', - 'enterRoomPasswordSubmit' : 'Raum betreten', - 'passwordEnteredInvalid' : 'Inkorrektes Passwort für Raum "%s".', - - 'nicknameConflict': 'Der Benutzername wird bereits verwendet. Bitte wähle einen anderen.', - - 'errorMembersOnly': 'Du kannst den Raum "%s" nicht betreten: Ungenügende Rechte.', - 'errorMaxOccupantsReached': 'Du kannst den Raum "%s" nicht betreten: Benutzerlimit erreicht.', - 'errorAutojoinMissing': 'Keine "autojoin" Konfiguration gefunden. Bitte setze eine konfiguration um fortzufahren.', - - 'antiSpamMessage' : 'Bitte nicht spammen. Du wurdest für eine kurze Zeit blockiert.' - }, - 'fr' : { - 'status': 'Status : %s', - 'statusConnecting': 'Connexion…', - 'statusConnected' : 'Connecté.', - 'statusDisconnecting': 'Déconnexion…', - 'statusDisconnected' : 'Déconnecté.', - 'statusAuthfail': 'L\'authentification a échoué', - - 'roomSubject' : 'Sujet :', - 'messageSubmit': 'Envoyer', - - 'labelUsername': 'Nom d\'utilisateur :', - 'labelPassword': 'Mot de passe :', - 'loginSubmit' : 'Connexion', - 'loginInvalid' : 'JID invalide', - - 'reason' : 'Motif :', - 'subject' : 'Titre :', - 'reasonWas' : 'Motif : %s.', - 'kickActionLabel' : 'Kick', - 'youHaveBeenKickedBy' : 'Vous avez été expulsé du salon %1$s (%2$s)', - 'youHaveBeenKicked' : 'Vous avez été expulsé du salon %s', - 'banActionLabel' : 'Ban', - 'youHaveBeenBannedBy' : 'Vous avez été banni du salon %1$s (%2$s)', - 'youHaveBeenBanned' : 'Vous avez été banni du salon %s', - - 'privateActionLabel' : 'Chat privé', - 'ignoreActionLabel' : 'Ignorer', - 'unignoreActionLabel' : 'Ne plus ignorer', - - 'setSubjectActionLabel': 'Changer le sujet', - - 'administratorMessageSubject' : 'Administrateur', - - 'userJoinedRoom' : '%s vient d\'entrer dans le salon.', - 'userLeftRoom' : '%s vient de quitter le salon.', - 'userHasBeenKickedFromRoom': '%s a été expulsé du salon.', - 'userHasBeenBannedFromRoom': '%s a été banni du salon.', - - 'presenceUnknownWarningSubject': 'Note :', - 'presenceUnknownWarning' : 'Cet utilisateur n\'est malheureusement plus connecté, le message ne sera pas envoyé.', - - 'dateFormat': 'dd/mm/yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Modérateur', - 'tooltipIgnored' : 'Vous ignorez cette personne', - 'tooltipEmoticons' : 'Smileys', - 'tooltipSound' : 'Jouer un son lors de la réception de nouveaux messages privés', - 'tooltipAutoscroll' : 'Défilement automatique', - 'tooltipStatusmessage' : 'Messages d\'état', - 'tooltipAdministration' : 'Administration du salon', - 'tooltipUsercount' : 'Nombre d\'utilisateurs dans le salon', - - 'enterRoomPassword' : 'Le salon "%s" est protégé par un mot de passe.', - 'enterRoomPasswordSubmit' : 'Entrer dans le salon', - 'passwordEnteredInvalid' : 'Le mot de passe pour le salon "%s" est invalide.', - - 'nicknameConflict': 'Le nom d\'utilisateur est déjà utilisé. Veuillez en choisir un autre.', - - 'errorMembersOnly': 'Vous ne pouvez pas entrer dans le salon "%s" : droits insuffisants.', - 'errorMaxOccupantsReached': 'Vous ne pouvez pas entrer dans le salon "%s": Limite d\'utilisateur atteint.', - - 'antiSpamMessage' : 'Merci de ne pas envoyer de spam. Vous avez été bloqué pendant une courte période..' - }, - 'nl' : { - 'status': 'Status: %s', - 'statusConnecting': 'Verbinding maken...', - 'statusConnected' : 'Verbinding is gereed', - 'statusDisconnecting': 'Verbinding verbreken...', - 'statusDisconnected' : 'Verbinding is verbroken', - 'statusAuthfail': 'Authenticatie is mislukt', - - 'roomSubject' : 'Onderwerp:', - 'messageSubmit': 'Verstuur', - - 'labelUsername': 'Gebruikersnaam:', - 'labelPassword': 'Wachtwoord:', - 'loginSubmit' : 'Inloggen', - 'loginInvalid' : 'JID is onjuist', - - 'reason' : 'Reden:', - 'subject' : 'Onderwerp:', - 'reasonWas' : 'De reden was: %s.', - 'kickActionLabel' : 'Verwijderen', - 'youHaveBeenKickedBy' : 'Je bent verwijderd van %1$s door %2$s', - 'youHaveBeenKicked' : 'Je bent verwijderd van %s', - 'banActionLabel' : 'Blokkeren', - 'youHaveBeenBannedBy' : 'Je bent geblokkeerd van %1$s door %2$s', - 'youHaveBeenBanned' : 'Je bent geblokkeerd van %s', - - 'privateActionLabel' : 'Prive gesprek', - 'ignoreActionLabel' : 'Negeren', - 'unignoreActionLabel' : 'Niet negeren', - - 'setSubjectActionLabel': 'Onderwerp wijzigen', - - 'administratorMessageSubject' : 'Beheerder', - - 'userJoinedRoom' : '%s komt de chat binnen.', - 'userLeftRoom' : '%s heeft de chat verlaten.', - 'userHasBeenKickedFromRoom': '%s is verwijderd.', - 'userHasBeenBannedFromRoom': '%s is geblokkeerd.', - - 'presenceUnknownWarningSubject': 'Mededeling:', - 'presenceUnknownWarning' : 'Deze gebruiker is waarschijnlijk offline, we kunnen zijn/haar aanwezigheid niet vaststellen.', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderator', - 'tooltipIgnored' : 'Je negeert deze gebruiker', - 'tooltipEmoticons' : 'Emotie-iconen', - 'tooltipSound' : 'Speel een geluid af bij nieuwe privé berichten.', - 'tooltipAutoscroll' : 'Automatisch scrollen', - 'tooltipStatusmessage' : 'Statusberichten weergeven', - 'tooltipAdministration' : 'Instellingen', - 'tooltipUsercount' : 'Gebruikers', - - 'enterRoomPassword' : 'De Chatroom "%s" is met een wachtwoord beveiligd.', - 'enterRoomPasswordSubmit' : 'Ga naar Chatroom', - 'passwordEnteredInvalid' : 'Het wachtwoord voor de Chatroom "%s" is onjuist.', - - 'nicknameConflict': 'De gebruikersnaam is reeds in gebruik. Probeer a.u.b. een andere gebruikersnaam.', - - 'errorMembersOnly': 'Je kunt niet deelnemen aan de Chatroom "%s": Je hebt onvoldoende rechten.', - 'errorMaxOccupantsReached': 'Je kunt niet deelnemen aan de Chatroom "%s": Het maximum aantal gebruikers is bereikt.', - - 'antiSpamMessage' : 'Het is niet toegestaan om veel berichten naar de server te versturen. Je bent voor een korte periode geblokkeerd.' - }, - 'es': { - 'status': 'Estado: %s', - 'statusConnecting': 'Conectando...', - 'statusConnected' : 'Conectado', - 'statusDisconnecting': 'Desconectando...', - 'statusDisconnected' : 'Desconectado', - 'statusAuthfail': 'Falló la autenticación', - - 'roomSubject' : 'Asunto:', - 'messageSubmit': 'Enviar', - - 'labelUsername': 'Usuario:', - 'labelPassword': 'Clave:', - 'loginSubmit' : 'Entrar', - 'loginInvalid' : 'JID no válido', - - 'reason' : 'Razón:', - 'subject' : 'Asunto:', - 'reasonWas' : 'La razón fue: %s.', - 'kickActionLabel' : 'Expulsar', - 'youHaveBeenKickedBy' : 'Has sido expulsado de %1$s por %2$s', - 'youHaveBeenKicked' : 'Has sido expulsado de %s', - 'banActionLabel' : 'Prohibir', - 'youHaveBeenBannedBy' : 'Has sido expulsado permanentemente de %1$s por %2$s', - 'youHaveBeenBanned' : 'Has sido expulsado permanentemente de %s', - - 'privateActionLabel' : 'Chat privado', - 'ignoreActionLabel' : 'Ignorar', - 'unignoreActionLabel' : 'No ignorar', - - 'setSubjectActionLabel': 'Cambiar asunto', - - 'administratorMessageSubject' : 'Administrador', - - 'userJoinedRoom' : '%s se ha unido a la sala.', - 'userLeftRoom' : '%s ha dejado la sala.', - 'userHasBeenKickedFromRoom': '%s ha sido expulsado de la sala.', - 'userHasBeenBannedFromRoom': '%s ha sido expulsado permanentemente de la sala.', - - 'presenceUnknownWarningSubject': 'Atención:', - 'presenceUnknownWarning' : 'Éste usuario podría estar desconectado..', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderador', - 'tooltipIgnored' : 'Ignoras a éste usuario', - 'tooltipEmoticons' : 'Emoticonos', - 'tooltipSound' : 'Reproducir un sonido para nuevos mensajes privados', - 'tooltipAutoscroll' : 'Desplazamiento automático', - 'tooltipStatusmessage' : 'Mostrar mensajes de estado', - 'tooltipAdministration' : 'Administración de la sala', - 'tooltipUsercount' : 'Usuarios en la sala', - - 'enterRoomPassword' : 'La sala "%s" está protegida mediante contraseña.', - 'enterRoomPasswordSubmit' : 'Unirse a la sala', - 'passwordEnteredInvalid' : 'Contraseña incorrecta para la sala "%s".', - - 'nicknameConflict': 'El nombre de usuario ya está siendo utilizado. Por favor elija otro.', - - 'errorMembersOnly': 'No se puede unir a la sala "%s": no tiene privilegios suficientes.', - 'errorMaxOccupantsReached': 'No se puede unir a la sala "%s": demasiados participantes.', - - 'antiSpamMessage' : 'Por favor, no hagas spam. Has sido bloqueado temporalmente.' - }, - 'cn': { - 'status': '状态: %s', - 'statusConnecting': '连接中...', - 'statusConnected': '已连接', - 'statusDisconnecting': '断开连接中...', - 'statusDisconnected': '已断开连接', - 'statusAuthfail': '认证失败', - - 'roomSubject': '主题:', - 'messageSubmit': '发送', - - 'labelUsername': '用户名:', - 'labelPassword': '密码:', - 'loginSubmit': '登录', - 'loginInvalid': '用户名不合法', - - 'reason': '原因:', - 'subject': '主题:', - 'reasonWas': '原因是: %s.', - 'kickActionLabel': '踢除', - 'youHaveBeenKickedBy': '你在 %1$s 被管理者 %2$s 请出房间', - 'banActionLabel': '禁言', - 'youHaveBeenBannedBy': '你在 %1$s 被管理者 %2$s 禁言', - - 'privateActionLabel': '单独对话', - 'ignoreActionLabel': '忽略', - 'unignoreActionLabel': '不忽略', - - 'setSubjectActionLabel': '变更主题', - - 'administratorMessageSubject': '管理员', - - 'userJoinedRoom': '%s 加入房间', - 'userLeftRoom': '%s 离开房间', - 'userHasBeenKickedFromRoom': '%s 被请出这个房间', - 'userHasBeenBannedFromRoom': '%s 被管理者禁言', - - 'presenceUnknownWarningSubject': '注意:', - 'presenceUnknownWarning': '这个会员可能已经下线,不能追踪到他的连接信息', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole': '管理', - 'tooltipIgnored': '你忽略了这个会员', - 'tooltipEmoticons': '表情', - 'tooltipSound': '新消息发音', - 'tooltipAutoscroll': '滚动条', - 'tooltipStatusmessage': '禁用状态消息', - 'tooltipAdministration': '房间管理', - 'tooltipUsercount': '房间占有者', - - 'enterRoomPassword': '登录房间 "%s" 需要密码.', - 'enterRoomPasswordSubmit': '加入房间', - 'passwordEnteredInvalid': '登录房间 "%s" 的密码不正确', - - 'nicknameConflict': '用户名已经存在,请另选一个', - - 'errorMembersOnly': '您的权限不够,不能登录房间 "%s" ', - 'errorMaxOccupantsReached': '房间 "%s" 的人数已达上限,您不能登录', - - 'antiSpamMessage': '因为您在短时间内发送过多的消息 服务器要阻止您一小段时间。' - }, - 'ja' : { - 'status' : 'ステータス: %s', - 'statusConnecting' : '接続中…', - 'statusConnected' : '接続されました', - 'statusDisconnecting' : 'ディスコネクト中…', - 'statusDisconnected' : 'ディスコネクトされました', - 'statusAuthfail' : '認証に失敗しました', - - 'roomSubject' : 'トピック:', - 'messageSubmit' : '送信', - - 'labelUsername' : 'ユーザーネーム:', - 'labelPassword' : 'パスワード:', - 'loginSubmit' : 'ログイン', - 'loginInvalid' : 'ユーザーネームが正しくありません', - - 'reason' : '理由:', - 'subject' : 'トピック:', - 'reasonWas' : '理由: %s。', - 'kickActionLabel' : 'キック', - 'youHaveBeenKickedBy' : 'あなたは%2$sにより%1$sからキックされました。', - 'youHaveBeenKicked' : 'あなたは%sからキックされました。', - 'banActionLabel' : 'アカウントバン', - 'youHaveBeenBannedBy' : 'あなたは%2$sにより%1$sからアカウントバンされました。', - 'youHaveBeenBanned' : 'あなたは%sからアカウントバンされました。', - - 'privateActionLabel' : 'プライベートメッセージ', - 'ignoreActionLabel' : '無視する', - 'unignoreActionLabel' : '無視をやめる', - - 'setSubjectActionLabel' : 'トピックを変える', - - 'administratorMessageSubject' : '管理者', - - 'userJoinedRoom' : '%sは入室しました。', - 'userLeftRoom' : '%sは退室しました。', - 'userHasBeenKickedFromRoom' : '%sは部屋からキックされました。', - 'userHasBeenBannedFromRoom' : '%sは部屋からアカウントバンされました。', - - 'presenceUnknownWarningSubject' : '忠告:', - 'presenceUnknownWarning' : 'このユーザーのステータスは不明です。', - - 'dateFormat' : 'dd.mm.yyyy', - 'timeFormat' : 'HH:MM:ss', - - 'tooltipRole' : 'モデレーター', - 'tooltipIgnored' : 'このユーザーを無視設定にしている', - 'tooltipEmoticons' : '絵文字', - 'tooltipSound' : '新しいメッセージが届くたびに音を鳴らす', - 'tooltipAutoscroll' : 'オートスクロール', - 'tooltipStatusmessage' : 'ステータスメッセージを表示', - 'tooltipAdministration' : '部屋の管理', - 'tooltipUsercount' : 'この部屋の参加者の数', - - 'enterRoomPassword' : '"%s"の部屋に入るにはパスワードが必要です。', - 'enterRoomPasswordSubmit' : '部屋に入る', - 'passwordEnteredInvalid' : '"%s"のパスワードと異なるパスワードを入力しました。', - - 'nicknameConflict' : 'このユーザーネームはすでに利用されているため、別のユーザーネームを選んでください。', - - 'errorMembersOnly' : '"%s"の部屋に入ることができません: 利用権限を満たしていません。', - 'errorMaxOccupantsReached' : '"%s"の部屋に入ることができません: 参加者の数はすでに上限に達しました。', - - 'antiSpamMessage' : 'スパムなどの行為はやめてください。あなたは一時的にブロックされました。' - }, - 'sv' : { - 'status': 'Status: %s', - 'statusConnecting': 'Ansluter...', - 'statusConnected' : 'Ansluten', - 'statusDisconnecting': 'Kopplar från...', - 'statusDisconnected' : 'Frånkopplad', - 'statusAuthfail': 'Autentisering misslyckades', - - 'roomSubject' : 'Ämne:', - 'messageSubmit': 'Skicka', - - 'labelUsername': 'Användarnamn:', - 'labelPassword': 'Lösenord:', - 'loginSubmit' : 'Logga in', - 'loginInvalid' : 'Ogiltigt JID', - - 'reason' : 'Anledning:', - 'subject' : 'Ämne:', - 'reasonWas' : 'Anledningen var: %s.', - 'kickActionLabel' : 'Sparka ut', - 'youHaveBeenKickedBy' : 'Du har blivit utsparkad från %2$s av %1$s', - 'youHaveBeenKicked' : 'Du har blivit utsparkad från %s', - 'banActionLabel' : 'Bannlys', - 'youHaveBeenBannedBy' : 'Du har blivit bannlyst från %1$s av %2$s', - 'youHaveBeenBanned' : 'Du har blivit bannlyst från %s', - - 'privateActionLabel' : 'Privat chatt', - 'ignoreActionLabel' : 'Blockera', - 'unignoreActionLabel' : 'Avblockera', - - 'setSubjectActionLabel': 'Ändra ämne', - - 'administratorMessageSubject' : 'Administratör', - - 'userJoinedRoom' : '%s kom in i rummet.', - 'userLeftRoom' : '%s har lämnat rummet.', - 'userHasBeenKickedFromRoom': '%s har blivit utsparkad ur rummet.', - 'userHasBeenBannedFromRoom': '%s har blivit bannlyst från rummet.', - - 'presenceUnknownWarningSubject': 'Notera:', - 'presenceUnknownWarning' : 'Denna användare kan vara offline. Vi kan inte följa dennes närvaro.', - - 'dateFormat': 'yyyy-mm-dd', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderator', - 'tooltipIgnored' : 'Du blockerar denna användare', - 'tooltipEmoticons' : 'Smilies', - 'tooltipSound' : 'Spela upp ett ljud vid nytt privat meddelande', - 'tooltipAutoscroll' : 'Autoskrolla', - 'tooltipStatusmessage' : 'Visa statusmeddelanden', - 'tooltipAdministration' : 'Rumadministrering', - 'tooltipUsercount' : 'Antal användare i rummet', - - 'enterRoomPassword' : 'Rummet "%s" är lösenordsskyddat.', - 'enterRoomPasswordSubmit' : 'Anslut till rum', - 'passwordEnteredInvalid' : 'Ogiltigt lösenord för rummet "%s".', - - 'nicknameConflict': 'Upptaget användarnamn. Var god välj ett annat.', - - 'errorMembersOnly': 'Du kan inte ansluta till rummet "%s": Otillräckliga rättigheter.', - 'errorMaxOccupantsReached': 'Du kan inte ansluta till rummet "%s": Rummet är fullt.', - - 'antiSpamMessage' : 'Var god avstå från att spamma. Du har blivit blockerad för en kort stund.' - }, - 'it' : { - 'status': 'Stato: %s', - 'statusConnecting': 'Connessione...', - 'statusConnected' : 'Connessione', - 'statusDisconnecting': 'Disconnessione...', - 'statusDisconnected' : 'Disconnesso', - 'statusAuthfail': 'Autenticazione fallita', - - 'roomSubject' : 'Oggetto:', - 'messageSubmit': 'Invia', - - 'labelUsername': 'Nome utente:', - 'labelPassword': 'Password:', - 'loginSubmit' : 'Login', - 'loginInvalid' : 'JID non valido', - - 'reason' : 'Ragione:', - 'subject' : 'Oggetto:', - 'reasonWas' : 'Ragione precedente: %s.', - 'kickActionLabel' : 'Espelli', - 'youHaveBeenKickedBy' : 'Sei stato espulso da %2$s da %1$s', - 'youHaveBeenKicked' : 'Sei stato espulso da %s', - 'banActionLabel' : 'Escluso', - 'youHaveBeenBannedBy' : 'Sei stato escluso da %1$s da %2$s', - 'youHaveBeenBanned' : 'Sei stato escluso da %s', - - 'privateActionLabel' : 'Stanza privata', - 'ignoreActionLabel' : 'Ignora', - 'unignoreActionLabel' : 'Non ignorare', - - 'setSubjectActionLabel': 'Cambia oggetto', - - 'administratorMessageSubject' : 'Amministratore', - - 'userJoinedRoom' : '%s si è unito alla stanza.', - 'userLeftRoom' : '%s ha lasciato la stanza.', - 'userHasBeenKickedFromRoom': '%s è stato espulso dalla stanza.', - 'userHasBeenBannedFromRoom': '%s è stato escluso dalla stanza.', - - 'presenceUnknownWarningSubject': 'Nota:', - 'presenceUnknownWarning' : 'Questo utente potrebbe essere offline. Non possiamo tracciare la sua presenza.', - - 'dateFormat': 'dd/mm/yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderatore', - 'tooltipIgnored' : 'Stai ignorando questo utente', - 'tooltipEmoticons' : 'Emoticons', - 'tooltipSound' : 'Riproduci un suono quando arrivano messaggi privati', - 'tooltipAutoscroll' : 'Autoscroll', - 'tooltipStatusmessage' : 'Mostra messaggi di stato', - 'tooltipAdministration' : 'Amministrazione stanza', - 'tooltipUsercount' : 'Partecipanti alla stanza', - - 'enterRoomPassword' : 'La stanza "%s" è protetta da password.', - 'enterRoomPasswordSubmit' : 'Unisciti alla stanza', - 'passwordEnteredInvalid' : 'Password non valida per la stanza "%s".', - - 'nicknameConflict': 'Nome utente già in uso. Scegline un altro.', - - 'errorMembersOnly': 'Non puoi unirti alla stanza "%s": Permessi insufficienti.', - 'errorMaxOccupantsReached': 'Non puoi unirti alla stanza "%s": Troppi partecipanti.', - - 'antiSpamMessage' : 'Per favore non scrivere messaggi pubblicitari. Sei stato bloccato per un po\' di tempo.' - }, - 'pt': { - 'status': 'Status: %s', - 'statusConnecting': 'Conectando...', - 'statusConnected' : 'Conectado', - 'statusDisconnecting': 'Desligando...', - 'statusDisconnected' : 'Desligado', - 'statusAuthfail': 'Falha na autenticação', - - 'roomSubject' : 'Assunto:', - 'messageSubmit': 'Enviar', - - 'labelUsername': 'Usuário:', - 'labelPassword': 'Senha:', - 'loginSubmit' : 'Entrar', - 'loginInvalid' : 'JID inválido', - - 'reason' : 'Motivo:', - 'subject' : 'Assunto:', - 'reasonWas' : 'O motivo foi: %s.', - 'kickActionLabel' : 'Excluir', - 'youHaveBeenKickedBy' : 'Você foi excluido de %1$s por %2$s', - 'youHaveBeenKicked' : 'Você foi excluido de %s', - 'banActionLabel' : 'Bloquear', - 'youHaveBeenBannedBy' : 'Você foi excluido permanentemente de %1$s por %2$s', - 'youHaveBeenBanned' : 'Você foi excluido permanentemente de %s', - - 'privateActionLabel' : 'Bate-papo privado', - 'ignoreActionLabel' : 'Ignorar', - 'unignoreActionLabel' : 'Não ignorar', - - 'setSubjectActionLabel': 'Trocar Assunto', - - 'administratorMessageSubject' : 'Administrador', - - 'userJoinedRoom' : '%s entrou na sala.', - 'userLeftRoom' : '%s saiu da sala.', - 'userHasBeenKickedFromRoom': '%s foi excluido da sala.', - 'userHasBeenBannedFromRoom': '%s foi excluido permanentemente da sala.', - - 'presenceUnknownWarning' : 'Este usuário pode estar desconectado. Não é possível determinar o status.', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderador', - 'tooltipIgnored' : 'Você ignora este usuário', - 'tooltipEmoticons' : 'Emoticons', - 'tooltipSound' : 'Reproduzir o som para novas mensagens privados', - 'tooltipAutoscroll' : 'Deslocamento automático', - 'tooltipStatusmessage' : 'Mostrar mensagens de status', - 'tooltipAdministration' : 'Administração da sala', - 'tooltipUsercount' : 'Usuários na sala', - - 'enterRoomPassword' : 'A sala "%s" é protegida por senha.', - 'enterRoomPasswordSubmit' : 'Junte-se à sala', - 'passwordEnteredInvalid' : 'Senha incorreta para a sala "%s".', - - 'nicknameConflict': 'O nome de usuário já está em uso. Por favor, escolha outro.', - - 'errorMembersOnly': 'Você não pode participar da sala "%s": privilégios insuficientes.', - 'errorMaxOccupantsReached': 'Você não pode participar da sala "%s": muitos participantes.', - - 'antiSpamMessage' : 'Por favor, não envie spam. Você foi bloqueado temporariamente.' - }, - 'pt_br' : { - 'status': 'Estado: %s', - 'statusConnecting': 'Conectando...', - 'statusConnected' : 'Conectado', - 'statusDisconnecting': 'Desconectando...', - 'statusDisconnected' : 'Desconectado', - 'statusAuthfail': 'Autenticação falhou', - - 'roomSubject' : 'Assunto:', - 'messageSubmit': 'Enviar', - - 'labelUsername': 'Usuário:', - 'labelPassword': 'Senha:', - 'loginSubmit' : 'Entrar', - 'loginInvalid' : 'JID inválido', - - 'reason' : 'Motivo:', - 'subject' : 'Assunto:', - 'reasonWas' : 'Motivo foi: %s.', - 'kickActionLabel' : 'Derrubar', - 'youHaveBeenKickedBy' : 'Você foi derrubado de %2$s por %1$s', - 'youHaveBeenKicked' : 'Você foi derrubado de %s', - 'banActionLabel' : 'Banir', - 'youHaveBeenBannedBy' : 'Você foi banido de %1$s por %2$s', - 'youHaveBeenBanned' : 'Você foi banido de %s', - - 'privateActionLabel' : 'Conversa privada', - 'ignoreActionLabel' : 'Ignorar', - 'unignoreActionLabel' : 'Não ignorar', - - 'setSubjectActionLabel': 'Mudar Assunto', - - 'administratorMessageSubject' : 'Administrador', - - 'userJoinedRoom' : '%s entrou na sala.', - 'userLeftRoom' : '%s saiu da sala.', - 'userHasBeenKickedFromRoom': '%s foi derrubado da sala.', - 'userHasBeenBannedFromRoom': '%s foi banido da sala.', - - 'presenceUnknownWarningSubject': 'Aviso:', - 'presenceUnknownWarning' : 'Este usuário pode estar desconectado.. Não conseguimos rastrear sua presença..', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderador', - 'tooltipIgnored' : 'Você ignora este usuário', - 'tooltipEmoticons' : 'Emoticons', - 'tooltipSound' : 'Tocar som para novas mensagens privadas', - 'tooltipAutoscroll' : 'Auto-rolagem', - 'tooltipStatusmessage' : 'Exibir mensagens de estados', - 'tooltipAdministration' : 'Administração de Sala', - 'tooltipUsercount' : 'Participantes da Sala', - - 'enterRoomPassword' : 'Sala "%s" é protegida por senha.', - 'enterRoomPasswordSubmit' : 'Entrar na sala', - 'passwordEnteredInvalid' : 'Senha inváida para sala "%s".', - - 'nicknameConflict': 'Nome de usuário já em uso. Por favor escolha outro.', - - 'errorMembersOnly': 'Você não pode entrar na sala "%s": privilégios insuficientes.', - 'errorMaxOccupantsReached': 'Você não pode entrar na sala "%s": máximo de participantes atingido.', - - 'antiSpamMessage' : 'Por favor, não faça spam. Você foi bloqueado temporariamente.' - }, - 'ru' : { - 'status': 'Статус: %s', - 'statusConnecting': 'Подключение...', - 'statusConnected' : 'Подключено', - 'statusDisconnecting': 'Отключение...', - 'statusDisconnected' : 'Отключено', - 'statusAuthfail': 'Неверный логин', - - 'roomSubject' : 'Топик:', - 'messageSubmit': 'Послать', - - 'labelUsername': 'Имя:', - 'labelPassword': 'Пароль:', - 'loginSubmit' : 'Логин', - 'loginInvalid' : 'Неверный JID', - - 'reason' : 'Причина:', - 'subject' : 'Топик:', - 'reasonWas' : 'Причина была: %s.', - 'kickActionLabel' : 'Выбросить', - 'youHaveBeenKickedBy' : 'Пользователь %1$s выбросил вас из чата %2$s', - 'youHaveBeenKicked' : 'Вас выбросили из чата %s', - 'banActionLabel' : 'Запретить доступ', - 'youHaveBeenBannedBy' : 'Пользователь %1$s запретил вам доступ в чат %2$s', - 'youHaveBeenBanned' : 'Вам запретили доступ в чат %s', - - 'privateActionLabel' : 'Один-на-один чат', - 'ignoreActionLabel' : 'Игнорировать', - 'unignoreActionLabel' : 'Отменить игнорирование', - - 'setSubjectActionLabel': 'Изменить топик', - - 'administratorMessageSubject' : 'Администратор', - - 'userJoinedRoom' : '%s вошёл в чат.', - 'userLeftRoom' : '%s вышел из чата.', - 'userHasBeenKickedFromRoom': '%s выброшен из чата.', - 'userHasBeenBannedFromRoom': '%s запрещён доступ в чат.', - - 'presenceUnknownWarningSubject': 'Уведомление:', - 'presenceUnknownWarning' : 'Этот пользователь вероятнее всего оффлайн.', - - 'dateFormat': 'mm.dd.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Модератор', - 'tooltipIgnored' : 'Вы игнорируете этого пользователя.', - 'tooltipEmoticons' : 'Смайлики', - 'tooltipSound' : 'Озвучивать новое частное сообщение', - 'tooltipAutoscroll' : 'Авто-прокручивание', - 'tooltipStatusmessage' : 'Показывать статус сообщения', - 'tooltipAdministration' : 'Администрирование чат комнаты', - 'tooltipUsercount' : 'Участники чата', - - 'enterRoomPassword' : 'Чат комната "%s" защищена паролем.', - 'enterRoomPasswordSubmit' : 'Войти в чат', - 'passwordEnteredInvalid' : 'Неверный пароль для комнаты "%s".', - - 'nicknameConflict': 'Это имя уже используется. Пожалуйста выберите другое имя.', - - 'errorMembersOnly': 'Вы не можете войти в чат "%s": Недостаточно прав доступа.', - 'errorMaxOccupantsReached': 'Вы не можете войти в чат "%s": Слишком много участников.', - - 'antiSpamMessage' : 'Пожалуйста не рассылайте спам. Вас заблокировали на короткое время.' - }, - 'ca': { - 'status': 'Estat: %s', - 'statusConnecting': 'Connectant...', - 'statusConnected' : 'Connectat', - 'statusDisconnecting': 'Desconnectant...', - 'statusDisconnected' : 'Desconnectat', - 'statusAuthfail': 'Ha fallat la autenticació', - - 'roomSubject' : 'Assumpte:', - 'messageSubmit': 'Enviar', - - 'labelUsername': 'Usuari:', - 'labelPassword': 'Clau:', - 'loginSubmit' : 'Entrar', - 'loginInvalid' : 'JID no vàlid', - - 'reason' : 'Raó:', - 'subject' : 'Assumpte:', - 'reasonWas' : 'La raó ha estat: %s.', - 'kickActionLabel' : 'Expulsar', - 'youHaveBeenKickedBy' : 'Has estat expulsat de %1$s per %2$s', - 'youHaveBeenKicked' : 'Has estat expulsat de %s', - 'banActionLabel' : 'Prohibir', - 'youHaveBeenBannedBy' : 'Has estat expulsat permanentment de %1$s per %2$s', - 'youHaveBeenBanned' : 'Has estat expulsat permanentment de %s', - - 'privateActionLabel' : 'Xat privat', - 'ignoreActionLabel' : 'Ignorar', - 'unignoreActionLabel' : 'No ignorar', - - 'setSubjectActionLabel': 'Canviar assumpte', - - 'administratorMessageSubject' : 'Administrador', - - 'userJoinedRoom' : '%s ha entrat a la sala.', - 'userLeftRoom' : '%s ha deixat la sala.', - 'userHasBeenKickedFromRoom': '%s ha estat expulsat de la sala.', - 'userHasBeenBannedFromRoom': '%s ha estat expulsat permanentment de la sala.', - - 'presenceUnknownWarningSubject': 'Atenció:', - 'presenceUnknownWarning' : 'Aquest usuari podria estar desconnectat ...', - - 'dateFormat': 'dd.mm.yyyy', - 'timeFormat': 'HH:MM:ss', - - 'tooltipRole' : 'Moderador', - 'tooltipIgnored' : 'Estàs ignorant aquest usuari', - 'tooltipEmoticons' : 'Emoticones', - 'tooltipSound' : 'Reproduir un so per a nous missatges', - 'tooltipAutoscroll' : 'Desplaçament automàtic', - 'tooltipStatusmessage' : 'Mostrar missatges d\'estat', - 'tooltipAdministration' : 'Administració de la sala', - 'tooltipUsercount' : 'Usuaris dins la sala', - - 'enterRoomPassword' : 'La sala "%s" està protegida amb contrasenya.', - 'enterRoomPasswordSubmit' : 'Entrar a la sala', - 'passwordEnteredInvalid' : 'Contrasenya incorrecta per a la sala "%s".', - - 'nicknameConflict': 'El nom d\'usuari ja s\'està utilitzant. Si us plau, escolleix-ne un altre.', - - 'errorMembersOnly': 'No pots unir-te a la sala "%s": no tens prous privilegis.', - 'errorMaxOccupantsReached': 'No pots unir-te a la sala "%s": hi ha masses participants.', - - 'antiSpamMessage' : 'Si us plau, no facis spam. Has estat bloquejat temporalment.' - } + en: { + status: "Status: %s", + statusConnecting: "Connecting...", + statusConnected: "Connected", + statusDisconnecting: "Disconnecting...", + statusDisconnected: "Disconnected", + statusAuthfail: "Authentication failed", + roomSubject: "Subject:", + messageSubmit: "Send", + labelUsername: "Username:", + labelNickname: "Nickname:", + labelPassword: "Password:", + loginSubmit: "Login", + loginInvalid: "Invalid JID", + reason: "Reason:", + subject: "Subject:", + reasonWas: "Reason was: %s.", + kickActionLabel: "Kick", + youHaveBeenKickedBy: "You have been kicked from %2$s by %1$s", + youHaveBeenKicked: "You have been kicked from %s", + banActionLabel: "Ban", + youHaveBeenBannedBy: "You have been banned from %1$s by %2$s", + youHaveBeenBanned: "You have been banned from %s", + privateActionLabel: "Private chat", + ignoreActionLabel: "Ignore", + unignoreActionLabel: "Unignore", + setSubjectActionLabel: "Change Subject", + administratorMessageSubject: "Administrator", + userJoinedRoom: "%s joined the room.", + userLeftRoom: "%s left the room.", + userHasBeenKickedFromRoom: "%s has been kicked from the room.", + userHasBeenBannedFromRoom: "%s has been banned from the room.", + userChangedNick: "%1$s has changed his nickname to %2$s.", + presenceUnknownWarningSubject: "Notice:", + presenceUnknownWarning: "This user might be offline. We can't track his presence.", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderator", + tooltipIgnored: "You ignore this user", + tooltipEmoticons: "Emoticons", + tooltipSound: "Play sound for new private messages", + tooltipAutoscroll: "Autoscroll", + tooltipStatusmessage: "Display status messages", + tooltipAdministration: "Room Administration", + tooltipUsercount: "Room Occupants", + enterRoomPassword: 'Room "%s" is password protected.', + enterRoomPasswordSubmit: "Join room", + passwordEnteredInvalid: 'Invalid password for room "%s".', + nicknameConflict: "Username already in use. Please choose another one.", + errorMembersOnly: 'You can\'t join room "%s": Insufficient rights.', + errorMaxOccupantsReached: 'You can\'t join room "%s": Too many occupants.', + errorAutojoinMissing: "No autojoin parameter set in configuration. Please set one to continue.", + antiSpamMessage: "Please do not spam. You have been blocked for a short-time." + }, + de: { + status: "Status: %s", + statusConnecting: "Verbinden...", + statusConnected: "Verbunden", + statusDisconnecting: "Verbindung trennen...", + statusDisconnected: "Verbindung getrennt", + statusAuthfail: "Authentifizierung fehlgeschlagen", + roomSubject: "Thema:", + messageSubmit: "Senden", + labelUsername: "Benutzername:", + labelNickname: "Spitzname:", + labelPassword: "Passwort:", + loginSubmit: "Anmelden", + loginInvalid: "Ungültige JID", + reason: "Begründung:", + subject: "Titel:", + reasonWas: "Begründung: %s.", + kickActionLabel: "Kick", + youHaveBeenKickedBy: "Du wurdest soeben aus dem Raum %1$s gekickt (%2$s)", + youHaveBeenKicked: "Du wurdest soeben aus dem Raum %s gekickt", + banActionLabel: "Ban", + youHaveBeenBannedBy: "Du wurdest soeben aus dem Raum %1$s verbannt (%2$s)", + youHaveBeenBanned: "Du wurdest soeben aus dem Raum %s verbannt", + privateActionLabel: "Privater Chat", + ignoreActionLabel: "Ignorieren", + unignoreActionLabel: "Nicht mehr ignorieren", + setSubjectActionLabel: "Thema ändern", + administratorMessageSubject: "Administrator", + userJoinedRoom: "%s hat soeben den Raum betreten.", + userLeftRoom: "%s hat soeben den Raum verlassen.", + userHasBeenKickedFromRoom: "%s ist aus dem Raum gekickt worden.", + userHasBeenBannedFromRoom: "%s ist aus dem Raum verbannt worden.", + userChangedNick: "%1$s hat den Nicknamen zu %2$s geändert.", + presenceUnknownWarningSubject: "Hinweis:", + presenceUnknownWarning: "Dieser Benutzer könnte bereits abgemeldet sein. Wir können seine Anwesenheit nicht verfolgen.", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderator", + tooltipIgnored: "Du ignorierst diesen Benutzer", + tooltipEmoticons: "Smileys", + tooltipSound: "Ton abspielen bei neuen privaten Nachrichten", + tooltipAutoscroll: "Autoscroll", + tooltipStatusmessage: "Statusnachrichten anzeigen", + tooltipAdministration: "Raum Administration", + tooltipUsercount: "Anzahl Benutzer im Raum", + enterRoomPassword: 'Raum "%s" ist durch ein Passwort geschützt.', + enterRoomPasswordSubmit: "Raum betreten", + passwordEnteredInvalid: 'Inkorrektes Passwort für Raum "%s".', + nicknameConflict: "Der Benutzername wird bereits verwendet. Bitte wähle einen anderen.", + errorMembersOnly: 'Du kannst den Raum "%s" nicht betreten: Ungenügende Rechte.', + errorMaxOccupantsReached: 'Du kannst den Raum "%s" nicht betreten: Benutzerlimit erreicht.', + errorAutojoinMissing: 'Keine "autojoin" Konfiguration gefunden. Bitte setze eine konfiguration um fortzufahren.', + antiSpamMessage: "Bitte nicht spammen. Du wurdest für eine kurze Zeit blockiert." + }, + fr: { + status: "Status : %s", + statusConnecting: "Connexion…", + statusConnected: "Connecté.", + statusDisconnecting: "Déconnexion…", + statusDisconnected: "Déconnecté.", + statusAuthfail: "L'authentification a échoué", + roomSubject: "Sujet :", + messageSubmit: "Envoyer", + labelUsername: "Nom d'utilisateur :", + labelPassword: "Mot de passe :", + loginSubmit: "Connexion", + loginInvalid: "JID invalide", + reason: "Motif :", + subject: "Titre :", + reasonWas: "Motif : %s.", + kickActionLabel: "Kick", + youHaveBeenKickedBy: "Vous avez été expulsé du salon %1$s (%2$s)", + youHaveBeenKicked: "Vous avez été expulsé du salon %s", + banActionLabel: "Ban", + youHaveBeenBannedBy: "Vous avez été banni du salon %1$s (%2$s)", + youHaveBeenBanned: "Vous avez été banni du salon %s", + privateActionLabel: "Chat privé", + ignoreActionLabel: "Ignorer", + unignoreActionLabel: "Ne plus ignorer", + setSubjectActionLabel: "Changer le sujet", + administratorMessageSubject: "Administrateur", + userJoinedRoom: "%s vient d'entrer dans le salon.", + userLeftRoom: "%s vient de quitter le salon.", + userHasBeenKickedFromRoom: "%s a été expulsé du salon.", + userHasBeenBannedFromRoom: "%s a été banni du salon.", + presenceUnknownWarningSubject: "Note :", + presenceUnknownWarning: "Cet utilisateur n'est malheureusement plus connecté, le message ne sera pas envoyé.", + dateFormat: "dd/mm/yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Modérateur", + tooltipIgnored: "Vous ignorez cette personne", + tooltipEmoticons: "Smileys", + tooltipSound: "Jouer un son lors de la réception de nouveaux messages privés", + tooltipAutoscroll: "Défilement automatique", + tooltipStatusmessage: "Messages d'état", + tooltipAdministration: "Administration du salon", + tooltipUsercount: "Nombre d'utilisateurs dans le salon", + enterRoomPassword: 'Le salon "%s" est protégé par un mot de passe.', + enterRoomPasswordSubmit: "Entrer dans le salon", + passwordEnteredInvalid: 'Le mot de passe pour le salon "%s" est invalide.', + nicknameConflict: "Le nom d'utilisateur est déjà utilisé. Veuillez en choisir un autre.", + errorMembersOnly: 'Vous ne pouvez pas entrer dans le salon "%s" : droits insuffisants.', + errorMaxOccupantsReached: 'Vous ne pouvez pas entrer dans le salon "%s": Limite d\'utilisateur atteint.', + antiSpamMessage: "Merci de ne pas envoyer de spam. Vous avez été bloqué pendant une courte période.." + }, + nl: { + status: "Status: %s", + statusConnecting: "Verbinding maken...", + statusConnected: "Verbinding is gereed", + statusDisconnecting: "Verbinding verbreken...", + statusDisconnected: "Verbinding is verbroken", + statusAuthfail: "Authenticatie is mislukt", + roomSubject: "Onderwerp:", + messageSubmit: "Verstuur", + labelUsername: "Gebruikersnaam:", + labelPassword: "Wachtwoord:", + loginSubmit: "Inloggen", + loginInvalid: "JID is onjuist", + reason: "Reden:", + subject: "Onderwerp:", + reasonWas: "De reden was: %s.", + kickActionLabel: "Verwijderen", + youHaveBeenKickedBy: "Je bent verwijderd van %1$s door %2$s", + youHaveBeenKicked: "Je bent verwijderd van %s", + banActionLabel: "Blokkeren", + youHaveBeenBannedBy: "Je bent geblokkeerd van %1$s door %2$s", + youHaveBeenBanned: "Je bent geblokkeerd van %s", + privateActionLabel: "Prive gesprek", + ignoreActionLabel: "Negeren", + unignoreActionLabel: "Niet negeren", + setSubjectActionLabel: "Onderwerp wijzigen", + administratorMessageSubject: "Beheerder", + userJoinedRoom: "%s komt de chat binnen.", + userLeftRoom: "%s heeft de chat verlaten.", + userHasBeenKickedFromRoom: "%s is verwijderd.", + userHasBeenBannedFromRoom: "%s is geblokkeerd.", + presenceUnknownWarningSubject: "Mededeling:", + presenceUnknownWarning: "Deze gebruiker is waarschijnlijk offline, we kunnen zijn/haar aanwezigheid niet vaststellen.", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderator", + tooltipIgnored: "Je negeert deze gebruiker", + tooltipEmoticons: "Emotie-iconen", + tooltipSound: "Speel een geluid af bij nieuwe privé berichten.", + tooltipAutoscroll: "Automatisch scrollen", + tooltipStatusmessage: "Statusberichten weergeven", + tooltipAdministration: "Instellingen", + tooltipUsercount: "Gebruikers", + enterRoomPassword: 'De Chatroom "%s" is met een wachtwoord beveiligd.', + enterRoomPasswordSubmit: "Ga naar Chatroom", + passwordEnteredInvalid: 'Het wachtwoord voor de Chatroom "%s" is onjuist.', + nicknameConflict: "De gebruikersnaam is reeds in gebruik. Probeer a.u.b. een andere gebruikersnaam.", + errorMembersOnly: 'Je kunt niet deelnemen aan de Chatroom "%s": Je hebt onvoldoende rechten.', + errorMaxOccupantsReached: 'Je kunt niet deelnemen aan de Chatroom "%s": Het maximum aantal gebruikers is bereikt.', + antiSpamMessage: "Het is niet toegestaan om veel berichten naar de server te versturen. Je bent voor een korte periode geblokkeerd." + }, + es: { + status: "Estado: %s", + statusConnecting: "Conectando...", + statusConnected: "Conectado", + statusDisconnecting: "Desconectando...", + statusDisconnected: "Desconectado", + statusAuthfail: "Falló la autenticación", + roomSubject: "Asunto:", + messageSubmit: "Enviar", + labelUsername: "Usuario:", + labelPassword: "Clave:", + loginSubmit: "Entrar", + loginInvalid: "JID no válido", + reason: "Razón:", + subject: "Asunto:", + reasonWas: "La razón fue: %s.", + kickActionLabel: "Expulsar", + youHaveBeenKickedBy: "Has sido expulsado de %1$s por %2$s", + youHaveBeenKicked: "Has sido expulsado de %s", + banActionLabel: "Prohibir", + youHaveBeenBannedBy: "Has sido expulsado permanentemente de %1$s por %2$s", + youHaveBeenBanned: "Has sido expulsado permanentemente de %s", + privateActionLabel: "Chat privado", + ignoreActionLabel: "Ignorar", + unignoreActionLabel: "No ignorar", + setSubjectActionLabel: "Cambiar asunto", + administratorMessageSubject: "Administrador", + userJoinedRoom: "%s se ha unido a la sala.", + userLeftRoom: "%s ha dejado la sala.", + userHasBeenKickedFromRoom: "%s ha sido expulsado de la sala.", + userHasBeenBannedFromRoom: "%s ha sido expulsado permanentemente de la sala.", + presenceUnknownWarningSubject: "Atención:", + presenceUnknownWarning: "Éste usuario podría estar desconectado..", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderador", + tooltipIgnored: "Ignoras a éste usuario", + tooltipEmoticons: "Emoticonos", + tooltipSound: "Reproducir un sonido para nuevos mensajes privados", + tooltipAutoscroll: "Desplazamiento automático", + tooltipStatusmessage: "Mostrar mensajes de estado", + tooltipAdministration: "Administración de la sala", + tooltipUsercount: "Usuarios en la sala", + enterRoomPassword: 'La sala "%s" está protegida mediante contraseña.', + enterRoomPasswordSubmit: "Unirse a la sala", + passwordEnteredInvalid: 'Contraseña incorrecta para la sala "%s".', + nicknameConflict: "El nombre de usuario ya está siendo utilizado. Por favor elija otro.", + errorMembersOnly: 'No se puede unir a la sala "%s": no tiene privilegios suficientes.', + errorMaxOccupantsReached: 'No se puede unir a la sala "%s": demasiados participantes.', + antiSpamMessage: "Por favor, no hagas spam. Has sido bloqueado temporalmente." + }, + cn: { + status: "状态: %s", + statusConnecting: "连接中...", + statusConnected: "已连接", + statusDisconnecting: "断开连接中...", + statusDisconnected: "已断开连接", + statusAuthfail: "认证失败", + roomSubject: "主题:", + messageSubmit: "发送", + labelUsername: "用户名:", + labelPassword: "密码:", + loginSubmit: "登录", + loginInvalid: "用户名不合法", + reason: "原因:", + subject: "主题:", + reasonWas: "原因是: %s.", + kickActionLabel: "踢除", + youHaveBeenKickedBy: "你在 %1$s 被管理者 %2$s 请出房间", + banActionLabel: "禁言", + youHaveBeenBannedBy: "你在 %1$s 被管理者 %2$s 禁言", + privateActionLabel: "单独对话", + ignoreActionLabel: "忽略", + unignoreActionLabel: "不忽略", + setSubjectActionLabel: "变更主题", + administratorMessageSubject: "管理员", + userJoinedRoom: "%s 加入房间", + userLeftRoom: "%s 离开房间", + userHasBeenKickedFromRoom: "%s 被请出这个房间", + userHasBeenBannedFromRoom: "%s 被管理者禁言", + presenceUnknownWarningSubject: "注意:", + presenceUnknownWarning: "这个会员可能已经下线,不能追踪到他的连接信息", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "管理", + tooltipIgnored: "你忽略了这个会员", + tooltipEmoticons: "表情", + tooltipSound: "新消息发音", + tooltipAutoscroll: "滚动条", + tooltipStatusmessage: "禁用状态消息", + tooltipAdministration: "房间管理", + tooltipUsercount: "房间占有者", + enterRoomPassword: '登录房间 "%s" 需要密码.', + enterRoomPasswordSubmit: "加入房间", + passwordEnteredInvalid: '登录房间 "%s" 的密码不正确', + nicknameConflict: "用户名已经存在,请另选一个", + errorMembersOnly: '您的权限不够,不能登录房间 "%s" ', + errorMaxOccupantsReached: '房间 "%s" 的人数已达上限,您不能登录', + antiSpamMessage: "因为您在短时间内发送过多的消息 服务器要阻止您一小段时间。" + }, + ja: { + status: "ステータス: %s", + statusConnecting: "接続中…", + statusConnected: "接続されました", + statusDisconnecting: "ディスコネクト中…", + statusDisconnected: "ディスコネクトされました", + statusAuthfail: "認証に失敗しました", + roomSubject: "トピック:", + messageSubmit: "送信", + labelUsername: "ユーザーネーム:", + labelPassword: "パスワード:", + loginSubmit: "ログイン", + loginInvalid: "ユーザーネームが正しくありません", + reason: "理由:", + subject: "トピック:", + reasonWas: "理由: %s。", + kickActionLabel: "キック", + youHaveBeenKickedBy: "あなたは%2$sにより%1$sからキックされました。", + youHaveBeenKicked: "あなたは%sからキックされました。", + banActionLabel: "アカウントバン", + youHaveBeenBannedBy: "あなたは%2$sにより%1$sからアカウントバンされました。", + youHaveBeenBanned: "あなたは%sからアカウントバンされました。", + privateActionLabel: "プライベートメッセージ", + ignoreActionLabel: "無視する", + unignoreActionLabel: "無視をやめる", + setSubjectActionLabel: "トピックを変える", + administratorMessageSubject: "管理者", + userJoinedRoom: "%sは入室しました。", + userLeftRoom: "%sは退室しました。", + userHasBeenKickedFromRoom: "%sは部屋からキックされました。", + userHasBeenBannedFromRoom: "%sは部屋からアカウントバンされました。", + presenceUnknownWarningSubject: "忠告:", + presenceUnknownWarning: "このユーザーのステータスは不明です。", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "モデレーター", + tooltipIgnored: "このユーザーを無視設定にしている", + tooltipEmoticons: "絵文字", + tooltipSound: "新しいメッセージが届くたびに音を鳴らす", + tooltipAutoscroll: "オートスクロール", + tooltipStatusmessage: "ステータスメッセージを表示", + tooltipAdministration: "部屋の管理", + tooltipUsercount: "この部屋の参加者の数", + enterRoomPassword: '"%s"の部屋に入るにはパスワードが必要です。', + enterRoomPasswordSubmit: "部屋に入る", + passwordEnteredInvalid: '"%s"のパスワードと異なるパスワードを入力しました。', + nicknameConflict: "このユーザーネームはすでに利用されているため、別のユーザーネームを選んでください。", + errorMembersOnly: '"%s"の部屋に入ることができません: 利用権限を満たしていません。', + errorMaxOccupantsReached: '"%s"の部屋に入ることができません: 参加者の数はすでに上限に達しました。', + antiSpamMessage: "スパムなどの行為はやめてください。あなたは一時的にブロックされました。" + }, + sv: { + status: "Status: %s", + statusConnecting: "Ansluter...", + statusConnected: "Ansluten", + statusDisconnecting: "Kopplar från...", + statusDisconnected: "Frånkopplad", + statusAuthfail: "Autentisering misslyckades", + roomSubject: "Ämne:", + messageSubmit: "Skicka", + labelUsername: "Användarnamn:", + labelPassword: "Lösenord:", + loginSubmit: "Logga in", + loginInvalid: "Ogiltigt JID", + reason: "Anledning:", + subject: "Ämne:", + reasonWas: "Anledningen var: %s.", + kickActionLabel: "Sparka ut", + youHaveBeenKickedBy: "Du har blivit utsparkad från %2$s av %1$s", + youHaveBeenKicked: "Du har blivit utsparkad från %s", + banActionLabel: "Bannlys", + youHaveBeenBannedBy: "Du har blivit bannlyst från %1$s av %2$s", + youHaveBeenBanned: "Du har blivit bannlyst från %s", + privateActionLabel: "Privat chatt", + ignoreActionLabel: "Blockera", + unignoreActionLabel: "Avblockera", + setSubjectActionLabel: "Ändra ämne", + administratorMessageSubject: "Administratör", + userJoinedRoom: "%s kom in i rummet.", + userLeftRoom: "%s har lämnat rummet.", + userHasBeenKickedFromRoom: "%s har blivit utsparkad ur rummet.", + userHasBeenBannedFromRoom: "%s har blivit bannlyst från rummet.", + presenceUnknownWarningSubject: "Notera:", + presenceUnknownWarning: "Denna användare kan vara offline. Vi kan inte följa dennes närvaro.", + dateFormat: "yyyy-mm-dd", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderator", + tooltipIgnored: "Du blockerar denna användare", + tooltipEmoticons: "Smilies", + tooltipSound: "Spela upp ett ljud vid nytt privat meddelande", + tooltipAutoscroll: "Autoskrolla", + tooltipStatusmessage: "Visa statusmeddelanden", + tooltipAdministration: "Rumadministrering", + tooltipUsercount: "Antal användare i rummet", + enterRoomPassword: 'Rummet "%s" är lösenordsskyddat.', + enterRoomPasswordSubmit: "Anslut till rum", + passwordEnteredInvalid: 'Ogiltigt lösenord för rummet "%s".', + nicknameConflict: "Upptaget användarnamn. Var god välj ett annat.", + errorMembersOnly: 'Du kan inte ansluta till rummet "%s": Otillräckliga rättigheter.', + errorMaxOccupantsReached: 'Du kan inte ansluta till rummet "%s": Rummet är fullt.', + antiSpamMessage: "Var god avstå från att spamma. Du har blivit blockerad för en kort stund." + }, + it: { + status: "Stato: %s", + statusConnecting: "Connessione...", + statusConnected: "Connessione", + statusDisconnecting: "Disconnessione...", + statusDisconnected: "Disconnesso", + statusAuthfail: "Autenticazione fallita", + roomSubject: "Oggetto:", + messageSubmit: "Invia", + labelUsername: "Nome utente:", + labelPassword: "Password:", + loginSubmit: "Login", + loginInvalid: "JID non valido", + reason: "Ragione:", + subject: "Oggetto:", + reasonWas: "Ragione precedente: %s.", + kickActionLabel: "Espelli", + youHaveBeenKickedBy: "Sei stato espulso da %2$s da %1$s", + youHaveBeenKicked: "Sei stato espulso da %s", + banActionLabel: "Escluso", + youHaveBeenBannedBy: "Sei stato escluso da %1$s da %2$s", + youHaveBeenBanned: "Sei stato escluso da %s", + privateActionLabel: "Stanza privata", + ignoreActionLabel: "Ignora", + unignoreActionLabel: "Non ignorare", + setSubjectActionLabel: "Cambia oggetto", + administratorMessageSubject: "Amministratore", + userJoinedRoom: "%s si è unito alla stanza.", + userLeftRoom: "%s ha lasciato la stanza.", + userHasBeenKickedFromRoom: "%s è stato espulso dalla stanza.", + userHasBeenBannedFromRoom: "%s è stato escluso dalla stanza.", + presenceUnknownWarningSubject: "Nota:", + presenceUnknownWarning: "Questo utente potrebbe essere offline. Non possiamo tracciare la sua presenza.", + dateFormat: "dd/mm/yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderatore", + tooltipIgnored: "Stai ignorando questo utente", + tooltipEmoticons: "Emoticons", + tooltipSound: "Riproduci un suono quando arrivano messaggi privati", + tooltipAutoscroll: "Autoscroll", + tooltipStatusmessage: "Mostra messaggi di stato", + tooltipAdministration: "Amministrazione stanza", + tooltipUsercount: "Partecipanti alla stanza", + enterRoomPassword: 'La stanza "%s" è protetta da password.', + enterRoomPasswordSubmit: "Unisciti alla stanza", + passwordEnteredInvalid: 'Password non valida per la stanza "%s".', + nicknameConflict: "Nome utente già in uso. Scegline un altro.", + errorMembersOnly: 'Non puoi unirti alla stanza "%s": Permessi insufficienti.', + errorMaxOccupantsReached: 'Non puoi unirti alla stanza "%s": Troppi partecipanti.', + antiSpamMessage: "Per favore non scrivere messaggi pubblicitari. Sei stato bloccato per un po' di tempo." + }, + pt: { + status: "Status: %s", + statusConnecting: "Conectando...", + statusConnected: "Conectado", + statusDisconnecting: "Desligando...", + statusDisconnected: "Desligado", + statusAuthfail: "Falha na autenticação", + roomSubject: "Assunto:", + messageSubmit: "Enviar", + labelUsername: "Usuário:", + labelPassword: "Senha:", + loginSubmit: "Entrar", + loginInvalid: "JID inválido", + reason: "Motivo:", + subject: "Assunto:", + reasonWas: "O motivo foi: %s.", + kickActionLabel: "Excluir", + youHaveBeenKickedBy: "Você foi excluido de %1$s por %2$s", + youHaveBeenKicked: "Você foi excluido de %s", + banActionLabel: "Bloquear", + youHaveBeenBannedBy: "Você foi excluido permanentemente de %1$s por %2$s", + youHaveBeenBanned: "Você foi excluido permanentemente de %s", + privateActionLabel: "Bate-papo privado", + ignoreActionLabel: "Ignorar", + unignoreActionLabel: "Não ignorar", + setSubjectActionLabel: "Trocar Assunto", + administratorMessageSubject: "Administrador", + userJoinedRoom: "%s entrou na sala.", + userLeftRoom: "%s saiu da sala.", + userHasBeenKickedFromRoom: "%s foi excluido da sala.", + userHasBeenBannedFromRoom: "%s foi excluido permanentemente da sala.", + presenceUnknownWarning: "Este usuário pode estar desconectado. Não é possível determinar o status.", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderador", + tooltipIgnored: "Você ignora este usuário", + tooltipEmoticons: "Emoticons", + tooltipSound: "Reproduzir o som para novas mensagens privados", + tooltipAutoscroll: "Deslocamento automático", + tooltipStatusmessage: "Mostrar mensagens de status", + tooltipAdministration: "Administração da sala", + tooltipUsercount: "Usuários na sala", + enterRoomPassword: 'A sala "%s" é protegida por senha.', + enterRoomPasswordSubmit: "Junte-se à sala", + passwordEnteredInvalid: 'Senha incorreta para a sala "%s".', + nicknameConflict: "O nome de usuário já está em uso. Por favor, escolha outro.", + errorMembersOnly: 'Você não pode participar da sala "%s": privilégios insuficientes.', + errorMaxOccupantsReached: 'Você não pode participar da sala "%s": muitos participantes.', + antiSpamMessage: "Por favor, não envie spam. Você foi bloqueado temporariamente." + }, + pt_br: { + status: "Estado: %s", + statusConnecting: "Conectando...", + statusConnected: "Conectado", + statusDisconnecting: "Desconectando...", + statusDisconnected: "Desconectado", + statusAuthfail: "Autenticação falhou", + roomSubject: "Assunto:", + messageSubmit: "Enviar", + labelUsername: "Usuário:", + labelPassword: "Senha:", + loginSubmit: "Entrar", + loginInvalid: "JID inválido", + reason: "Motivo:", + subject: "Assunto:", + reasonWas: "Motivo foi: %s.", + kickActionLabel: "Derrubar", + youHaveBeenKickedBy: "Você foi derrubado de %2$s por %1$s", + youHaveBeenKicked: "Você foi derrubado de %s", + banActionLabel: "Banir", + youHaveBeenBannedBy: "Você foi banido de %1$s por %2$s", + youHaveBeenBanned: "Você foi banido de %s", + privateActionLabel: "Conversa privada", + ignoreActionLabel: "Ignorar", + unignoreActionLabel: "Não ignorar", + setSubjectActionLabel: "Mudar Assunto", + administratorMessageSubject: "Administrador", + userJoinedRoom: "%s entrou na sala.", + userLeftRoom: "%s saiu da sala.", + userHasBeenKickedFromRoom: "%s foi derrubado da sala.", + userHasBeenBannedFromRoom: "%s foi banido da sala.", + presenceUnknownWarningSubject: "Aviso:", + presenceUnknownWarning: "Este usuário pode estar desconectado.. Não conseguimos rastrear sua presença..", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderador", + tooltipIgnored: "Você ignora este usuário", + tooltipEmoticons: "Emoticons", + tooltipSound: "Tocar som para novas mensagens privadas", + tooltipAutoscroll: "Auto-rolagem", + tooltipStatusmessage: "Exibir mensagens de estados", + tooltipAdministration: "Administração de Sala", + tooltipUsercount: "Participantes da Sala", + enterRoomPassword: 'Sala "%s" é protegida por senha.', + enterRoomPasswordSubmit: "Entrar na sala", + passwordEnteredInvalid: 'Senha inváida para sala "%s".', + nicknameConflict: "Nome de usuário já em uso. Por favor escolha outro.", + errorMembersOnly: 'Você não pode entrar na sala "%s": privilégios insuficientes.', + errorMaxOccupantsReached: 'Você não pode entrar na sala "%s": máximo de participantes atingido.', + antiSpamMessage: "Por favor, não faça spam. Você foi bloqueado temporariamente." + }, + ru: { + status: "Статус: %s", + statusConnecting: "Подключение...", + statusConnected: "Подключено", + statusDisconnecting: "Отключение...", + statusDisconnected: "Отключено", + statusAuthfail: "Неверный логин", + roomSubject: "Топик:", + messageSubmit: "Послать", + labelUsername: "Имя:", + labelPassword: "Пароль:", + loginSubmit: "Логин", + loginInvalid: "Неверный JID", + reason: "Причина:", + subject: "Топик:", + reasonWas: "Причина была: %s.", + kickActionLabel: "Выбросить", + youHaveBeenKickedBy: "Пользователь %1$s выбросил вас из чата %2$s", + youHaveBeenKicked: "Вас выбросили из чата %s", + banActionLabel: "Запретить доступ", + youHaveBeenBannedBy: "Пользователь %1$s запретил вам доступ в чат %2$s", + youHaveBeenBanned: "Вам запретили доступ в чат %s", + privateActionLabel: "Один-на-один чат", + ignoreActionLabel: "Игнорировать", + unignoreActionLabel: "Отменить игнорирование", + setSubjectActionLabel: "Изменить топик", + administratorMessageSubject: "Администратор", + userJoinedRoom: "%s вошёл в чат.", + userLeftRoom: "%s вышел из чата.", + userHasBeenKickedFromRoom: "%s выброшен из чата.", + userHasBeenBannedFromRoom: "%s запрещён доступ в чат.", + presenceUnknownWarningSubject: "Уведомление:", + presenceUnknownWarning: "Этот пользователь вероятнее всего оффлайн.", + dateFormat: "mm.dd.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Модератор", + tooltipIgnored: "Вы игнорируете этого пользователя.", + tooltipEmoticons: "Смайлики", + tooltipSound: "Озвучивать новое частное сообщение", + tooltipAutoscroll: "Авто-прокручивание", + tooltipStatusmessage: "Показывать статус сообщения", + tooltipAdministration: "Администрирование чат комнаты", + tooltipUsercount: "Участники чата", + enterRoomPassword: 'Чат комната "%s" защищена паролем.', + enterRoomPasswordSubmit: "Войти в чат", + passwordEnteredInvalid: 'Неверный пароль для комнаты "%s".', + nicknameConflict: "Это имя уже используется. Пожалуйста выберите другое имя.", + errorMembersOnly: 'Вы не можете войти в чат "%s": Недостаточно прав доступа.', + errorMaxOccupantsReached: 'Вы не можете войти в чат "%s": Слишком много участников.', + antiSpamMessage: "Пожалуйста не рассылайте спам. Вас заблокировали на короткое время." + }, + ca: { + status: "Estat: %s", + statusConnecting: "Connectant...", + statusConnected: "Connectat", + statusDisconnecting: "Desconnectant...", + statusDisconnected: "Desconnectat", + statusAuthfail: "Ha fallat la autenticació", + roomSubject: "Assumpte:", + messageSubmit: "Enviar", + labelUsername: "Usuari:", + labelPassword: "Clau:", + loginSubmit: "Entrar", + loginInvalid: "JID no vàlid", + reason: "Raó:", + subject: "Assumpte:", + reasonWas: "La raó ha estat: %s.", + kickActionLabel: "Expulsar", + youHaveBeenKickedBy: "Has estat expulsat de %1$s per %2$s", + youHaveBeenKicked: "Has estat expulsat de %s", + banActionLabel: "Prohibir", + youHaveBeenBannedBy: "Has estat expulsat permanentment de %1$s per %2$s", + youHaveBeenBanned: "Has estat expulsat permanentment de %s", + privateActionLabel: "Xat privat", + ignoreActionLabel: "Ignorar", + unignoreActionLabel: "No ignorar", + setSubjectActionLabel: "Canviar assumpte", + administratorMessageSubject: "Administrador", + userJoinedRoom: "%s ha entrat a la sala.", + userLeftRoom: "%s ha deixat la sala.", + userHasBeenKickedFromRoom: "%s ha estat expulsat de la sala.", + userHasBeenBannedFromRoom: "%s ha estat expulsat permanentment de la sala.", + presenceUnknownWarningSubject: "Atenció:", + presenceUnknownWarning: "Aquest usuari podria estar desconnectat ...", + dateFormat: "dd.mm.yyyy", + timeFormat: "HH:MM:ss", + tooltipRole: "Moderador", + tooltipIgnored: "Estàs ignorant aquest usuari", + tooltipEmoticons: "Emoticones", + tooltipSound: "Reproduir un so per a nous missatges", + tooltipAutoscroll: "Desplaçament automàtic", + tooltipStatusmessage: "Mostrar missatges d'estat", + tooltipAdministration: "Administració de la sala", + tooltipUsercount: "Usuaris dins la sala", + enterRoomPassword: 'La sala "%s" està protegida amb contrasenya.', + enterRoomPasswordSubmit: "Entrar a la sala", + passwordEnteredInvalid: 'Contrasenya incorrecta per a la sala "%s".', + nicknameConflict: "El nom d'usuari ja s'està utilitzant. Si us plau, escolleix-ne un altre.", + errorMembersOnly: 'No pots unir-te a la sala "%s": no tens prous privilegis.', + errorMaxOccupantsReached: 'No pots unir-te a la sala "%s": hi ha masses participants.', + antiSpamMessage: "Si us plau, no facis spam. Has estat bloquejat temporalment." + } }; +//# sourceMappingURL=candy.bundle.map \ No newline at end of file diff --git a/candy.bundle.map b/candy.bundle.map new file mode 100644 index 00000000..c78fad81 --- /dev/null +++ b/candy.bundle.map @@ -0,0 +1 @@ +{"version":3,"file":"candy.bundle.js","sources":["src/candy.js","src/core.js","src/view.js","src/util.js","src/core/action.js","src/core/chatRoom.js","src/core/chatRoster.js","src/core/chatUser.js","src/core/event.js","src/view/observer.js","src/view/pane.js","src/view/template.js","src/view/translation.js"],"names":["Candy","self","$","about","name","version","init","service","options","viewClass","View","view","Core","core","jQuery","Strophe","_connection","_service","_user","_rooms","_anonymousConnection","_status","_options","autojoin","undefined","debug","disableWindowUnload","presencePriority","resource","_addNamespace","value","addNamespace","_addNamespaces","_getEscapedJidFromJid","jid","node","getNodeFromJid","domain","getDomainFromJid","escapeNode","extend","window","console","log","Function","prototype","bind","call","apply","arguments","Connection","rawInput","rawOutput","caps","onbeforeunload","onWindowUnload","registerEventHandlers","addHandler","Event","Jabber","Version","NS","VERSION","Presence","Message","Bookmarks","PRIVATE","Room","Disco","DISCO_INFO","disco","_onDiscoInfo","_onDiscoItems","DISCO_ITEMS","_delegateCapabilities","CAPS","connect","jidOrHost","password","nick","reset","triggerHandler","connection","indexOf","Connect","ChatUser","Login","attach","sid","rid","disconnect","connected","each","getRooms","Action","Leave","this","getJid","handler","ns","type","id","from","getUser","setUser","user","getConnection","removeRoom","roomJid","getStropheStatus","setStropheStatus","status","isAnonymousConnection","getOptions","getRoom","sync","flush","data","_current","container","language","resources","messages","limit","remove","crop","message","nickname","body","roster","_setupTranslation","i18n","load","Translation","_registerObservers","on","Observer","Chat","AutojoinMissing","update","PresenceError","_registerWindowHandlers","Util","getIeVersion","document","focusin","Pane","Window","onFocus","focusout","onBlur","focus","blur","resize","fitTabs","_initToolbar","Toolbar","_delegateTooltips","delegate","Tooltip","show","Parser","setEmoticonPath","html","Mustache","to_html","Template","pane","tooltipEmoticons","_","tooltipSound","tooltipAutoscroll","tooltipStatusmessage","tooltipAdministration","tooltipUsercount","resourcesPath","tabs","rooms","modal","toolbar","soundcontrol","getCurrent","jidToId","MD5","hexdigest","escapeJid","getResourceFromJid","unescapeJid","unescapeNode","str","len","length","substr","setCookie","lifetime_days","exp","Date","setDate","getDate","cookie","toUTCString","cookieExists","getCookie","regex","RegExp","escape","matches","exec","deleteCookie","getPosLeftAccordingToWindowBounds","elem","pos","windowWidth","width","elemWidth","outerWidth","marginDiff","backgroundPositionAlignment","px","getPosTopAccordingToWindowBounds","windowHeight","height","elemHeight","outerHeight","localizedTime","dateTime","date","iso8601toDate","toDateString","format","timestamp","parse","isNaN","struct","minutesOffset","getTimezoneOffset","replace","isEmptyObject","obj","prop","hasOwnProperty","forceRedraw","css","display","setTimeout","ie","undef","v","div","createElement","all","getElementsByTagName","innerHTML","_emoticonPath","path","emoticons","plain","image","emotify","text","i","linkify","nl2br","msg","send","$iq","to","attr","c","os","navigator","userAgent","SetNickname","Array","roomNick","presence","$pres","getUniqueId","Roster","xmlns","CLIENT","ROSTER","tree","el","pres","t","toString","up","generateCapsAttrs","appendChild","Services","Autojoin","sendIQ","BOOKMARKS","isArray","Join","valueOf","split","ResetIgnoreList","getEscapedJid","PRIVACY","action","order","RemoveIgnoreList","GetIgnoreList","iq","iqId","PrivacyList","SetIgnoreListActive","GetJidIfAnonymous","conn","getNick","MUC","muc","leave","trim","IgnoreUnignore","userJid","addToOrRemoveFromPrivacyList","UpdatePrivacyList","currentUser","privacyList","getPrivacyList","index","Admin","UserAction","reason","itemObj","role","affiliation","MUC_ADMIN","SetSubject","subject","setTopic","ChatRoom","room","ChatRoster","setName","getName","setRoster","getRoster","items","add","get","getAll","ROLE_MODERATOR","AFFILIATION_OWNER","privacyLists","customData","previousNick","setJid","setNick","getRole","getAffiliation","isModerator","list","splice","push","setPrivacyLists","lists","isInPrivacyList","setCustomData","getCustomData","setPreviousNick","getPreviousNick","presetJid","Status","CONNECTED","ATTACHED","DISCONNECTED","AUTHFAIL","CONNECTING","DISCONNECTING","AUTHENTICATING","ERROR","CONNFAIL","children","stanza","item","PrivacyListError","fromJid","toJid","getBareJidFromJid","roomName","find","actor","code","identity","presenceType","nickAssign","nickChange","l","$status","tagName","toLowerCase","error","bareRoomJid","isNoConferenceRoomJid","delay","DELAY","_showConnectedMessageModal","event","args","eventName","Modal","hide","showLoginForm","adminMessage","onInfoMessage","close","notifyPrivateChats","actorName","actionLabel","translationParams","Context","adminMessageReason","_action","_reason","evtData","PrivateRoom","setStatus","showEnterPasswordForm","showNicknameConflictForm","showError","setSubject","infoMessage","open","_hasFocus","_plainTitle","title","_unreadMessagesCount","autoscroll","hasFocus","increaseUnreadMessages","renderUnreadMessages","reduceUnreadMessages","num","clearUnreadMessages","count","unreadmessages","setFocusToForm","addTab","roomType","roomId","tab","privateUserChat","appendTo","click","tabClick","tabClose","getTab","removeTab","setActiveTab","addClass","removeClass","unreadElem","parseInt","e","currentRoomJid","scrollPosition","getPane","scrollTop","preventDefault","parent","allTabsClosed","availableWidth","innerWidth","tabsWidth","overflow","tabDiffToRealWidth","tabWidth","Math","floor","sender","time","toGMTString","appendToMessagePane","scrollToBottom","_supportsNativeAudio","showEmoticonsMenu","currentTarget","stopPropagation","onAutoscrollControlClick","a","canPlayType","onSoundControlClick","onStatusMessageControlClick","context","me","updateUsercount","usercount","playSound","onPlaySound","Audio","play","chatSoundPlayer","getElementById","SetVariable","control","hasClass","toggleClass","onScrollToStoredPosition","onScrollToBottom","showCloseControl","showSpinner","hideCloseControl","hideSpinner","stop","fadeIn","callback","fadeOut","keydown","which","form","_labelNickname","_labelUsername","_labelPassword","_loginSubmit","displayPassword","displayUsername","displayNickname","submit","username","val","enterPasswordForm","_label","_joinSubmit","nicknameConflictForm","replacements","displayError","_error","content","tooltip","target","append","offset","posLeft","left","posTop","top","mouseleave","menu","links","menulinks","getMenuLinks","clickHandler","link","class","label","element","initialMenuLinks","requiredPermission","private","ignore","ignoreUser","unignore","unignoreUser","kick","contextModalForm","_submit","ban","input","emoticon","messageCount","_messageSubmit","_userOnline","_roomSubject","openRooms","last","sliceMessagePane","slice","messagePane","roomPane","chatPane","addIgnoreIcon","removeIgnoreIcon","subPane","changeDataUserJidIfUserIsMe","roomElement","switchToRoom","messageForm","removeAttr","changeNick","previousPrivateRoomJid","newPrivateRoomJid","previousPrivateRoomId","newPrivateRoomId","roomTabElement","userId","usercountDiff","userElem","displayNick","tooltipRole","tooltipIgnored","userInserted","rosterPane","userSortCompare","toUpperCase","before","showJoinAnimation","replaceWith","opacity","userClick","leaveAnimation","rosterUserId","$rosterUserElem","is","joinAnimation","elementId","slideDown","animate","complete","slideUp","previousUserJid","substring","renderEvtData","template","templateData","displayName","en","statusConnecting","statusConnected","statusDisconnecting","statusDisconnected","statusAuthfail","roomSubject","messageSubmit","labelUsername","labelNickname","labelPassword","loginSubmit","loginInvalid","reasonWas","kickActionLabel","youHaveBeenKickedBy","youHaveBeenKicked","banActionLabel","youHaveBeenBannedBy","youHaveBeenBanned","privateActionLabel","ignoreActionLabel","unignoreActionLabel","setSubjectActionLabel","administratorMessageSubject","userJoinedRoom","userLeftRoom","userHasBeenKickedFromRoom","userHasBeenBannedFromRoom","userChangedNick","presenceUnknownWarningSubject","presenceUnknownWarning","dateFormat","timeFormat","enterRoomPassword","enterRoomPasswordSubmit","passwordEnteredInvalid","nicknameConflict","errorMembersOnly","errorMaxOccupantsReached","errorAutojoinMissing","antiSpamMessage","de","fr","nl","es","cn","ja","sv","it","pt","pt_br","ru","ca"],"mappings":"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"} \ No newline at end of file diff --git a/candy.min.js b/candy.min.js index 19c50a31..dc9713c6 100644 --- a/candy.min.js +++ b/candy.min.js @@ -1,2 +1,2 @@ -"use strict";var Candy=function(a,b){return a.about={name:"Candy",version:"1.6.0-beta3"},a.init=function(c,d){d.viewClass||(d.viewClass=a.View),d.viewClass.init(b("#candy"),d.view),a.Core.init(c,d.core)},a}(Candy||{},jQuery);Candy.Core=function(a,b,c){var d,e=null,f=null,g=null,h={},i=!1,j={autojoin:void 0,debug:!1,disableWindowUnload:!1,presencePriority:1,resource:Candy.about.name},k=function(a,c){b.addNamespace(a,c)},l=function(){k("PRIVATE","jabber:iq:private"),k("BOOKMARKS","storage:bookmarks"),k("PRIVACY","jabber:iq:privacy"),k("DELAY","jabber:x:delay")},m=function(a){var c=b.getNodeFromJid(a),d=b.getDomainFromJid(a);return c?b.escapeNode(c)+"@"+d:d};return a.init=function(d,g){f=d,c.extend(!0,j,g),j.debug&&(a.log=function(a){try{void 0!==typeof window.console&&void 0!==typeof window.console.log&&console.log(a)}catch(b){}},a.log("[Init] Debugging enabled")),l(),e=new b.Connection(f),e.rawInput=a.rawInput.bind(a),e.rawOutput=a.rawOutput.bind(a),e.caps.node="https://candy-chat.github.io/candy/",j.disableWindowUnload||(window.onbeforeunload=a.onWindowUnload)},a.registerEventHandlers=function(){a.addHandler(a.Event.Jabber.Version,b.NS.VERSION,"iq"),a.addHandler(a.Event.Jabber.Presence,null,"presence"),a.addHandler(a.Event.Jabber.Message,null,"message"),a.addHandler(a.Event.Jabber.Bookmarks,b.NS.PRIVATE,"iq"),a.addHandler(a.Event.Jabber.Room.Disco,b.NS.DISCO_INFO,"iq","result"),a.addHandler(e.disco._onDiscoInfo.bind(e.disco),b.NS.DISCO_INFO,"iq","get"),a.addHandler(e.disco._onDiscoItems.bind(e.disco),b.NS.DISCO_ITEMS,"iq","get"),a.addHandler(e.caps._delegateCapabilities.bind(e.caps),b.NS.CAPS)},a.connect=function(d,f,h){e.reset(),a.registerEventHandlers(),c(Candy).triggerHandler("candy:core.before-connect",{connection:e}),i=i?!0:d&&d.indexOf("@")<0,d&&f?(e.connect(m(d)+"/"+j.resource,f,Candy.Core.Event.Strophe.Connect),g=h?new a.ChatUser(d,h):new a.ChatUser(d,b.getNodeFromJid(d))):d&&h?(e.connect(m(d)+"/"+j.resource,null,Candy.Core.Event.Strophe.Connect),g=new a.ChatUser(null,h)):d?Candy.Core.Event.Login(d):Candy.Core.Event.Login()},a.attach=function(c,d,f){g=new a.ChatUser(c,b.getNodeFromJid(c)),a.registerEventHandlers(),e.attach(c,d,f,Candy.Core.Event.Strophe.Connect)},a.disconnect=function(){e.connected&&(c.each(a.getRooms(),function(){Candy.Core.Action.Jabber.Room.Leave(this.getJid())}),e.disconnect())},a.addHandler=function(a,b,c,d,f,g,h){return e.addHandler(a,b,c,d,f,g,h)},a.getUser=function(){return g},a.setUser=function(a){g=a},a.getConnection=function(){return e},a.removeRoom=function(a){delete h[a]},a.getRooms=function(){return h},a.getStropheStatus=function(){return d},a.setStropheStatus=function(a){d=a},a.isAnonymousConnection=function(){return i},a.getOptions=function(){return j},a.getRoom=function(a){return h[a]?h[a]:null},a.onWindowUnload=function(){e.options.sync=!0,a.disconnect(),e.flush()},a.rawInput=function(a){this.log("RECV: "+a)},a.rawOutput=function(a){this.log("SENT: "+a)},a.log=function(){},a}(Candy.Core||{},Strophe,jQuery),Candy.View=function(a,b){var c={container:null,roomJid:null},d={language:"en",resources:"res/",messages:{limit:2e3,remove:500},crop:{message:{nickname:15,body:1e3},roster:{nickname:15}}},e=function(c){b.i18n.load(a.Translation[c])},f=function(){b(Candy).on("candy:core.chat.connection",a.Observer.Chat.Connection),b(Candy).on("candy:core.chat.message",a.Observer.Chat.Message),b(Candy).on("candy:core.login",a.Observer.Login),b(Candy).on("candy:core.autojoin-missing",a.Observer.AutojoinMissing),b(Candy).on("candy:core.presence",a.Observer.Presence.update),b(Candy).on("candy:core.presence.leave",a.Observer.Presence.update),b(Candy).on("candy:core.presence.room",a.Observer.Presence.update),b(Candy).on("candy:core.presence.error",a.Observer.PresenceError),b(Candy).on("candy:core.message",a.Observer.Message)},g=function(){Candy.Util.getIeVersion()<9?b(document).focusin(Candy.View.Pane.Window.onFocus).focusout(Candy.View.Pane.Window.onBlur):b(window).focus(Candy.View.Pane.Window.onFocus).blur(Candy.View.Pane.Window.onBlur),b(window).resize(Candy.View.Pane.Chat.fitTabs)},h=function(){a.Pane.Chat.Toolbar.init()},i=function(){b("body").delegate("li[data-tooltip]","mouseenter",Candy.View.Pane.Chat.Tooltip.show)};return a.init=function(a,j){b.extend(!0,d,j),e(d.language),Candy.Util.Parser.setEmoticonPath(this.getOptions().resources+"img/emoticons/"),c.container=a,c.container.html(Mustache.to_html(Candy.View.Template.Chat.pane,{tooltipEmoticons:b.i18n._("tooltipEmoticons"),tooltipSound:b.i18n._("tooltipSound"),tooltipAutoscroll:b.i18n._("tooltipAutoscroll"),tooltipStatusmessage:b.i18n._("tooltipStatusmessage"),tooltipAdministration:b.i18n._("tooltipAdministration"),tooltipUsercount:b.i18n._("tooltipUsercount"),resourcesPath:this.getOptions().resources},{tabs:Candy.View.Template.Chat.tabs,rooms:Candy.View.Template.Chat.rooms,modal:Candy.View.Template.Chat.modal,toolbar:Candy.View.Template.Chat.toolbar,soundcontrol:Candy.View.Template.Chat.soundcontrol})),g(),h(),f(),i()},a.getCurrent=function(){return c},a.getOptions=function(){return d},a}(Candy.View||{},jQuery),Candy.Util=function(a,b){a.jidToId=function(a){return MD5.hexdigest(a)},a.escapeJid=function(a){var b=Strophe.escapeNode(Strophe.getNodeFromJid(a)),c=Strophe.getDomainFromJid(a),d=Strophe.getResourceFromJid(a);return a=b+"@"+c,d&&(a+="/"+d),a},a.unescapeJid=function(a){var b=Strophe.unescapeNode(Strophe.getNodeFromJid(a)),c=Strophe.getDomainFromJid(a),d=Strophe.getResourceFromJid(a);return a=b+"@"+c,d&&(a+="/"+d),a},a.crop=function(a,b){return a.length>b&&(a=a.substr(0,b-3)+"..."),a},a.setCookie=function(a,b,c){var d=new Date;d.setDate((new Date).getDate()+c),document.cookie=a+"="+b+";expires="+d.toUTCString()+";path=/"},a.cookieExists=function(a){return document.cookie.indexOf(a)>-1},a.getCookie=function(a){if(document.cookie){var b=new RegExp(escape(a)+"=([^;]*)","gm"),c=b.exec(document.cookie);if(c)return c[1]}},a.deleteCookie=function(a){document.cookie=a+"=;expires=Thu, 01-Jan-70 00:00:01 GMT;path=/"},a.getPosLeftAccordingToWindowBounds=function(a,c){var d=b(document).width(),e=a.outerWidth(),f=e-a.outerWidth(!0),g="left";return c+e>=d&&(c-=e-f,g="right"),{px:c,backgroundPositionAlignment:g}},a.getPosTopAccordingToWindowBounds=function(a,c){var d=b(document).height(),e=a.outerHeight(),f=e-a.outerHeight(!0),g="top";return c+e>=d&&(c-=e-f,g="bottom"),{px:c,backgroundPositionAlignment:g}},a.localizedTime=function(c){if(void 0===c)return void 0;var d=a.iso8601toDate(c);return d.format(d.toDateString()===(new Date).toDateString()?b.i18n._("timeFormat"):b.i18n._("dateFormat"))},a.iso8601toDate=function(a){var b=Date.parse(a);if(isNaN(b)){var c=/^(\d{4}|[+\-]\d{6})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?))?/.exec(a);if(c){var d=0;return"Z"!==c[8]&&(d=60*+c[10]+ +c[11],"+"===c[9]&&(d=-d)),d-=(new Date).getTimezoneOffset(),new Date(+c[1],+c[2]-1,+c[3],+c[4],+c[5]+d,+c[6],c[7]?+c[7].substr(0,3):0)}b=Date.parse(a.replace(/^(\d{4})(\d{2})(\d{2})/,"$1-$2-$3")+"Z")}return new Date(b)},a.isEmptyObject=function(a){var b;for(b in a)if(a.hasOwnProperty(b))return!1;return!0},a.forceRedraw=function(a){a.css({display:"none"}),setTimeout(function(){this.css({display:"block"})}.bind(a),1)};var c=function(){for(var a,b=3,c=document.createElement("div"),d=c.getElementsByTagName("i");c.innerHTML="",d[0];);return b>4?b:a}();return a.getIeVersion=function(){return c},a.Parser={_emoticonPath:"",setEmoticonPath:function(a){this._emoticonPath=a},emoticons:[{plain:":)",regex:/((\s):-?\)|:-?\)(\s|$))/gm,image:"Smiling.png"},{plain:";)",regex:/((\s);-?\)|;-?\)(\s|$))/gm,image:"Winking.png"},{plain:":D",regex:/((\s):-?D|:-?D(\s|$))/gm,image:"Grinning.png"},{plain:";D",regex:/((\s);-?D|;-?D(\s|$))/gm,image:"Grinning_Winking.png"},{plain:":(",regex:/((\s):-?\(|:-?\((\s|$))/gm,image:"Unhappy.png"},{plain:"^^",regex:/((\s)\^\^|\^\^(\s|$))/gm,image:"Happy_3.png"},{plain:":P",regex:/((\s):-?P|:-?P(\s|$))/gim,image:"Tongue_Out.png"},{plain:";P",regex:/((\s);-?P|;-?P(\s|$))/gim,image:"Tongue_Out_Winking.png"},{plain:":S",regex:/((\s):-?S|:-?S(\s|$))/gim,image:"Confused.png"},{plain:":/",regex:/((\s):-?\/|:-?\/(\s|$))/gm,image:"Uncertain.png"},{plain:"8)",regex:/((\s)8-?\)|8-?\)(\s|$))/gm,image:"Sunglasses.png"},{plain:"$)",regex:/((\s)\$-?\)|\$-?\)(\s|$))/gm,image:"Greedy.png"},{plain:"oO",regex:/((\s)oO|oO(\s|$))/gm,image:"Huh.png"},{plain:":x",regex:/((\s):x|:x(\s|$))/gm,image:"Lips_Sealed.png"},{plain:":666:",regex:/((\s):666:|:666:(\s|$))/gm,image:"Devil.png"},{plain:"<3",regex:/((\s)<3|<3(\s|$))/gm,image:"Heart.png"}],emotify:function(a){var b;for(b=this.emoticons.length-1;b>=0;b--)a=a.replace(this.emoticons[b].regex,'$2$1$3');return a},linkify:function(a){return a=a.replace(/(^|[^\/])(www\.[^\.]+\.[\S]+(\b|$))/gi,"$1http://$2"),a.replace(/(\b(https?|ftp|file):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/gi,'$1')},escape:function(a){return b("
                ").text(a).html()},nl2br:function(a){return a.replace(/\r\n|\r|\n/g,"
                ")},all:function(a){return a&&(a=this.escape(a),a=this.linkify(a),a=this.emotify(a),a=this.nl2br(a)),a}},a}(Candy.Util||{},jQuery),Candy.Core.Action=function(a,b,c){return a.Jabber={Version:function(a){Candy.Core.getConnection().send($iq({type:"result",to:Candy.Util.escapeJid(a.attr("from")),from:Candy.Util.escapeJid(a.attr("to")),id:a.attr("id")}).c("query",{name:Candy.about.name,version:Candy.about.version,os:navigator.userAgent}))},SetNickname:function(a,b){b=b instanceof Array?b:Candy.Core.getRooms();var d,e;c.each(b,function(b){d=Candy.Util.escapeJid(b+"/"+a),e=$pres({to:d,from:Candy.Core.getConnection().jid,id:"pres:"+Candy.Core.getConnection().getUniqueId()}),Candy.Core.getConnection().send(e)})},Roster:function(){Candy.Core.getConnection().send($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.ROSTER}).tree())},Presence:function(a,b){var c=$pres(a).c("priority").t(Candy.Core.getOptions().presencePriority.toString()).up().c("c",Candy.Core.getConnection().caps.generateCapsAttrs()).up();b&&c.node.appendChild(b.node),Candy.Core.getConnection().send(c.tree())},Services:function(){Candy.Core.getConnection().send($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.DISCO_ITEMS}).tree())},Autojoin:function(){Candy.Core.getOptions().autojoin===!0?Candy.Core.getConnection().sendIQ($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.PRIVATE}).c("storage",{xmlns:b.NS.BOOKMARKS}).tree()):c.isArray(Candy.Core.getOptions().autojoin)?c.each(Candy.Core.getOptions().autojoin,function(){a.Jabber.Room.Join.apply(null,this.valueOf().split(":",2))}):c(Candy).triggerHandler("candy:core.autojoin-missing")},ResetIgnoreList:function(){Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("list",{name:"ignore"}).c("item",{action:"allow",order:"0"}).tree())},RemoveIgnoreList:function(){Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("list",{name:"ignore"}).tree())},GetIgnoreList:function(){var a=$iq({type:"get",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("list",{name:"ignore"}).tree(),c=Candy.Core.getConnection().sendIQ(a);Candy.Core.addHandler(Candy.Core.Event.Jabber.PrivacyList,null,"iq",null,c)},SetIgnoreListActive:function(){Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("active",{name:"ignore"}).tree())},GetJidIfAnonymous:function(){Candy.Core.getUser().getJid()||(Candy.Core.log("[Jabber] Anonymous login"),Candy.Core.getUser().data.jid=Candy.Core.getConnection().jid)},Room:{Join:function(c,d){a.Jabber.Room.Disco(c),c=Candy.Util.escapeJid(c);var e=Candy.Core.getConnection(),f=c+"/"+Candy.Core.getUser().getNick(),g=$pres({to:f}).c("x",{xmlns:b.NS.MUC});d&&g.c("password").t(d),g.up().c("c",e.caps.generateCapsAttrs()),e.send(g.tree())},Leave:function(a){var b=Candy.Core.getRoom(a).getUser();a=Candy.Util.escapeJid(a),b&&Candy.Core.getConnection().muc.leave(a,b.getNick(),function(){})},Disco:function(a){Candy.Core.getConnection().sendIQ($iq({type:"get",from:Candy.Core.getUser().getEscapedJid(),to:Candy.Util.escapeJid(a)}).c("query",{xmlns:b.NS.DISCO_INFO}).tree())},Message:function(a,b,d){return b=c.trim(b),""===b?!1:(Candy.Core.getConnection().muc.message(Candy.Util.escapeJid(a),null,b,null,d),!0)},IgnoreUnignore:function(a){Candy.Core.getUser().addToOrRemoveFromPrivacyList("ignore",a),Candy.Core.Action.Jabber.Room.UpdatePrivacyList()},UpdatePrivacyList:function(){var a=Candy.Core.getUser(),b=$iq({type:"set",from:a.getEscapedJid()}).c("query",{xmlns:"jabber:iq:privacy"}).c("list",{name:"ignore"}),d=a.getPrivacyList("ignore");d.length>0?c.each(d,function(a,c){b.c("item",{type:"jid",value:Candy.Util.escapeJid(c),action:"deny",order:a}).c("message").up().up()}):b.c("item",{action:"allow",order:"0"}),Candy.Core.getConnection().sendIQ(b.tree())},Admin:{UserAction:function(a,c,d,e){a=Candy.Util.escapeJid(a),c=Candy.Util.escapeJid(c);var f={nick:b.getResourceFromJid(c)};switch(d){case"kick":f.role="none";break;case"ban":f.affiliation="outcast";break;default:return!1}return Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid(),to:a}).c("query",{xmlns:b.NS.MUC_ADMIN}).c("item",f).c("reason").t(e).tree()),!0},SetSubject:function(a,b){Candy.Core.getConnection().muc.setTopic(Candy.Util.escapeJid(a),b)}}}},a}(Candy.Core.Action||{},Strophe,jQuery),Candy.Core.ChatRoom=function(a){this.room={jid:a,name:Strophe.getNodeFromJid(a)},this.user=null,this.roster=new Candy.Core.ChatRoster,this.setUser=function(a){this.user=a},this.getUser=function(){return this.user},this.getJid=function(){return this.room.jid},this.setName=function(a){this.room.name=a},this.getName=function(){return this.room.name},this.setRoster=function(a){this.roster=a},this.getRoster=function(){return this.roster}},Candy.Core.ChatRoster=function(){this.items={},this.add=function(a){this.items[a.getJid()]=a},this.remove=function(a){delete this.items[a]},this.get=function(a){return this.items[a]},this.getAll=function(){return this.items}},Candy.Core.ChatUser=function(a,b,c,d){this.ROLE_MODERATOR="moderator",this.AFFILIATION_OWNER="owner",this.data={jid:a,nick:Strophe.unescapeNode(b),affiliation:c,role:d,privacyLists:{},customData:{},previousNick:void 0},this.getJid=function(){return this.data.jid?Candy.Util.unescapeJid(this.data.jid):void 0},this.getEscapedJid=function(){return Candy.Util.escapeJid(this.data.jid)},this.setJid=function(a){this.data.jid=a},this.getNick=function(){return Strophe.unescapeNode(this.data.nick)},this.setNick=function(a){this.data.nick=a},this.getRole=function(){return this.data.role},this.getAffiliation=function(){return this.data.affiliation},this.isModerator=function(){return this.getRole()===this.ROLE_MODERATOR||this.getAffiliation()===this.AFFILIATION_OWNER},this.addToOrRemoveFromPrivacyList=function(a,b){this.data.privacyLists[a]||(this.data.privacyLists[a]=[]);var c=-1;return-1!==(c=this.data.privacyLists[a].indexOf(b))?this.data.privacyLists[a].splice(c,1):this.data.privacyLists[a].push(b),this.data.privacyLists[a]},this.getPrivacyList=function(a){return this.data.privacyLists[a]||(this.data.privacyLists[a]=[]),this.data.privacyLists[a]},this.setPrivacyLists=function(a){this.data.privacyLists=a},this.isInPrivacyList=function(a,b){return this.data.privacyLists[a]?-1!==this.data.privacyLists[a].indexOf(b):!1},this.setCustomData=function(a){this.data.customData=a},this.getCustomData=function(){return this.data.customData},this.setPreviousNick=function(a){this.data.previousNick=a},this.getPreviousNick=function(){return this.data.previousNick}},Candy.Core.Event=function(a,b,c){return a.Login=function(a){c(Candy).triggerHandler("candy:core.login",{presetJid:a})},a.Strophe={Connect:function(a){switch(Candy.Core.setStropheStatus(a),a){case b.Status.CONNECTED:Candy.Core.log("[Connection] Connected"),Candy.Core.Action.Jabber.GetJidIfAnonymous();case b.Status.ATTACHED:Candy.Core.log("[Connection] Attached"),Candy.Core.Action.Jabber.Presence(),Candy.Core.Action.Jabber.Autojoin(),Candy.Core.Action.Jabber.GetIgnoreList();break;case b.Status.DISCONNECTED:Candy.Core.log("[Connection] Disconnected");break;case b.Status.AUTHFAIL:Candy.Core.log("[Connection] Authentication failed");break;case b.Status.CONNECTING:Candy.Core.log("[Connection] Connecting");break;case b.Status.DISCONNECTING:Candy.Core.log("[Connection] Disconnecting");break;case b.Status.AUTHENTICATING:Candy.Core.log("[Connection] Authenticating");break;case b.Status.ERROR:case b.Status.CONNFAIL:Candy.Core.log("[Connection] Failed ("+a+")");break;default:Candy.Core.log("[Connection] What?!")}c(Candy).triggerHandler("candy:core.chat.connection",{status:a})}},a.Jabber={Version:function(a){return Candy.Core.log("[Jabber] Version"),Candy.Core.Action.Jabber.Version(c(a)),!0},Presence:function(d){return Candy.Core.log("[Jabber] Presence"),d=c(d),d.children('x[xmlns^="'+b.NS.MUC+'"]').length>0?"error"===d.attr("type")?a.Jabber.Room.PresenceError(d):a.Jabber.Room.Presence(d):c(Candy).triggerHandler("candy:core.presence",{from:d.attr("from"),stanza:d}),!0},Bookmarks:function(a){return Candy.Core.log("[Jabber] Bookmarks"),c("conference",a).each(function(){var a=c(this);a.attr("autojoin")&&Candy.Core.Action.Jabber.Room.Join(a.attr("jid"))}),!0},PrivacyList:function(b){Candy.Core.log("[Jabber] PrivacyList");var d=Candy.Core.getUser();return b=c(b),"result"===b.attr("type")?(c('list[name="ignore"] item',b).each(function(){var a=c(this);"deny"===a.attr("action")&&d.addToOrRemoveFromPrivacyList("ignore",a.attr("value"))}),Candy.Core.Action.Jabber.SetIgnoreListActive(),!1):a.Jabber.PrivacyListError(b)},PrivacyListError:function(a){return Candy.Core.log("[Jabber] PrivacyListError"),c('error[code="404"][type="cancel"] item-not-found',a)&&(Candy.Core.Action.Jabber.ResetIgnoreList(),Candy.Core.Action.Jabber.SetIgnoreListActive()),!1},Message:function(d){Candy.Core.log("[Jabber] Message"),d=c(d);var e=d.attr("from"),f=d.attr("type"),g=d.attr("to");return e===b.getDomainFromJid(e)||"groupchat"!==f&&"chat"!==f&&"error"!==f&&"normal"!==f?g||e!==b.getDomainFromJid(e)?g&&e===b.getDomainFromJid(e)&&c(Candy).triggerHandler("candy:core.chat.message.server",{type:f||"message",subject:d.children("subject").text(),message:d.children("body").text()}):c(Candy).triggerHandler("candy:core.chat.message.admin",{type:f||"message",message:d.children("body").text()}):a.Jabber.Room.Message(d),!0},Room:{Leave:function(a){Candy.Core.log("[Jabber:Room] Leave"),a=c(a);var d=Candy.Util.unescapeJid(a.attr("from")),e=b.getBareJidFromJid(d);if(!Candy.Core.getRoom(e))return!0;var f,g,h=Candy.Core.getRoom(e).getName(),i=a.find("item"),j="leave";if(delete Candy.Core.getRooms()[e],"none"===i.attr("role")){var k=a.find("status").attr("code");"307"===k?j="kick":"301"===k&&(j="ban"),f=i.find("reason").text(),g=i.find("actor").attr("jid")}var l=new Candy.Core.ChatUser(d,b.getResourceFromJid(d),i.attr("affiliation"),i.attr("role"));return c(Candy).triggerHandler("candy:core.presence.leave",{roomJid:e,roomName:h,type:j,reason:f,actor:g,user:l}),!0},Disco:function(a){Candy.Core.log("[Jabber:Room] Disco"),a=c(a);var d=b.getBareJidFromJid(Candy.Util.unescapeJid(a.attr("from")));Candy.Core.getRooms()[d]||(Candy.Core.getRooms()[d]=new Candy.Core.ChatRoom(d));var e=a.find("identity");if(e.length){var f=e.attr("name"),g=Candy.Core.getRoom(d);null===g.getName()&&g.setName(b.unescapeNode(f))}return!0},Presence:function(d){Candy.Core.log("[Jabber:Room] Presence");var e=Candy.Util.unescapeJid(d.attr("from")),f=b.getBareJidFromJid(e),g=d.attr("type"),h=d.find("status"),i=!1,j=!1;if(h.length)for(var k=0,l=h.length;l>k;k++){var m=c(h[k]),n=m.attr("code");"303"===n?j=!0:"210"===n&&(i=!0)}var o=Candy.Core.getRoom(f);o||(Candy.Core.getRooms()[f]=new Candy.Core.ChatRoom(f),o=Candy.Core.getRoom(f));var p=o.getUser()?o.getUser():Candy.Core.getUser();if(b.getResourceFromJid(e)===p.getNick()&&"unavailable"===g&&j===!1)return a.Jabber.Room.Leave(d),!0;var q,r,s,t=o.getRoster(),u=d.find("item");if("unavailable"!==g){if(t.get(e))return!0;s=b.getResourceFromJid(e),r=new Candy.Core.ChatUser(e,s,u.attr("affiliation"),u.attr("role")),null!==o.getUser()||Candy.Core.getUser().getNick()!==s&&!i||(o.setUser(r),p=r),t.add(r),q="join"}else r=t.get(e),t.remove(e),j?(s=u.attr("nick"),q="nickchange",r.setPreviousNick(r.getNick()),r.setNick(s),r.setJid(b.getBareJidFromJid(e)+"/"+s),t.add(r)):(q="leave","none"===u.attr("role")&&("307"===d.find("status").attr("code")?q="kick":"301"===d.find("status").attr("code")&&(q="ban")));return c(Candy).triggerHandler("candy:core.presence.room",{roomJid:f,roomName:o.getName(),user:r,action:q,currentUser:p}),!0},PresenceError:function(a){Candy.Core.log("[Jabber:Room] Presence Error");var d=Candy.Util.unescapeJid(a.attr("from")),e=b.getBareJidFromJid(d),f=Candy.Core.getRooms()[e],g=f.getName();return Candy.Core.removeRoom(e),f=void 0,c(Candy).triggerHandler("candy:core.presence.error",{msg:a,type:a.children("error").children()[0].tagName.toLowerCase(),roomJid:e,roomName:g}),!0},Message:function(a){Candy.Core.log("[Jabber:Room] Message");var d,e;if(a.children("subject").length>0)d=Candy.Util.unescapeJid(b.getBareJidFromJid(a.attr("from"))),e={name:b.getNodeFromJid(d),body:a.children("subject").text(),type:"subject"};else if("error"===a.attr("type")){var f=a.children("error");f.children("text").length>0&&(d=a.attr("from"),e={type:"info",body:f.children("text").text()})}else{if(!(a.children("body").length>0))return!0;if("chat"===a.attr("type")||"normal"===a.attr("type")){d=Candy.Util.unescapeJid(a.attr("from"));var g=b.getBareJidFromJid(d),h=!Candy.Core.getRoom(g),i=h?b.getNodeFromJid(d):b.getResourceFromJid(d);e={name:i,body:a.children("body").text(),type:a.attr("type"),isNoConferenceRoomJid:h}}else{d=Candy.Util.unescapeJid(b.getBareJidFromJid(a.attr("from")));var j=b.getResourceFromJid(a.attr("from"));if(j)j=b.unescapeNode(j),e={name:j,body:a.children("body").text(),type:a.attr("type")};else{if(!Candy.View.Pane.Chat.rooms[a.attr("from")])return!0;e={name:"",body:a.children("body").text(),type:"info"}}}}var k=a.children(a.children("delay")?"delay":'x[xmlns="'+b.NS.DELAY+'"]'),l=void 0!==k?k.attr("stamp"):null;return c(Candy).triggerHandler("candy:core.message",{roomJid:d,message:e,timestamp:l}),!0}}},a}(Candy.Core.Event||{},Strophe,jQuery),Candy.View.Observer=function(a,b){var c=!0;return a.Chat={Connection:function(a,d){var e="candy:view.connection.status-"+d.status;if(b(Candy).triggerHandler(e)===!1)return!1;switch(d.status){case Strophe.Status.CONNECTING:case Strophe.Status.AUTHENTICATING:Candy.View.Pane.Chat.Modal.show(b.i18n._("statusConnecting"),!1,!0);break;case Strophe.Status.ATTACHED:case Strophe.Status.CONNECTED:c===!0&&(Candy.View.Pane.Chat.Modal.show(b.i18n._("statusConnected")),Candy.View.Pane.Chat.Modal.hide());break;case Strophe.Status.DISCONNECTING:Candy.View.Pane.Chat.Modal.show(b.i18n._("statusDisconnecting"),!1,!0);break;case Strophe.Status.DISCONNECTED:var f=Candy.Core.isAnonymousConnection()?Strophe.getDomainFromJid(Candy.Core.getUser().getJid()):null;Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("statusDisconnected"),f);break;case Strophe.Status.AUTHFAIL:Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("statusAuthfail"));break;default:Candy.View.Pane.Chat.Modal.show(b.i18n._("status",d.status))}},Message:function(a,b){"message"===b.type?Candy.View.Pane.Chat.adminMessage(b.subject||"",b.message):("chat"===b.type||"groupchat"===b.type)&&Candy.View.Pane.Chat.onInfoMessage(Candy.View.getCurrent().roomJid,b.subject||"",b.message)}},a.Presence={update:function(c,d){if("leave"===d.type){var e=Candy.View.Pane.Room.getUser(d.roomJid);Candy.View.Pane.Room.close(d.roomJid),a.Presence.notifyPrivateChats(e,d.type)}else if("kick"===d.type||"ban"===d.type){var f,g=d.actor?Strophe.getNodeFromJid(d.actor):null,h=[d.roomName];switch(g&&h.push(g),d.type){case"kick":f=b.i18n._(g?"youHaveBeenKickedBy":"youHaveBeenKicked",h);break;case"ban":f=b.i18n._(g?"youHaveBeenBannedBy":"youHaveBeenBanned",h)}Candy.View.Pane.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.adminMessageReason,{reason:d.reason,_action:f,_reason:b.i18n._("reasonWas",[d.reason])})),setTimeout(function(){Candy.View.Pane.Chat.Modal.hide(function(){Candy.View.Pane.Room.close(d.roomJid),a.Presence.notifyPrivateChats(d.user,d.type)})},5e3);var i={type:d.type,reason:d.reason,roomJid:d.roomJid,user:d.user};b(Candy).triggerHandler("candy:view.presence",[i])}else d.roomJid&&(d.roomJid=Candy.Util.unescapeJid(d.roomJid),Candy.View.Pane.Chat.rooms[d.roomJid]||(Candy.View.Pane.Room.init(d.roomJid,d.roomName),Candy.View.Pane.Room.show(d.roomJid)),Candy.View.Pane.Roster.update(d.roomJid,d.user,d.action,d.currentUser),Candy.View.Pane.Chat.rooms[d.user.getJid()]&&"nickchange"!==d.action&&(Candy.View.Pane.Roster.update(d.user.getJid(),d.user,d.action,d.currentUser),Candy.View.Pane.PrivateRoom.setStatus(d.user.getJid(),d.action)))},notifyPrivateChats:function(a,b){Candy.Core.log("[View:Observer] notify Private Chats");var c;for(c in Candy.View.Pane.Chat.rooms)Candy.View.Pane.Chat.rooms.hasOwnProperty(c)&&Candy.View.Pane.Room.getUser(c)&&a.getJid()===Candy.View.Pane.Room.getUser(c).getJid()&&(Candy.View.Pane.Roster.update(c,a,b,a),Candy.View.Pane.PrivateRoom.setStatus(c,b))}},a.PresenceError=function(a,c){switch(c.type){case"not-authorized":var d;c.msg.children("x").children("password").length>0&&(d=b.i18n._("passwordEnteredInvalid",[c.roomName])),Candy.View.Pane.Chat.Modal.showEnterPasswordForm(c.roomJid,c.roomName,d);break;case"conflict":Candy.View.Pane.Chat.Modal.showNicknameConflictForm(c.roomJid);break;case"registration-required":Candy.View.Pane.Chat.Modal.showError("errorMembersOnly",[c.roomName]);break;case"service-unavailable":Candy.View.Pane.Chat.Modal.showError("errorMaxOccupantsReached",[c.roomName])}},a.Message=function(a,b){"subject"===b.message.type?(Candy.View.Pane.Chat.rooms[b.roomJid]||(Candy.View.Pane.Room.init(b.roomJid,b.message.name),Candy.View.Pane.Room.show(b.roomJid)),Candy.View.Pane.Room.setSubject(b.roomJid,b.message.body)):"info"===b.message.type?Candy.View.Pane.Chat.infoMessage(b.roomJid,b.message.body):("chat"!==b.message.type||Candy.View.Pane.Chat.rooms[b.roomJid]||Candy.View.Pane.PrivateRoom.open(b.roomJid,b.message.name,!1,b.message.isNoConferenceRoomJid),Candy.View.Pane.Message.show(b.roomJid,b.message.name,b.message.body,b.timestamp))},a.Login=function(a,b){Candy.View.Pane.Chat.Modal.showLoginForm(null,b.presetJid)},a.AutojoinMissing=function(){c=!1,Candy.View.Pane.Chat.Modal.showError("errorAutojoinMissing")},a}(Candy.View.Observer||{},jQuery),Candy.View.Pane=function(a,b){return a.Window={_hasFocus:!0,_plainTitle:document.title,_unreadMessagesCount:0,autoscroll:!0,hasFocus:function(){return a.Window._hasFocus},increaseUnreadMessages:function(){a.Window.renderUnreadMessages(++a.Window._unreadMessagesCount)},reduceUnreadMessages:function(b){a.Window._unreadMessagesCount-=b,a.Window._unreadMessagesCount<=0?a.Window.clearUnreadMessages():a.Window.renderUnreadMessages(a.Window._unreadMessagesCount)},clearUnreadMessages:function(){a.Window._unreadMessagesCount=0,document.title=a.Window._plainTitle},renderUnreadMessages:function(b){document.title=Candy.View.Template.Window.unreadmessages.replace("{{count}}",b).replace("{{title}}",a.Window._plainTitle)},onFocus:function(){a.Window._hasFocus=!0,Candy.View.getCurrent().roomJid&&(a.Room.setFocusToForm(Candy.View.getCurrent().roomJid),a.Chat.clearUnreadMessages(Candy.View.getCurrent().roomJid))},onBlur:function(){a.Window._hasFocus=!1}},a.Chat={rooms:[],addTab:function(c,d,e){var f=Candy.Util.jidToId(c),g=Mustache.to_html(Candy.View.Template.Chat.tab,{roomJid:c,roomId:f,name:d||Strophe.getNodeFromJid(c),privateUserChat:function(){return"chat"===e},roomType:e}),h=b(g).appendTo("#chat-tabs");h.click(a.Chat.tabClick),b("a.close",h).click(a.Chat.tabClose),a.Chat.fitTabs()},getTab:function(a){return b("#chat-tabs").children('li[data-roomjid="'+a+'"]')},removeTab:function(b){a.Chat.getTab(b).remove(),a.Chat.fitTabs()},setActiveTab:function(a){b("#chat-tabs").children().each(function(){var c=b(this);c.attr("data-roomjid")===a?c.addClass("active"):c.removeClass("active")})},increaseUnreadMessages:function(b){var c=this.getTab(b).find(".unread");c.show().text(""!==c.text()?parseInt(c.text(),10)+1:1),"chat"===a.Chat.rooms[b].type&&a.Window.increaseUnreadMessages()},clearUnreadMessages:function(b){var c=a.Chat.getTab(b).find(".unread");a.Window.reduceUnreadMessages(c.text()),c.hide().text("")},tabClick:function(c){var d=Candy.View.getCurrent().roomJid;a.Chat.rooms[d].scrollPosition=a.Room.getPane(d,".message-pane-wrapper").scrollTop(),a.Room.show(b(this).attr("data-roomjid")),c.preventDefault()},tabClose:function(){var c=b(this).parent().attr("data-roomjid");return"chat"===a.Chat.rooms[c].type?a.Room.close(c):Candy.Core.Action.Jabber.Room.Leave(c),!1},allTabsClosed:function(){Candy.Core.disconnect(),a.Chat.Toolbar.hide()},fitTabs:function(){var a=b("#chat-tabs").innerWidth(),c=0,d=b("#chat-tabs").children();if(d.each(function(){c+=b(this).css({width:"auto",overflow:"visible"}).outerWidth(!0)}),c>a){var e=d.outerWidth(!0)-d.width(),f=Math.floor(a/d.length)-e;d.css({width:f,overflow:"hidden"})}},adminMessage:function(c,d){if(Candy.View.getCurrent().roomJid){var e=Mustache.to_html(Candy.View.Template.Chat.adminMessage,{subject:c,message:d,sender:b.i18n._("administratorMessageSubject"),time:Candy.Util.localizedTime((new Date).toGMTString())});b("#chat-rooms").children().each(function(){a.Room.appendToMessagePane(b(this).attr("data-roomjid"),e)}),a.Room.scrollToBottom(Candy.View.getCurrent().roomJid),b(Candy).triggerHandler("candy:view.chat.admin-message",{subject:c,message:d})}},infoMessage:function(b,c,d){a.Chat.onInfoMessage(b,c,d)},onInfoMessage:function(c,d,e){if(Candy.View.getCurrent().roomJid){var f=Mustache.to_html(Candy.View.Template.Chat.infoMessage,{subject:d,message:b.i18n._(e),time:Candy.Util.localizedTime((new Date).toGMTString())});a.Room.appendToMessagePane(c,f),Candy.View.getCurrent().roomJid===c&&a.Room.scrollToBottom(Candy.View.getCurrent().roomJid)}},Toolbar:{_supportsNativeAudio:!1,init:function(){b("#emoticons-icon").click(function(b){a.Chat.Context.showEmoticonsMenu(b.currentTarget),b.stopPropagation()}),b("#chat-autoscroll-control").click(a.Chat.Toolbar.onAutoscrollControlClick);var c=document.createElement("audio");a.Chat.Toolbar._supportsNativeAudio=!(!c.canPlayType||!c.canPlayType("audio/mpeg;").replace(/no/,"")),b("#chat-sound-control").click(a.Chat.Toolbar.onSoundControlClick),Candy.Util.cookieExists("candy-nosound")&&b("#chat-sound-control").click(),b("#chat-statusmessage-control").click(a.Chat.Toolbar.onStatusMessageControlClick),Candy.Util.cookieExists("candy-nostatusmessages")&&b("#chat-statusmessage-control").click()},show:function(){b("#chat-toolbar").show()},hide:function(){b("#chat-toolbar").hide()},update:function(c){var d=b("#chat-toolbar").find(".context"),e=a.Room.getUser(c);e&&e.isModerator()?d.show().click(function(b){a.Chat.Context.show(b.currentTarget,c),b.stopPropagation()}):d.hide(),a.Chat.Toolbar.updateUsercount(a.Chat.rooms[c].usercount)},playSound:function(){a.Chat.Toolbar.onPlaySound()},onPlaySound:function(){try{if(a.Chat.Toolbar._supportsNativeAudio)new Audio(Candy.View.getOptions().resources+"notify.mp3").play();else{var b=document.getElementById("chat-sound-player");b.SetVariable("method:stop",""),b.SetVariable("method:play","")}}catch(c){}},onSoundControlClick:function(){var c=b("#chat-sound-control");c.hasClass("checked")?(a.Chat.Toolbar.playSound=function(){},Candy.Util.setCookie("candy-nosound","1",365)):(a.Chat.Toolbar.playSound=function(){a.Chat.Toolbar.onPlaySound() +"use strict";var Candy=function(a,b){return a.about={name:"Candy",version:"1.6.0-beta3"},a.init=function(c,d){d.viewClass||(d.viewClass=a.View),d.viewClass.init(b("#candy"),d.view),a.Core.init(c,d.core)},a}(Candy||{},jQuery);Candy.Core=function(a,b,c){var d,e=null,f=null,g=null,h={},i=!1,j={autojoin:void 0,debug:!1,disableWindowUnload:!1,presencePriority:1,resource:Candy.about.name},k=function(a,c){b.addNamespace(a,c)},l=function(){k("PRIVATE","jabber:iq:private"),k("BOOKMARKS","storage:bookmarks"),k("PRIVACY","jabber:iq:privacy"),k("DELAY","jabber:x:delay")},m=function(a){var c=b.getNodeFromJid(a),d=b.getDomainFromJid(a);return c?b.escapeNode(c)+"@"+d:d};return a.init=function(d,g){f=d,c.extend(!0,j,g),j.debug&&(void 0!==typeof window.console&&void 0!==typeof window.console.log&&(a.log=Function.prototype.bind?Function.prototype.bind.call(console.log,console):function(){Function.prototype.apply.call(console.log,console,arguments)}),a.log("[Init] Debugging enabled")),l(),e=new b.Connection(f),e.rawInput=a.rawInput.bind(a),e.rawOutput=a.rawOutput.bind(a),e.caps.node="https://candy-chat.github.io/candy/",j.disableWindowUnload||(window.onbeforeunload=a.onWindowUnload)},a.registerEventHandlers=function(){a.addHandler(a.Event.Jabber.Version,b.NS.VERSION,"iq"),a.addHandler(a.Event.Jabber.Presence,null,"presence"),a.addHandler(a.Event.Jabber.Message,null,"message"),a.addHandler(a.Event.Jabber.Bookmarks,b.NS.PRIVATE,"iq"),a.addHandler(a.Event.Jabber.Room.Disco,b.NS.DISCO_INFO,"iq","result"),a.addHandler(e.disco._onDiscoInfo.bind(e.disco),b.NS.DISCO_INFO,"iq","get"),a.addHandler(e.disco._onDiscoItems.bind(e.disco),b.NS.DISCO_ITEMS,"iq","get"),a.addHandler(e.caps._delegateCapabilities.bind(e.caps),b.NS.CAPS)},a.connect=function(d,f,h){e.reset(),a.registerEventHandlers(),c(Candy).triggerHandler("candy:core.before-connect",{connection:e}),i=i?!0:d&&d.indexOf("@")<0,d&&f?(e.connect(m(d)+"/"+j.resource,f,Candy.Core.Event.Strophe.Connect),g=h?new a.ChatUser(d,h):new a.ChatUser(d,b.getNodeFromJid(d))):d&&h?(e.connect(m(d)+"/"+j.resource,null,Candy.Core.Event.Strophe.Connect),g=new a.ChatUser(null,h)):d?Candy.Core.Event.Login(d):Candy.Core.Event.Login()},a.attach=function(c,d,f){g=new a.ChatUser(c,b.getNodeFromJid(c)),a.registerEventHandlers(),e.attach(c,d,f,Candy.Core.Event.Strophe.Connect)},a.disconnect=function(){e.connected&&(c.each(a.getRooms(),function(){Candy.Core.Action.Jabber.Room.Leave(this.getJid())}),e.disconnect())},a.addHandler=function(a,b,c,d,f,g,h){return e.addHandler(a,b,c,d,f,g,h)},a.getUser=function(){return g},a.setUser=function(a){g=a},a.getConnection=function(){return e},a.removeRoom=function(a){delete h[a]},a.getRooms=function(){return h},a.getStropheStatus=function(){return d},a.setStropheStatus=function(a){d=a},a.isAnonymousConnection=function(){return i},a.getOptions=function(){return j},a.getRoom=function(a){return h[a]?h[a]:null},a.onWindowUnload=function(){e.options.sync=!0,a.disconnect(),e.flush()},a.rawInput=function(a){this.log("RECV: "+a)},a.rawOutput=function(a){this.log("SENT: "+a)},a.log=function(){},a}(Candy.Core||{},Strophe,jQuery),Candy.View=function(a,b){var c={container:null,roomJid:null},d={language:"en",resources:"res/",messages:{limit:2e3,remove:500},crop:{message:{nickname:15,body:1e3},roster:{nickname:15}}},e=function(c){b.i18n.load(a.Translation[c])},f=function(){b(Candy).on("candy:core.chat.connection",a.Observer.Chat.Connection),b(Candy).on("candy:core.chat.message",a.Observer.Chat.Message),b(Candy).on("candy:core.login",a.Observer.Login),b(Candy).on("candy:core.autojoin-missing",a.Observer.AutojoinMissing),b(Candy).on("candy:core.presence",a.Observer.Presence.update),b(Candy).on("candy:core.presence.leave",a.Observer.Presence.update),b(Candy).on("candy:core.presence.room",a.Observer.Presence.update),b(Candy).on("candy:core.presence.error",a.Observer.PresenceError),b(Candy).on("candy:core.message",a.Observer.Message)},g=function(){Candy.Util.getIeVersion()<9?b(document).focusin(Candy.View.Pane.Window.onFocus).focusout(Candy.View.Pane.Window.onBlur):b(window).focus(Candy.View.Pane.Window.onFocus).blur(Candy.View.Pane.Window.onBlur),b(window).resize(Candy.View.Pane.Chat.fitTabs)},h=function(){a.Pane.Chat.Toolbar.init()},i=function(){b("body").delegate("li[data-tooltip]","mouseenter",Candy.View.Pane.Chat.Tooltip.show)};return a.init=function(a,j){b.extend(!0,d,j),e(d.language),Candy.Util.Parser.setEmoticonPath(this.getOptions().resources+"img/emoticons/"),c.container=a,c.container.html(Mustache.to_html(Candy.View.Template.Chat.pane,{tooltipEmoticons:b.i18n._("tooltipEmoticons"),tooltipSound:b.i18n._("tooltipSound"),tooltipAutoscroll:b.i18n._("tooltipAutoscroll"),tooltipStatusmessage:b.i18n._("tooltipStatusmessage"),tooltipAdministration:b.i18n._("tooltipAdministration"),tooltipUsercount:b.i18n._("tooltipUsercount"),resourcesPath:this.getOptions().resources},{tabs:Candy.View.Template.Chat.tabs,rooms:Candy.View.Template.Chat.rooms,modal:Candy.View.Template.Chat.modal,toolbar:Candy.View.Template.Chat.toolbar,soundcontrol:Candy.View.Template.Chat.soundcontrol})),g(),h(),f(),i()},a.getCurrent=function(){return c},a.getOptions=function(){return d},a}(Candy.View||{},jQuery),Candy.Util=function(a,b){a.jidToId=function(a){return MD5.hexdigest(a)},a.escapeJid=function(a){var b=Strophe.escapeNode(Strophe.getNodeFromJid(a)),c=Strophe.getDomainFromJid(a),d=Strophe.getResourceFromJid(a);return a=b+"@"+c,d&&(a+="/"+d),a},a.unescapeJid=function(a){var b=Strophe.unescapeNode(Strophe.getNodeFromJid(a)),c=Strophe.getDomainFromJid(a),d=Strophe.getResourceFromJid(a);return a=b+"@"+c,d&&(a+="/"+d),a},a.crop=function(a,b){return a.length>b&&(a=a.substr(0,b-3)+"..."),a},a.setCookie=function(a,b,c){var d=new Date;d.setDate((new Date).getDate()+c),document.cookie=a+"="+b+";expires="+d.toUTCString()+";path=/"},a.cookieExists=function(a){return document.cookie.indexOf(a)>-1},a.getCookie=function(a){if(document.cookie){var b=new RegExp(escape(a)+"=([^;]*)","gm"),c=b.exec(document.cookie);if(c)return c[1]}},a.deleteCookie=function(a){document.cookie=a+"=;expires=Thu, 01-Jan-70 00:00:01 GMT;path=/"},a.getPosLeftAccordingToWindowBounds=function(a,c){var d=b(document).width(),e=a.outerWidth(),f=e-a.outerWidth(!0),g="left";return c+e>=d&&(c-=e-f,g="right"),{px:c,backgroundPositionAlignment:g}},a.getPosTopAccordingToWindowBounds=function(a,c){var d=b(document).height(),e=a.outerHeight(),f=e-a.outerHeight(!0),g="top";return c+e>=d&&(c-=e-f,g="bottom"),{px:c,backgroundPositionAlignment:g}},a.localizedTime=function(c){if(void 0===c)return void 0;var d=a.iso8601toDate(c);return d.format(d.toDateString()===(new Date).toDateString()?b.i18n._("timeFormat"):b.i18n._("dateFormat"))},a.iso8601toDate=function(a){var b=Date.parse(a);if(isNaN(b)){var c=/^(\d{4}|[+\-]\d{6})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?))?/.exec(a);if(c){var d=0;return"Z"!==c[8]&&(d=60*+c[10]+ +c[11],"+"===c[9]&&(d=-d)),d-=(new Date).getTimezoneOffset(),new Date(+c[1],+c[2]-1,+c[3],+c[4],+c[5]+d,+c[6],c[7]?+c[7].substr(0,3):0)}b=Date.parse(a.replace(/^(\d{4})(\d{2})(\d{2})/,"$1-$2-$3")+"Z")}return new Date(b)},a.isEmptyObject=function(a){var b;for(b in a)if(a.hasOwnProperty(b))return!1;return!0},a.forceRedraw=function(a){a.css({display:"none"}),setTimeout(function(){this.css({display:"block"})}.bind(a),1)};var c=function(){for(var a,b=3,c=document.createElement("div"),d=c.getElementsByTagName("i");c.innerHTML="",d[0];);return b>4?b:a}();return a.getIeVersion=function(){return c},a.Parser={_emoticonPath:"",setEmoticonPath:function(a){this._emoticonPath=a},emoticons:[{plain:":)",regex:/((\s):-?\)|:-?\)(\s|$))/gm,image:"Smiling.png"},{plain:";)",regex:/((\s);-?\)|;-?\)(\s|$))/gm,image:"Winking.png"},{plain:":D",regex:/((\s):-?D|:-?D(\s|$))/gm,image:"Grinning.png"},{plain:";D",regex:/((\s);-?D|;-?D(\s|$))/gm,image:"Grinning_Winking.png"},{plain:":(",regex:/((\s):-?\(|:-?\((\s|$))/gm,image:"Unhappy.png"},{plain:"^^",regex:/((\s)\^\^|\^\^(\s|$))/gm,image:"Happy_3.png"},{plain:":P",regex:/((\s):-?P|:-?P(\s|$))/gim,image:"Tongue_Out.png"},{plain:";P",regex:/((\s);-?P|;-?P(\s|$))/gim,image:"Tongue_Out_Winking.png"},{plain:":S",regex:/((\s):-?S|:-?S(\s|$))/gim,image:"Confused.png"},{plain:":/",regex:/((\s):-?\/|:-?\/(\s|$))/gm,image:"Uncertain.png"},{plain:"8)",regex:/((\s)8-?\)|8-?\)(\s|$))/gm,image:"Sunglasses.png"},{plain:"$)",regex:/((\s)\$-?\)|\$-?\)(\s|$))/gm,image:"Greedy.png"},{plain:"oO",regex:/((\s)oO|oO(\s|$))/gm,image:"Huh.png"},{plain:":x",regex:/((\s):x|:x(\s|$))/gm,image:"Lips_Sealed.png"},{plain:":666:",regex:/((\s):666:|:666:(\s|$))/gm,image:"Devil.png"},{plain:"<3",regex:/((\s)<3|<3(\s|$))/gm,image:"Heart.png"}],emotify:function(a){var b;for(b=this.emoticons.length-1;b>=0;b--)a=a.replace(this.emoticons[b].regex,'$2$1$3');return a},linkify:function(a){return a=a.replace(/(^|[^\/])(www\.[^\.]+\.[\S]+(\b|$))/gi,"$1http://$2"),a.replace(/(\b(https?|ftp|file):\/\/[\-A-Z0-9+&@#\/%?=~_|!:,.;]*[\-A-Z0-9+&@#\/%=~_|])/gi,'$1')},escape:function(a){return b("
                ").text(a).html()},nl2br:function(a){return a.replace(/\r\n|\r|\n/g,"
                ")},all:function(a){return a&&(a=this.escape(a),a=this.linkify(a),a=this.emotify(a),a=this.nl2br(a)),a}},a}(Candy.Util||{},jQuery),Candy.Core.Action=function(a,b,c){return a.Jabber={Version:function(a){Candy.Core.getConnection().send($iq({type:"result",to:Candy.Util.escapeJid(a.attr("from")),from:Candy.Util.escapeJid(a.attr("to")),id:a.attr("id")}).c("query",{name:Candy.about.name,version:Candy.about.version,os:navigator.userAgent}))},SetNickname:function(a,b){b=b instanceof Array?b:Candy.Core.getRooms();var d,e;c.each(b,function(b){d=Candy.Util.escapeJid(b+"/"+a),e=$pres({to:d,from:Candy.Core.getConnection().jid,id:"pres:"+Candy.Core.getConnection().getUniqueId()}),Candy.Core.getConnection().send(e)})},Roster:function(){Candy.Core.getConnection().send($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.ROSTER}).tree())},Presence:function(a,b){var c=$pres(a).c("priority").t(Candy.Core.getOptions().presencePriority.toString()).up().c("c",Candy.Core.getConnection().caps.generateCapsAttrs()).up();b&&c.node.appendChild(b.node),Candy.Core.getConnection().send(c.tree())},Services:function(){Candy.Core.getConnection().send($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.DISCO_ITEMS}).tree())},Autojoin:function(){Candy.Core.getOptions().autojoin===!0?Candy.Core.getConnection().sendIQ($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.PRIVATE}).c("storage",{xmlns:b.NS.BOOKMARKS}).tree()):c.isArray(Candy.Core.getOptions().autojoin)?c.each(Candy.Core.getOptions().autojoin,function(){a.Jabber.Room.Join.apply(null,this.valueOf().split(":",2))}):c(Candy).triggerHandler("candy:core.autojoin-missing")},ResetIgnoreList:function(){Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("list",{name:"ignore"}).c("item",{action:"allow",order:"0"}).tree())},RemoveIgnoreList:function(){Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("list",{name:"ignore"}).tree())},GetIgnoreList:function(){var a=$iq({type:"get",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("list",{name:"ignore"}).tree(),c=Candy.Core.getConnection().sendIQ(a);Candy.Core.addHandler(Candy.Core.Event.Jabber.PrivacyList,null,"iq",null,c)},SetIgnoreListActive:function(){Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid()}).c("query",{xmlns:b.NS.PRIVACY}).c("active",{name:"ignore"}).tree())},GetJidIfAnonymous:function(){Candy.Core.getUser().getJid()||(Candy.Core.log("[Jabber] Anonymous login"),Candy.Core.getUser().data.jid=Candy.Core.getConnection().jid)},Room:{Join:function(c,d){a.Jabber.Room.Disco(c),c=Candy.Util.escapeJid(c);var e=Candy.Core.getConnection(),f=c+"/"+Candy.Core.getUser().getNick(),g=$pres({to:f}).c("x",{xmlns:b.NS.MUC});d&&g.c("password").t(d),g.up().c("c",e.caps.generateCapsAttrs()),e.send(g.tree())},Leave:function(a){var b=Candy.Core.getRoom(a).getUser();a=Candy.Util.escapeJid(a),b&&Candy.Core.getConnection().muc.leave(a,b.getNick(),function(){})},Disco:function(a){Candy.Core.getConnection().sendIQ($iq({type:"get",from:Candy.Core.getUser().getEscapedJid(),to:Candy.Util.escapeJid(a)}).c("query",{xmlns:b.NS.DISCO_INFO}).tree())},Message:function(a,b,d){return b=c.trim(b),""===b?!1:(Candy.Core.getConnection().muc.message(Candy.Util.escapeJid(a),null,b,null,d),!0)},IgnoreUnignore:function(a){Candy.Core.getUser().addToOrRemoveFromPrivacyList("ignore",a),Candy.Core.Action.Jabber.Room.UpdatePrivacyList()},UpdatePrivacyList:function(){var a=Candy.Core.getUser(),b=$iq({type:"set",from:a.getEscapedJid()}).c("query",{xmlns:"jabber:iq:privacy"}).c("list",{name:"ignore"}),d=a.getPrivacyList("ignore");d.length>0?c.each(d,function(a,c){b.c("item",{type:"jid",value:Candy.Util.escapeJid(c),action:"deny",order:a}).c("message").up().up()}):b.c("item",{action:"allow",order:"0"}),Candy.Core.getConnection().sendIQ(b.tree())},Admin:{UserAction:function(a,c,d,e){a=Candy.Util.escapeJid(a),c=Candy.Util.escapeJid(c);var f={nick:b.getResourceFromJid(c)};switch(d){case"kick":f.role="none";break;case"ban":f.affiliation="outcast";break;default:return!1}return Candy.Core.getConnection().sendIQ($iq({type:"set",from:Candy.Core.getUser().getEscapedJid(),to:a}).c("query",{xmlns:b.NS.MUC_ADMIN}).c("item",f).c("reason").t(e).tree()),!0},SetSubject:function(a,b){Candy.Core.getConnection().muc.setTopic(Candy.Util.escapeJid(a),b)}}}},a}(Candy.Core.Action||{},Strophe,jQuery),Candy.Core.ChatRoom=function(a){this.room={jid:a,name:Strophe.getNodeFromJid(a)},this.user=null,this.roster=new Candy.Core.ChatRoster,this.setUser=function(a){this.user=a},this.getUser=function(){return this.user},this.getJid=function(){return this.room.jid},this.setName=function(a){this.room.name=a},this.getName=function(){return this.room.name},this.setRoster=function(a){this.roster=a},this.getRoster=function(){return this.roster}},Candy.Core.ChatRoster=function(){this.items={},this.add=function(a){this.items[a.getJid()]=a},this.remove=function(a){delete this.items[a]},this.get=function(a){return this.items[a]},this.getAll=function(){return this.items}},Candy.Core.ChatUser=function(a,b,c,d){this.ROLE_MODERATOR="moderator",this.AFFILIATION_OWNER="owner",this.data={jid:a,nick:Strophe.unescapeNode(b),affiliation:c,role:d,privacyLists:{},customData:{},previousNick:void 0},this.getJid=function(){return this.data.jid?Candy.Util.unescapeJid(this.data.jid):void 0},this.getEscapedJid=function(){return Candy.Util.escapeJid(this.data.jid)},this.setJid=function(a){this.data.jid=a},this.getNick=function(){return Strophe.unescapeNode(this.data.nick)},this.setNick=function(a){this.data.nick=a},this.getRole=function(){return this.data.role},this.getAffiliation=function(){return this.data.affiliation},this.isModerator=function(){return this.getRole()===this.ROLE_MODERATOR||this.getAffiliation()===this.AFFILIATION_OWNER},this.addToOrRemoveFromPrivacyList=function(a,b){this.data.privacyLists[a]||(this.data.privacyLists[a]=[]);var c=-1;return-1!==(c=this.data.privacyLists[a].indexOf(b))?this.data.privacyLists[a].splice(c,1):this.data.privacyLists[a].push(b),this.data.privacyLists[a]},this.getPrivacyList=function(a){return this.data.privacyLists[a]||(this.data.privacyLists[a]=[]),this.data.privacyLists[a]},this.setPrivacyLists=function(a){this.data.privacyLists=a},this.isInPrivacyList=function(a,b){return this.data.privacyLists[a]?-1!==this.data.privacyLists[a].indexOf(b):!1},this.setCustomData=function(a){this.data.customData=a},this.getCustomData=function(){return this.data.customData},this.setPreviousNick=function(a){this.data.previousNick=a},this.getPreviousNick=function(){return this.data.previousNick}},Candy.Core.Event=function(a,b,c){return a.Login=function(a){c(Candy).triggerHandler("candy:core.login",{presetJid:a})},a.Strophe={Connect:function(a){switch(Candy.Core.setStropheStatus(a),a){case b.Status.CONNECTED:Candy.Core.log("[Connection] Connected"),Candy.Core.Action.Jabber.GetJidIfAnonymous();case b.Status.ATTACHED:Candy.Core.log("[Connection] Attached"),Candy.Core.Action.Jabber.Presence(),Candy.Core.Action.Jabber.Autojoin(),Candy.Core.Action.Jabber.GetIgnoreList();break;case b.Status.DISCONNECTED:Candy.Core.log("[Connection] Disconnected");break;case b.Status.AUTHFAIL:Candy.Core.log("[Connection] Authentication failed");break;case b.Status.CONNECTING:Candy.Core.log("[Connection] Connecting");break;case b.Status.DISCONNECTING:Candy.Core.log("[Connection] Disconnecting");break;case b.Status.AUTHENTICATING:Candy.Core.log("[Connection] Authenticating");break;case b.Status.ERROR:case b.Status.CONNFAIL:Candy.Core.log("[Connection] Failed ("+a+")");break;default:Candy.Core.log("[Connection] What?!")}c(Candy).triggerHandler("candy:core.chat.connection",{status:a})}},a.Jabber={Version:function(a){return Candy.Core.log("[Jabber] Version"),Candy.Core.Action.Jabber.Version(c(a)),!0},Presence:function(d){return Candy.Core.log("[Jabber] Presence"),d=c(d),d.children('x[xmlns^="'+b.NS.MUC+'"]').length>0?"error"===d.attr("type")?a.Jabber.Room.PresenceError(d):a.Jabber.Room.Presence(d):c(Candy).triggerHandler("candy:core.presence",{from:d.attr("from"),stanza:d}),!0},Bookmarks:function(a){return Candy.Core.log("[Jabber] Bookmarks"),c("conference",a).each(function(){var a=c(this);a.attr("autojoin")&&Candy.Core.Action.Jabber.Room.Join(a.attr("jid"))}),!0},PrivacyList:function(b){Candy.Core.log("[Jabber] PrivacyList");var d=Candy.Core.getUser();return b=c(b),"result"===b.attr("type")?(c('list[name="ignore"] item',b).each(function(){var a=c(this);"deny"===a.attr("action")&&d.addToOrRemoveFromPrivacyList("ignore",a.attr("value"))}),Candy.Core.Action.Jabber.SetIgnoreListActive(),!1):a.Jabber.PrivacyListError(b)},PrivacyListError:function(a){return Candy.Core.log("[Jabber] PrivacyListError"),c('error[code="404"][type="cancel"] item-not-found',a)&&(Candy.Core.Action.Jabber.ResetIgnoreList(),Candy.Core.Action.Jabber.SetIgnoreListActive()),!1},Message:function(d){Candy.Core.log("[Jabber] Message"),d=c(d);var e=d.attr("from"),f=d.attr("type"),g=d.attr("to");return e===b.getDomainFromJid(e)||"groupchat"!==f&&"chat"!==f&&"error"!==f&&"normal"!==f?g||e!==b.getDomainFromJid(e)?g&&e===b.getDomainFromJid(e)&&c(Candy).triggerHandler("candy:core.chat.message.server",{type:f||"message",subject:d.children("subject").text(),message:d.children("body").text()}):c(Candy).triggerHandler("candy:core.chat.message.admin",{type:f||"message",message:d.children("body").text()}):a.Jabber.Room.Message(d),!0},Room:{Leave:function(a){Candy.Core.log("[Jabber:Room] Leave"),a=c(a);var d=Candy.Util.unescapeJid(a.attr("from")),e=b.getBareJidFromJid(d);if(!Candy.Core.getRoom(e))return!0;var f,g,h=Candy.Core.getRoom(e).getName(),i=a.find("item"),j="leave";if(delete Candy.Core.getRooms()[e],"none"===i.attr("role")){var k=a.find("status").attr("code");"307"===k?j="kick":"301"===k&&(j="ban"),f=i.find("reason").text(),g=i.find("actor").attr("jid")}var l=new Candy.Core.ChatUser(d,b.getResourceFromJid(d),i.attr("affiliation"),i.attr("role"));return c(Candy).triggerHandler("candy:core.presence.leave",{roomJid:e,roomName:h,type:j,reason:f,actor:g,user:l}),!0},Disco:function(a){Candy.Core.log("[Jabber:Room] Disco"),a=c(a);var d=b.getBareJidFromJid(Candy.Util.unescapeJid(a.attr("from")));Candy.Core.getRooms()[d]||(Candy.Core.getRooms()[d]=new Candy.Core.ChatRoom(d));var e=a.find("identity");if(e.length){var f=e.attr("name"),g=Candy.Core.getRoom(d);null===g.getName()&&g.setName(b.unescapeNode(f))}return!0},Presence:function(d){Candy.Core.log("[Jabber:Room] Presence");var e=Candy.Util.unescapeJid(d.attr("from")),f=b.getBareJidFromJid(e),g=d.attr("type"),h=d.find("status"),i=!1,j=!1;if(h.length)for(var k=0,l=h.length;l>k;k++){var m=c(h[k]),n=m.attr("code");"303"===n?j=!0:"210"===n&&(i=!0)}var o=Candy.Core.getRoom(f);o||(Candy.Core.getRooms()[f]=new Candy.Core.ChatRoom(f),o=Candy.Core.getRoom(f));var p=o.getUser()?o.getUser():Candy.Core.getUser();if(b.getResourceFromJid(e)===p.getNick()&&"unavailable"===g&&j===!1)return a.Jabber.Room.Leave(d),!0;var q,r,s,t=o.getRoster(),u=d.find("item");if("unavailable"!==g){if(t.get(e))return!0;s=b.getResourceFromJid(e),r=new Candy.Core.ChatUser(e,s,u.attr("affiliation"),u.attr("role")),null!==o.getUser()||Candy.Core.getUser().getNick()!==s&&!i||(o.setUser(r),p=r),t.add(r),q="join"}else r=t.get(e),t.remove(e),j?(s=u.attr("nick"),q="nickchange",r.setPreviousNick(r.getNick()),r.setNick(s),r.setJid(b.getBareJidFromJid(e)+"/"+s),t.add(r)):(q="leave","none"===u.attr("role")&&("307"===d.find("status").attr("code")?q="kick":"301"===d.find("status").attr("code")&&(q="ban")));return c(Candy).triggerHandler("candy:core.presence.room",{roomJid:f,roomName:o.getName(),user:r,action:q,currentUser:p}),!0},PresenceError:function(a){Candy.Core.log("[Jabber:Room] Presence Error");var d=Candy.Util.unescapeJid(a.attr("from")),e=b.getBareJidFromJid(d),f=Candy.Core.getRooms()[e],g=f.getName();return Candy.Core.removeRoom(e),f=void 0,c(Candy).triggerHandler("candy:core.presence.error",{msg:a,type:a.children("error").children()[0].tagName.toLowerCase(),roomJid:e,roomName:g}),!0},Message:function(a){Candy.Core.log("[Jabber:Room] Message");var d,e;if(a.children("subject").length>0)d=Candy.Util.unescapeJid(b.getBareJidFromJid(a.attr("from"))),e={name:b.getNodeFromJid(d),body:a.children("subject").text(),type:"subject"};else if("error"===a.attr("type")){var f=a.children("error");f.children("text").length>0&&(d=a.attr("from"),e={type:"info",body:f.children("text").text()})}else{if(!(a.children("body").length>0))return!0;if("chat"===a.attr("type")||"normal"===a.attr("type")){d=Candy.Util.unescapeJid(a.attr("from"));var g=b.getBareJidFromJid(d),h=!Candy.Core.getRoom(g),i=h?b.getNodeFromJid(d):b.getResourceFromJid(d);e={name:i,body:a.children("body").text(),type:a.attr("type"),isNoConferenceRoomJid:h}}else{d=Candy.Util.unescapeJid(b.getBareJidFromJid(a.attr("from")));var j=b.getResourceFromJid(a.attr("from"));if(j)j=b.unescapeNode(j),e={name:j,body:a.children("body").text(),type:a.attr("type")};else{if(!Candy.View.Pane.Chat.rooms[a.attr("from")])return!0;e={name:"",body:a.children("body").text(),type:"info"}}}}var k=a.children(a.children("delay")?"delay":'x[xmlns="'+b.NS.DELAY+'"]'),l=void 0!==k?k.attr("stamp"):null;return c(Candy).triggerHandler("candy:core.message",{roomJid:d,message:e,timestamp:l}),!0}}},a}(Candy.Core.Event||{},Strophe,jQuery),Candy.View.Observer=function(a,b){var c=!0;return a.Chat={Connection:function(a,d){var e="candy:view.connection.status-"+d.status;if(b(Candy).triggerHandler(e)===!1)return!1;switch(d.status){case Strophe.Status.CONNECTING:case Strophe.Status.AUTHENTICATING:Candy.View.Pane.Chat.Modal.show(b.i18n._("statusConnecting"),!1,!0);break;case Strophe.Status.ATTACHED:case Strophe.Status.CONNECTED:c===!0&&(Candy.View.Pane.Chat.Modal.show(b.i18n._("statusConnected")),Candy.View.Pane.Chat.Modal.hide());break;case Strophe.Status.DISCONNECTING:Candy.View.Pane.Chat.Modal.show(b.i18n._("statusDisconnecting"),!1,!0);break;case Strophe.Status.DISCONNECTED:var f=Candy.Core.isAnonymousConnection()?Strophe.getDomainFromJid(Candy.Core.getUser().getJid()):null;Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("statusDisconnected"),f);break;case Strophe.Status.AUTHFAIL:Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("statusAuthfail"));break;default:Candy.View.Pane.Chat.Modal.show(b.i18n._("status",d.status))}},Message:function(a,b){"message"===b.type?Candy.View.Pane.Chat.adminMessage(b.subject||"",b.message):("chat"===b.type||"groupchat"===b.type)&&Candy.View.Pane.Chat.onInfoMessage(Candy.View.getCurrent().roomJid,b.subject||"",b.message)}},a.Presence={update:function(c,d){if("leave"===d.type){var e=Candy.View.Pane.Room.getUser(d.roomJid);Candy.View.Pane.Room.close(d.roomJid),a.Presence.notifyPrivateChats(e,d.type)}else if("kick"===d.type||"ban"===d.type){var f,g=d.actor?Strophe.getNodeFromJid(d.actor):null,h=[d.roomName];switch(g&&h.push(g),d.type){case"kick":f=b.i18n._(g?"youHaveBeenKickedBy":"youHaveBeenKicked",h);break;case"ban":f=b.i18n._(g?"youHaveBeenBannedBy":"youHaveBeenBanned",h)}Candy.View.Pane.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.adminMessageReason,{reason:d.reason,_action:f,_reason:b.i18n._("reasonWas",[d.reason])})),setTimeout(function(){Candy.View.Pane.Chat.Modal.hide(function(){Candy.View.Pane.Room.close(d.roomJid),a.Presence.notifyPrivateChats(d.user,d.type)})},5e3);var i={type:d.type,reason:d.reason,roomJid:d.roomJid,user:d.user};b(Candy).triggerHandler("candy:view.presence",[i])}else d.roomJid&&(d.roomJid=Candy.Util.unescapeJid(d.roomJid),Candy.View.Pane.Chat.rooms[d.roomJid]||(Candy.View.Pane.Room.init(d.roomJid,d.roomName),Candy.View.Pane.Room.show(d.roomJid)),Candy.View.Pane.Roster.update(d.roomJid,d.user,d.action,d.currentUser),Candy.View.Pane.Chat.rooms[d.user.getJid()]&&"nickchange"!==d.action&&(Candy.View.Pane.Roster.update(d.user.getJid(),d.user,d.action,d.currentUser),Candy.View.Pane.PrivateRoom.setStatus(d.user.getJid(),d.action)))},notifyPrivateChats:function(a,b){Candy.Core.log("[View:Observer] notify Private Chats");var c;for(c in Candy.View.Pane.Chat.rooms)Candy.View.Pane.Chat.rooms.hasOwnProperty(c)&&Candy.View.Pane.Room.getUser(c)&&a.getJid()===Candy.View.Pane.Room.getUser(c).getJid()&&(Candy.View.Pane.Roster.update(c,a,b,a),Candy.View.Pane.PrivateRoom.setStatus(c,b))}},a.PresenceError=function(a,c){switch(c.type){case"not-authorized":var d;c.msg.children("x").children("password").length>0&&(d=b.i18n._("passwordEnteredInvalid",[c.roomName])),Candy.View.Pane.Chat.Modal.showEnterPasswordForm(c.roomJid,c.roomName,d);break;case"conflict":Candy.View.Pane.Chat.Modal.showNicknameConflictForm(c.roomJid);break;case"registration-required":Candy.View.Pane.Chat.Modal.showError("errorMembersOnly",[c.roomName]);break;case"service-unavailable":Candy.View.Pane.Chat.Modal.showError("errorMaxOccupantsReached",[c.roomName])}},a.Message=function(a,b){"subject"===b.message.type?(Candy.View.Pane.Chat.rooms[b.roomJid]||(Candy.View.Pane.Room.init(b.roomJid,b.message.name),Candy.View.Pane.Room.show(b.roomJid)),Candy.View.Pane.Room.setSubject(b.roomJid,b.message.body)):"info"===b.message.type?Candy.View.Pane.Chat.infoMessage(b.roomJid,b.message.body):("chat"!==b.message.type||Candy.View.Pane.Chat.rooms[b.roomJid]||Candy.View.Pane.PrivateRoom.open(b.roomJid,b.message.name,!1,b.message.isNoConferenceRoomJid),Candy.View.Pane.Message.show(b.roomJid,b.message.name,b.message.body,b.timestamp))},a.Login=function(a,b){Candy.View.Pane.Chat.Modal.showLoginForm(null,b.presetJid)},a.AutojoinMissing=function(){c=!1,Candy.View.Pane.Chat.Modal.showError("errorAutojoinMissing")},a}(Candy.View.Observer||{},jQuery),Candy.View.Pane=function(a,b){return a.Window={_hasFocus:!0,_plainTitle:document.title,_unreadMessagesCount:0,autoscroll:!0,hasFocus:function(){return a.Window._hasFocus},increaseUnreadMessages:function(){a.Window.renderUnreadMessages(++a.Window._unreadMessagesCount)},reduceUnreadMessages:function(b){a.Window._unreadMessagesCount-=b,a.Window._unreadMessagesCount<=0?a.Window.clearUnreadMessages():a.Window.renderUnreadMessages(a.Window._unreadMessagesCount)},clearUnreadMessages:function(){a.Window._unreadMessagesCount=0,document.title=a.Window._plainTitle},renderUnreadMessages:function(b){document.title=Candy.View.Template.Window.unreadmessages.replace("{{count}}",b).replace("{{title}}",a.Window._plainTitle)},onFocus:function(){a.Window._hasFocus=!0,Candy.View.getCurrent().roomJid&&(a.Room.setFocusToForm(Candy.View.getCurrent().roomJid),a.Chat.clearUnreadMessages(Candy.View.getCurrent().roomJid))},onBlur:function(){a.Window._hasFocus=!1}},a.Chat={rooms:[],addTab:function(c,d,e){var f=Candy.Util.jidToId(c),g=Mustache.to_html(Candy.View.Template.Chat.tab,{roomJid:c,roomId:f,name:d||Strophe.getNodeFromJid(c),privateUserChat:function(){return"chat"===e},roomType:e}),h=b(g).appendTo("#chat-tabs");h.click(a.Chat.tabClick),b("a.close",h).click(a.Chat.tabClose),a.Chat.fitTabs()},getTab:function(a){return b("#chat-tabs").children('li[data-roomjid="'+a+'"]')},removeTab:function(b){a.Chat.getTab(b).remove(),a.Chat.fitTabs()},setActiveTab:function(a){b("#chat-tabs").children().each(function(){var c=b(this);c.attr("data-roomjid")===a?c.addClass("active"):c.removeClass("active")})},increaseUnreadMessages:function(b){var c=this.getTab(b).find(".unread");c.show().text(""!==c.text()?parseInt(c.text(),10)+1:1),"chat"===a.Chat.rooms[b].type&&a.Window.increaseUnreadMessages()},clearUnreadMessages:function(b){var c=a.Chat.getTab(b).find(".unread");a.Window.reduceUnreadMessages(c.text()),c.hide().text("")},tabClick:function(c){var d=Candy.View.getCurrent().roomJid;a.Chat.rooms[d].scrollPosition=a.Room.getPane(d,".message-pane-wrapper").scrollTop(),a.Room.show(b(this).attr("data-roomjid")),c.preventDefault()},tabClose:function(){var c=b(this).parent().attr("data-roomjid");return"chat"===a.Chat.rooms[c].type?a.Room.close(c):Candy.Core.Action.Jabber.Room.Leave(c),!1},allTabsClosed:function(){Candy.Core.disconnect(),a.Chat.Toolbar.hide()},fitTabs:function(){var a=b("#chat-tabs").innerWidth(),c=0,d=b("#chat-tabs").children();if(d.each(function(){c+=b(this).css({width:"auto",overflow:"visible"}).outerWidth(!0)}),c>a){var e=d.outerWidth(!0)-d.width(),f=Math.floor(a/d.length)-e;d.css({width:f,overflow:"hidden"})}},adminMessage:function(c,d){if(Candy.View.getCurrent().roomJid){var e=Mustache.to_html(Candy.View.Template.Chat.adminMessage,{subject:c,message:d,sender:b.i18n._("administratorMessageSubject"),time:Candy.Util.localizedTime((new Date).toGMTString())});b("#chat-rooms").children().each(function(){a.Room.appendToMessagePane(b(this).attr("data-roomjid"),e)}),a.Room.scrollToBottom(Candy.View.getCurrent().roomJid),b(Candy).triggerHandler("candy:view.chat.admin-message",{subject:c,message:d})}},infoMessage:function(b,c,d){a.Chat.onInfoMessage(b,c,d)},onInfoMessage:function(c,d,e){if(Candy.View.getCurrent().roomJid){var f=Mustache.to_html(Candy.View.Template.Chat.infoMessage,{subject:d,message:b.i18n._(e),time:Candy.Util.localizedTime((new Date).toGMTString())});a.Room.appendToMessagePane(c,f),Candy.View.getCurrent().roomJid===c&&a.Room.scrollToBottom(Candy.View.getCurrent().roomJid)}},Toolbar:{_supportsNativeAudio:!1,init:function(){b("#emoticons-icon").click(function(b){a.Chat.Context.showEmoticonsMenu(b.currentTarget),b.stopPropagation()}),b("#chat-autoscroll-control").click(a.Chat.Toolbar.onAutoscrollControlClick);var c=document.createElement("audio");a.Chat.Toolbar._supportsNativeAudio=!(!c.canPlayType||!c.canPlayType("audio/mpeg;").replace(/no/,"")),b("#chat-sound-control").click(a.Chat.Toolbar.onSoundControlClick),Candy.Util.cookieExists("candy-nosound")&&b("#chat-sound-control").click(),b("#chat-statusmessage-control").click(a.Chat.Toolbar.onStatusMessageControlClick),Candy.Util.cookieExists("candy-nostatusmessages")&&b("#chat-statusmessage-control").click()},show:function(){b("#chat-toolbar").show()},hide:function(){b("#chat-toolbar").hide()},update:function(c){var d=b("#chat-toolbar").find(".context"),e=a.Room.getUser(c);e&&e.isModerator()?d.show().click(function(b){a.Chat.Context.show(b.currentTarget,c),b.stopPropagation()}):d.hide(),a.Chat.Toolbar.updateUsercount(a.Chat.rooms[c].usercount)},playSound:function(){a.Chat.Toolbar.onPlaySound()},onPlaySound:function(){try{if(a.Chat.Toolbar._supportsNativeAudio)new Audio(Candy.View.getOptions().resources+"notify.mp3").play();else{var b=document.getElementById("chat-sound-player");b.SetVariable("method:stop",""),b.SetVariable("method:play","")}}catch(c){}},onSoundControlClick:function(){var c=b("#chat-sound-control");c.hasClass("checked")?(a.Chat.Toolbar.playSound=function(){},Candy.Util.setCookie("candy-nosound","1",365)):(a.Chat.Toolbar.playSound=function(){a.Chat.Toolbar.onPlaySound() },Candy.Util.deleteCookie("candy-nosound")),c.toggleClass("checked")},onAutoscrollControlClick:function(){var c=b("#chat-autoscroll-control");c.hasClass("checked")?(a.Room.scrollToBottom=function(b){a.Room.onScrollToStoredPosition(b)},a.Window.autoscroll=!1):(a.Room.scrollToBottom=function(b){a.Room.onScrollToBottom(b)},a.Room.scrollToBottom(Candy.View.getCurrent().roomJid),a.Window.autoscroll=!0),c.toggleClass("checked")},onStatusMessageControlClick:function(){var c=b("#chat-statusmessage-control");c.hasClass("checked")?(a.Chat.infoMessage=function(){},Candy.Util.setCookie("candy-nostatusmessages","1",365)):(a.Chat.infoMessage=function(b,c,d){a.Chat.onInfoMessage(b,c,d)},Candy.Util.deleteCookie("candy-nostatusmessages")),c.toggleClass("checked")},updateUsercount:function(a){b("#chat-usercount").text(a)}},Modal:{show:function(c,d,e){d?a.Chat.Modal.showCloseControl():a.Chat.Modal.hideCloseControl(),e?a.Chat.Modal.showSpinner():a.Chat.Modal.hideSpinner(),b("#chat-modal").stop(!1,!0),b("#chat-modal-body").html(c),b("#chat-modal").fadeIn("fast"),b("#chat-modal-overlay").show()},hide:function(a){b("#chat-modal").fadeOut("fast",function(){b("#chat-modal-body").text(""),b("#chat-modal-overlay").hide()}),b(document).keydown(function(a){27===a.which&&a.preventDefault()}),a&&a()},showSpinner:function(){b("#chat-modal-spinner").show()},hideSpinner:function(){b("#chat-modal-spinner").hide()},showCloseControl:function(){b("#admin-message-cancel").show().click(function(b){a.Chat.Modal.hide(),b.preventDefault()}),b(document).keydown(function(b){27===b.which&&(a.Chat.Modal.hide(),b.preventDefault())})},hideCloseControl:function(){b("#admin-message-cancel").hide().click(function(){})},showLoginForm:function(c,d){a.Chat.Modal.show((c?c:"")+Mustache.to_html(Candy.View.Template.Login.form,{_labelNickname:b.i18n._("labelNickname"),_labelUsername:b.i18n._("labelUsername"),_labelPassword:b.i18n._("labelPassword"),_loginSubmit:b.i18n._("loginSubmit"),displayPassword:!Candy.Core.isAnonymousConnection(),displayUsername:!d,displayNickname:Candy.Core.isAnonymousConnection(),presetJid:d?d:!1})),b("#login-form").children(":input:first").focus(),b("#login-form").submit(function(){var a=b("#username").val(),c=b("#password").val();if(Candy.Core.isAnonymousConnection())Candy.Core.connect(d,null,a);else{var e=Candy.Core.getUser()&&a.indexOf("@")<0?a+"@"+Strophe.getDomainFromJid(Candy.Core.getUser().getJid()):a;e.indexOf("@")<0&&!Candy.Core.getUser()?Candy.View.Pane.Chat.Modal.showLoginForm(b.i18n._("loginInvalid")):Candy.Core.connect(e,c)}return!1})},showEnterPasswordForm:function(c,d,e){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.enterPasswordForm,{roomName:d,_labelPassword:b.i18n._("labelPassword"),_label:e?e:b.i18n._("enterRoomPassword",[d]),_joinSubmit:b.i18n._("enterRoomPasswordSubmit")}),!0),b("#password").focus(),b("#enter-password-form").submit(function(){var d=b("#password").val();return a.Chat.Modal.hide(function(){Candy.Core.Action.Jabber.Room.Join(c,d)}),!1})},showNicknameConflictForm:function(c){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.nicknameConflictForm,{_labelNickname:b.i18n._("labelNickname"),_label:b.i18n._("nicknameConflict"),_loginSubmit:b.i18n._("loginSubmit")})),b("#nickname").focus(),b("#nickname-conflict-form").submit(function(){var d=b("#nickname").val();return a.Chat.Modal.hide(function(){Candy.Core.getUser().data.nick=d,Candy.Core.Action.Jabber.Room.Join(c)}),!1})},showError:function(c,d){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.PresenceError.displayError,{_error:b.i18n._(c,d)}),!0)}},Tooltip:{show:function(a,c){var d=b("#tooltip"),e=b(a.currentTarget);if(c||(c=e.attr("data-tooltip")),0===d.length){var f=Mustache.to_html(Candy.View.Template.Chat.tooltip);b("#chat-pane").append(f),d=b("#tooltip")}b("#context-menu").hide(),d.stop(!1,!0),d.children("div").html(c);var g=e.offset(),h=Candy.Util.getPosLeftAccordingToWindowBounds(d,g.left),i=Candy.Util.getPosTopAccordingToWindowBounds(d,g.top);d.css({left:h.px,top:i.px}).removeClass("left-top left-bottom right-top right-bottom").addClass(h.backgroundPositionAlignment+"-"+i.backgroundPositionAlignment).fadeIn("fast"),e.mouseleave(function(a){a.stopPropagation(),b("#tooltip").stop(!1,!0).fadeOut("fast",function(){b(this).css({top:0,left:0})})})}},Context:{init:function(){if(0===b("#context-menu").length){var a=Mustache.to_html(Candy.View.Template.Chat.Context.menu);b("#chat-pane").append(a),b("#context-menu").mouseleave(function(){b(this).fadeOut("fast")})}},show:function(c,d,e){c=b(c);var f=a.Chat.rooms[d].id,g=b("#context-menu"),h=b("ul li",g);b("#tooltip").hide(),e||(e=Candy.Core.getUser()),h.remove();var i,j=this.getMenuLinks(d,e,c),k=function(a,c){return function(d){d.data.callback(d,a,c),b("#context-menu").hide()}};for(i in j)if(j.hasOwnProperty(i)){var l=j[i],m=Mustache.to_html(Candy.View.Template.Chat.Context.menulinks,{roomId:f,"class":l["class"],id:i,label:l.label});b("ul",g).append(m),b("#context-menu-"+i).bind("click",l,k(d,e))}if(i){var n=c.offset(),o=Candy.Util.getPosLeftAccordingToWindowBounds(g,n.left),p=Candy.Util.getPosTopAccordingToWindowBounds(g,n.top);return g.css({left:o.px,top:p.px}).removeClass("left-top left-bottom right-top right-bottom").addClass(o.backgroundPositionAlignment+"-"+p.backgroundPositionAlignment).fadeIn("fast"),b(Candy).triggerHandler("candy:view.roster.after-context-menu",{roomJid:d,user:e,element:g}),!0}},getMenuLinks:function(c,d,e){var f,g,h={roomJid:c,user:d,elem:e,menulinks:this.initialMenuLinks(e)};b(Candy).triggerHandler("candy:view.roster.context-menu",h),f=h.menulinks;for(g in f)f.hasOwnProperty(g)&&void 0!==f[g].requiredPermission&&!f[g].requiredPermission(d,a.Room.getUser(c),e)&&delete f[g];return f},initialMenuLinks:function(){return{"private":{requiredPermission:function(a,b){return b.getNick()!==a.getNick()&&Candy.Core.getRoom(Candy.View.getCurrent().roomJid)&&!Candy.Core.getUser().isInPrivacyList("ignore",a.getJid())},"class":"private",label:b.i18n._("privateActionLabel"),callback:function(a,c,d){b("#user-"+Candy.Util.jidToId(c)+"-"+Candy.Util.jidToId(d.getJid())).click()}},ignore:{requiredPermission:function(a,b){return b.getNick()!==a.getNick()&&!Candy.Core.getUser().isInPrivacyList("ignore",a.getJid())},"class":"ignore",label:b.i18n._("ignoreActionLabel"),callback:function(a,b,c){Candy.View.Pane.Room.ignoreUser(b,c.getJid())}},unignore:{requiredPermission:function(a,b){return b.getNick()!==a.getNick()&&Candy.Core.getUser().isInPrivacyList("ignore",a.getJid())},"class":"unignore",label:b.i18n._("unignoreActionLabel"),callback:function(a,b,c){Candy.View.Pane.Room.unignoreUser(b,c.getJid())}},kick:{requiredPermission:function(a,b){return b.getNick()!==a.getNick()&&b.isModerator()&&!a.isModerator()},"class":"kick",label:b.i18n._("kickActionLabel"),callback:function(c,d,e){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm,{_label:b.i18n._("reason"),_submit:b.i18n._("kickActionLabel")}),!0),b("#context-modal-field").focus(),b("#context-modal-form").submit(function(){return Candy.Core.Action.Jabber.Room.Admin.UserAction(d,e.getJid(),"kick",b("#context-modal-field").val()),a.Chat.Modal.hide(),!1})}},ban:{requiredPermission:function(a,b){return b.getNick()!==a.getNick()&&b.isModerator()&&!a.isModerator()},"class":"ban",label:b.i18n._("banActionLabel"),callback:function(c,d,e){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm,{_label:b.i18n._("reason"),_submit:b.i18n._("banActionLabel")}),!0),b("#context-modal-field").focus(),b("#context-modal-form").submit(function(){return Candy.Core.Action.Jabber.Room.Admin.UserAction(d,e.getJid(),"ban",b("#context-modal-field").val()),a.Chat.Modal.hide(),!1})}},subject:{requiredPermission:function(a,b){return b.getNick()===a.getNick()&&b.isModerator()},"class":"subject",label:b.i18n._("setSubjectActionLabel"),callback:function(c,d){a.Chat.Modal.show(Mustache.to_html(Candy.View.Template.Chat.Context.contextModalForm,{_label:b.i18n._("subject"),_submit:b.i18n._("setSubjectActionLabel")}),!0),b("#context-modal-field").focus(),b("#context-modal-form").submit(function(c){Candy.Core.Action.Jabber.Room.Admin.SetSubject(d,b("#context-modal-field").val()),a.Chat.Modal.hide(),c.preventDefault()})}}}},showEmoticonsMenu:function(a){a=b(a);var c,d=a.offset(),e=b("#context-menu"),f=b("ul",e),g="";for(b("#tooltip").hide(),c=Candy.Util.Parser.emoticons.length-1;c>=0;c--)g=''+Candy.Util.Parser.emoticons[c].plain+''+g;f.html('
              • '+g+"
              • "),f.find("img").click(function(){var a=Candy.View.Pane.Room.getPane(Candy.View.getCurrent().roomJid,".message-form").children(".field"),c=a.val(),d=b(this).attr("alt")+" ";a.val(c?c+" "+d:d).focus()});var h=Candy.Util.getPosLeftAccordingToWindowBounds(e,d.left),i=Candy.Util.getPosTopAccordingToWindowBounds(e,d.top);return e.css({left:h.px,top:i.px}).removeClass("left-top left-bottom right-top right-bottom").addClass(h.backgroundPositionAlignment+"-"+i.backgroundPositionAlignment).fadeIn("fast"),!0}}},a.Room={init:function(c,d,e){e=e||"groupchat",Candy.Util.isEmptyObject(a.Chat.rooms)&&a.Chat.Toolbar.show(),c=Candy.Util.unescapeJid(c);var f=Candy.Util.jidToId(c);return a.Chat.rooms[c]={id:f,usercount:0,name:d,type:e,messageCount:0,scrollPosition:-1},b("#chat-rooms").append(Mustache.to_html(Candy.View.Template.Room.pane,{roomId:f,roomJid:c,roomType:e,form:{_messageSubmit:b.i18n._("messageSubmit")},roster:{_userOnline:b.i18n._("userOnline")}},{roster:Candy.View.Template.Roster.pane,messages:Candy.View.Template.Message.pane,form:Candy.View.Template.Room.form})),a.Chat.addTab(c,d,e),a.Room.getPane(c,".message-form").submit(a.Message.submit),b(Candy).triggerHandler("candy:view.room.after-add",{roomJid:c,type:e,element:a.Room.getPane(c)}),f},show:function(c){var d,e=a.Chat.rooms[c].id;b(".room-pane").each(function(){var f=b(this);d={roomJid:c,element:f},f.attr("id")==="chat-room-"+e?(f.show(),Candy.View.getCurrent().roomJid=c,a.Chat.setActiveTab(c),a.Chat.Toolbar.update(c),a.Chat.clearUnreadMessages(c),a.Room.setFocusToForm(c),a.Room.scrollToBottom(c),b(Candy).triggerHandler("candy:view.room.after-show",d)):(f.hide(),b(Candy).triggerHandler("candy:view.room.after-hide",d))})},setSubject:function(c,d){d=Candy.Util.Parser.linkify(Candy.Util.Parser.escape(d));var e=Mustache.to_html(Candy.View.Template.Room.subject,{subject:d,roomName:a.Chat.rooms[c].name,_roomSubject:b.i18n._("roomSubject"),time:Candy.Util.localizedTime((new Date).toGMTString())});a.Room.appendToMessagePane(c,e),a.Room.scrollToBottom(c),b(Candy).triggerHandler("candy:view.room.after-subject-change",{roomJid:c,element:a.Room.getPane(c),subject:d})},close:function(c){a.Chat.removeTab(c),a.Window.clearUnreadMessages(),a.Room.getPane(c).remove();var d=b("#chat-rooms").children();Candy.View.getCurrent().roomJid===c&&(Candy.View.getCurrent().roomJid=null,0===d.length?a.Chat.allTabsClosed():a.Room.show(d.last().attr("data-roomjid"))),delete a.Chat.rooms[c],b(Candy).triggerHandler("candy:view.room.after-close",{roomJid:c})},appendToMessagePane:function(b,c){a.Room.getPane(b,".message-pane").append(c),a.Chat.rooms[b].messageCount++,a.Room.sliceMessagePane(b)},sliceMessagePane:function(b){if(a.Window.autoscroll){var c=Candy.View.getOptions().messages;a.Chat.rooms[b].messageCount>c.limit&&(a.Room.getPane(b,".message-pane").children().slice(0,c.remove).remove(),a.Chat.rooms[b].messageCount-=c.remove)}},scrollToBottom:function(b){a.Room.onScrollToBottom(b)},onScrollToBottom:function(b){var c=a.Room.getPane(b,".message-pane-wrapper");c.scrollTop(c.prop("scrollHeight"))},onScrollToStoredPosition:function(b){if(a.Chat.rooms[b].scrollPosition>-1){var c=a.Room.getPane(b,".message-pane-wrapper");c.scrollTop(a.Chat.rooms[b].scrollPosition),a.Chat.rooms[b].scrollPosition=-1}},setFocusToForm:function(b){var c=a.Room.getPane(b,".message-form");if(c)try{c.children(".field")[0].focus()}catch(d){}},setUser:function(c,d){a.Chat.rooms[c].user=d;var e=a.Room.getPane(c),f=b("#chat-pane");e.attr("data-userjid",d.getJid()),d.isModerator()?(d.getRole()===d.ROLE_MODERATOR&&f.addClass("role-moderator"),d.getAffiliation()===d.AFFILIATION_OWNER&&f.addClass("affiliation-owner")):f.removeClass("role-moderator affiliation-owner"),a.Chat.Context.init()},getUser:function(b){return a.Chat.rooms[b].user},ignoreUser:function(a,b){Candy.Core.Action.Jabber.Room.IgnoreUnignore(b),Candy.View.Pane.Room.addIgnoreIcon(a,b)},unignoreUser:function(a,b){Candy.Core.Action.Jabber.Room.IgnoreUnignore(b),Candy.View.Pane.Room.removeIgnoreIcon(a,b)},addIgnoreIcon:function(a,c){Candy.View.Pane.Chat.rooms[c]&&b("#user-"+Candy.View.Pane.Chat.rooms[c].id+"-"+Candy.Util.jidToId(c)).addClass("status-ignored"),Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(a)]&&b("#user-"+Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(a)].id+"-"+Candy.Util.jidToId(c)).addClass("status-ignored")},removeIgnoreIcon:function(a,c){Candy.View.Pane.Chat.rooms[c]&&b("#user-"+Candy.View.Pane.Chat.rooms[c].id+"-"+Candy.Util.jidToId(c)).removeClass("status-ignored"),Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(a)]&&b("#user-"+Candy.View.Pane.Chat.rooms[Strophe.getBareJidFromJid(a)].id+"-"+Candy.Util.jidToId(c)).removeClass("status-ignored")},getPane:function(c,d){return a.Chat.rooms[c]?d?a.Chat.rooms[c]["pane-"+d]?a.Chat.rooms[c]["pane-"+d]:(a.Chat.rooms[c]["pane-"+d]=b("#chat-room-"+a.Chat.rooms[c].id).find(d),a.Chat.rooms[c]["pane-"+d]):b("#chat-room-"+a.Chat.rooms[c].id):void 0},changeDataUserJidIfUserIsMe:function(a,c){if(c.getNick()===Candy.Core.getUser().getNick()){var d=b("#chat-room-"+a);d.attr("data-userjid",Strophe.getBareJidFromJid(d.attr("data-userjid"))+"/"+c.getNick())}}},a.PrivateRoom={open:function(c,d,e,f){var g=f?Candy.Core.getUser():a.Room.getUser(Strophe.getBareJidFromJid(c));return Candy.Core.getUser().isInPrivacyList("ignore",c)?!1:(a.Chat.rooms[c]||a.Room.init(c,d,"chat"),e&&a.Room.show(c),a.Roster.update(c,new Candy.Core.ChatUser(c,d),"join",g),a.Roster.update(c,g,"join",g),a.PrivateRoom.setStatus(c,"join"),f&&a.Chat.infoMessage(c,b.i18n._("presenceUnknownWarningSubject"),b.i18n._("presenceUnknownWarning")),void b(Candy).triggerHandler("candy:view.private-room.after-open",{roomJid:c,type:"chat",element:a.Room.getPane(c)}))},setStatus:function(b,c){var d=a.Room.getPane(b,".message-form");"join"===c?(a.Chat.getTab(b).addClass("online").removeClass("offline"),d.children(".field").removeAttr("disabled"),d.children(".submit").removeAttr("disabled"),a.Chat.getTab(b)):"leave"===c&&(a.Chat.getTab(b).addClass("offline").removeClass("online"),d.children(".field").attr("disabled",!0),d.children(".submit").attr("disabled",!0))},changeNick:function(c,d){Candy.Core.log("[View:Pane:PrivateRoom] changeNick");var e,f,g=c+"/"+d.getPreviousNick(),h=c+"/"+d.getNick(),i=Candy.Util.jidToId(g),j=Candy.Util.jidToId(h),k=a.Chat.rooms[g];a.Chat.rooms[h]&&a.Room.close(h),k?(k.name=d.getNick(),k.id=j,a.Chat.rooms[h]=k,delete a.Chat.rooms[g],e=b("#chat-room-"+i),e&&(e.attr("data-roomjid",h),e.attr("id","chat-room-"+j),f=b('#chat-tabs li[data-roomjid="'+g+'"]'),f.attr("data-roomjid",h),f.children("a.label").text("@"+d.getNick()),Candy.View.getCurrent().roomJid===g&&(Candy.View.getCurrent().roomJid=h))):(e=b('.room-pane.roomtype-chat[data-userjid="'+g+'"]'),e.length&&(i=Candy.Util.jidToId(e.attr("data-roomjid")),e.attr("data-userjid",h))),e&&e.length&&a.Roster.changeNick(i,d)}},a.Roster={update:function(c,d,e,f){Candy.Core.log("[View:Pane:Roster] "+e);var g=a.Chat.rooms[c].id,h=Candy.Util.jidToId(d.getJid()),i=-1,j=b("#user-"+g+"-"+h);if(b(Candy).triggerHandler("candy:view.roster.before-update",{roomJid:c,user:d,action:e,element:j}),"join"===e){i=1;var k=Mustache.to_html(Candy.View.Template.Roster.user,{roomId:g,userId:h,userJid:d.getJid(),nick:d.getNick(),displayNick:Candy.Util.crop(d.getNick(),Candy.View.getOptions().crop.roster.nickname),role:d.getRole(),affiliation:d.getAffiliation(),me:void 0!==f&&d.getNick()===f.getNick(),tooltipRole:b.i18n._("tooltipRole"),tooltipIgnored:b.i18n._("tooltipIgnored")});if(j.length<1){var l=!1,m=a.Room.getPane(c,".roster-pane");if(m.children().length>0){var n=d.getNick().toUpperCase();m.children().each(function(){var a=b(this);return a.attr("data-nick").toUpperCase()>n?(a.before(k),l=!0,!1):!0})}l||m.append(k),a.Roster.showJoinAnimation(d,h,g,c,f)}else i=0,j.replaceWith(k),b("#user-"+g+"-"+h).css({opacity:1}).show(),void 0!==f&&d.getNick()===f.getNick()&&a.Room.getUser(c)&&a.Chat.Toolbar.update(c);void 0!==f&&f.getNick()===d.getNick()?a.Room.setUser(c,d):b("#user-"+g+"-"+h).click(a.Roster.userClick),b("#user-"+g+"-"+h+" .context").click(function(b){a.Chat.Context.show(b.currentTarget,c,d),b.stopPropagation()}),void 0!==f&&f.isInPrivacyList("ignore",d.getJid())&&Candy.View.Pane.Room.addIgnoreIcon(c,d.getJid())}else if("leave"===e)a.Roster.leaveAnimation("user-"+g+"-"+h),"chat"===a.Chat.rooms[c].type?a.Chat.onInfoMessage(c,b.i18n._("userLeftRoom",[d.getNick()])):a.Chat.infoMessage(c,b.i18n._("userLeftRoom",[d.getNick()]));else if("nickchange"===e){i=0,a.Roster.changeNick(g,d),a.Room.changeDataUserJidIfUserIsMe(g,d),a.PrivateRoom.changeNick(c,d);var o=b.i18n._("userChangedNick",[d.getPreviousNick(),d.getNick()]);a.Chat.onInfoMessage(c,o)}else"kick"===e?(a.Roster.leaveAnimation("user-"+g+"-"+h),a.Chat.onInfoMessage(c,b.i18n._("userHasBeenKickedFromRoom",[d.getNick()]))):"ban"===e&&(a.Roster.leaveAnimation("user-"+g+"-"+h),a.Chat.onInfoMessage(c,b.i18n._("userHasBeenBannedFromRoom",[d.getNick()])));Candy.View.Pane.Chat.rooms[c].usercount+=i,c===Candy.View.getCurrent().roomJid&&Candy.View.Pane.Chat.Toolbar.updateUsercount(Candy.View.Pane.Chat.rooms[c].usercount),b(Candy).triggerHandler("candy:view.roster.after-update",{roomJid:c,user:d,action:e,element:b("#user-"+g+"-"+h)})},userClick:function(){var c=b(this);a.PrivateRoom.open(c.attr("data-jid"),c.attr("data-nick"),!0)},showJoinAnimation:function(c,d,e,f,g){var h="user-"+e+"-"+d,i=b("#"+h);c.getPreviousNick()&&i&&i.is(":visible")!==!1||(a.Roster.joinAnimation(h),void 0!==g&&c.getNick()!==g.getNick()&&a.Room.getUser(f)&&("chat"===a.Chat.rooms[f].type?a.Chat.onInfoMessage(f,b.i18n._("userJoinedRoom",[c.getNick()])):a.Chat.infoMessage(f,b.i18n._("userJoinedRoom",[c.getNick()]))))},joinAnimation:function(a){b("#"+a).stop(!0).slideDown("normal",function(){b(this).animate({opacity:1})})},leaveAnimation:function(a){b("#"+a).stop(!0).attr("id","#"+a+"-leaving").animate({opacity:0},{complete:function(){b(this).slideUp("normal",function(){b(this).remove()})}})},changeNick:function(a,c){Candy.Core.log("[View:Pane:Roster] changeNick");var d=Strophe.getBareJidFromJid(c.getJid())+"/"+c.getPreviousNick(),e="user-"+a+"-"+Candy.Util.jidToId(d),f=b("#"+e);f.attr("data-nick",c.getNick()),f.attr("data-jid",c.getJid()),f.children("div.label").text(c.getNick()),f.attr("id","user-"+a+"-"+Candy.Util.jidToId(c.getJid()))}},a.Message={submit:function(c){var d=Candy.View.Pane.Chat.rooms[Candy.View.getCurrent().roomJid].type,e=b(this).children(".field").val().substring(0,Candy.View.getOptions().crop.message.body),f={message:e};b(Candy).triggerHandler("candy:view.message.before-send",f),e=f.message,Candy.Core.Action.Jabber.Room.Message(Candy.View.getCurrent().roomJid,e,d),"chat"===d&&e&&a.Message.show(Candy.View.getCurrent().roomJid,a.Room.getUser(Candy.View.getCurrent().roomJid).getNick(),e),b(this).children(".field").val("").focus(),c.preventDefault()},show:function(c,d,e,f){e=Candy.Util.Parser.all(e.substring(0,Candy.View.getOptions().crop.message.body));var g={roomJid:c,name:d,message:e};if(b(Candy).triggerHandler("candy:view.message.before-show",g),e=g.message){var h={template:Candy.View.Template.Message.item,templateData:{name:d,displayName:Candy.Util.crop(d,Candy.View.getOptions().crop.message.nickname),message:e,time:Candy.Util.localizedTime(f||(new Date).toGMTString())}};b(Candy).triggerHandler("candy:view.message.before-render",h);var i=Mustache.to_html(h.template,h.templateData);a.Room.appendToMessagePane(c,i);var j=a.Room.getPane(c,".message-pane").children().last();j.find("a.label").click(function(b){b.preventDefault();var e=Candy.Core.getRoom(c);e&&d!==a.Room.getUser(Candy.View.getCurrent().roomJid).getNick()&&e.getRoster().get(c+"/"+d)&&Candy.View.Pane.PrivateRoom.open(c+"/"+d,d,!0)}),Candy.View.getCurrent().roomJid===c&&a.Window.hasFocus()||(a.Chat.increaseUnreadMessages(c),"chat"!==Candy.View.Pane.Chat.rooms[c].type||a.Window.hasFocus()||a.Chat.Toolbar.playSound()),Candy.View.getCurrent().roomJid===c&&a.Room.scrollToBottom(c),g={roomJid:c,element:j,name:d,message:e},b(Candy).triggerHandler("candy:view.message.after-show",g)}}},a}(Candy.View.Pane||{},jQuery),Candy.View.Template=function(a){return a.Window={unreadmessages:"({{count}}) {{title}}"},a.Chat={pane:'
                {{> tabs}}{{> toolbar}}{{> rooms}}
                {{> modal}}',rooms:'
                ',tabs:'
                  ',tab:'
                • {{#privateUserChat}}@{{/privateUserChat}}{{name}}×
                • ',modal:'
                  ',adminMessage:'
                • {{time}}
                  {{sender}}{{subject}} {{message}}
                • ',infoMessage:'
                • {{time}}
                  {{subject}} {{message}}
                • ',toolbar:'
                  • {{> soundcontrol}}
                  ',soundcontrol:'',Context:{menu:'
                    ',menulinks:'
                  • {{label}}
                  • ',contextModalForm:'
                    ',adminMessageReason:'×

                    {{_action}}

                    {{#reason}}

                    {{_reason}}

                    {{/reason}}'},tooltip:'
                    '},a.Room={pane:'
                    {{> roster}}{{> messages}}{{> form}}
                    ',subject:'
                  • {{time}}
                    {{roomName}}{{_roomSubject}} {{{subject}}}
                  • ',form:'
                    '},a.Roster={pane:'
                    ',user:'
                    {{displayNick}}
                    '},a.Message={pane:'
                      ',item:'
                    • {{time}}
                      {{displayName}}{{{message}}}
                    • '},a.Login={form:''},a.PresenceError={enterPasswordForm:'{{_label}}
                      ',nicknameConflictForm:'{{_label}}
                      ',displayError:"{{_error}}"},a}(Candy.View.Template||{}),Candy.View.Translation={en:{status:"Status: %s",statusConnecting:"Connecting...",statusConnected:"Connected",statusDisconnecting:"Disconnecting...",statusDisconnected:"Disconnected",statusAuthfail:"Authentication failed",roomSubject:"Subject:",messageSubmit:"Send",labelUsername:"Username:",labelNickname:"Nickname:",labelPassword:"Password:",loginSubmit:"Login",loginInvalid:"Invalid JID",reason:"Reason:",subject:"Subject:",reasonWas:"Reason was: %s.",kickActionLabel:"Kick",youHaveBeenKickedBy:"You have been kicked from %2$s by %1$s",youHaveBeenKicked:"You have been kicked from %s",banActionLabel:"Ban",youHaveBeenBannedBy:"You have been banned from %1$s by %2$s",youHaveBeenBanned:"You have been banned from %s",privateActionLabel:"Private chat",ignoreActionLabel:"Ignore",unignoreActionLabel:"Unignore",setSubjectActionLabel:"Change Subject",administratorMessageSubject:"Administrator",userJoinedRoom:"%s joined the room.",userLeftRoom:"%s left the room.",userHasBeenKickedFromRoom:"%s has been kicked from the room.",userHasBeenBannedFromRoom:"%s has been banned from the room.",userChangedNick:"%1$s has changed his nickname to %2$s.",presenceUnknownWarningSubject:"Notice:",presenceUnknownWarning:"This user might be offline. We can't track his presence.",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderator",tooltipIgnored:"You ignore this user",tooltipEmoticons:"Emoticons",tooltipSound:"Play sound for new private messages",tooltipAutoscroll:"Autoscroll",tooltipStatusmessage:"Display status messages",tooltipAdministration:"Room Administration",tooltipUsercount:"Room Occupants",enterRoomPassword:'Room "%s" is password protected.',enterRoomPasswordSubmit:"Join room",passwordEnteredInvalid:'Invalid password for room "%s".',nicknameConflict:"Username already in use. Please choose another one.",errorMembersOnly:'You can\'t join room "%s": Insufficient rights.',errorMaxOccupantsReached:'You can\'t join room "%s": Too many occupants.',errorAutojoinMissing:"No autojoin parameter set in configuration. Please set one to continue.",antiSpamMessage:"Please do not spam. You have been blocked for a short-time."},de:{status:"Status: %s",statusConnecting:"Verbinden...",statusConnected:"Verbunden",statusDisconnecting:"Verbindung trennen...",statusDisconnected:"Verbindung getrennt",statusAuthfail:"Authentifizierung fehlgeschlagen",roomSubject:"Thema:",messageSubmit:"Senden",labelUsername:"Benutzername:",labelNickname:"Spitzname:",labelPassword:"Passwort:",loginSubmit:"Anmelden",loginInvalid:"Ungültige JID",reason:"Begründung:",subject:"Titel:",reasonWas:"Begründung: %s.",kickActionLabel:"Kick",youHaveBeenKickedBy:"Du wurdest soeben aus dem Raum %1$s gekickt (%2$s)",youHaveBeenKicked:"Du wurdest soeben aus dem Raum %s gekickt",banActionLabel:"Ban",youHaveBeenBannedBy:"Du wurdest soeben aus dem Raum %1$s verbannt (%2$s)",youHaveBeenBanned:"Du wurdest soeben aus dem Raum %s verbannt",privateActionLabel:"Privater Chat",ignoreActionLabel:"Ignorieren",unignoreActionLabel:"Nicht mehr ignorieren",setSubjectActionLabel:"Thema ändern",administratorMessageSubject:"Administrator",userJoinedRoom:"%s hat soeben den Raum betreten.",userLeftRoom:"%s hat soeben den Raum verlassen.",userHasBeenKickedFromRoom:"%s ist aus dem Raum gekickt worden.",userHasBeenBannedFromRoom:"%s ist aus dem Raum verbannt worden.",userChangedNick:"%1$s hat den Nicknamen zu %2$s geändert.",presenceUnknownWarningSubject:"Hinweis:",presenceUnknownWarning:"Dieser Benutzer könnte bereits abgemeldet sein. Wir können seine Anwesenheit nicht verfolgen.",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderator",tooltipIgnored:"Du ignorierst diesen Benutzer",tooltipEmoticons:"Smileys",tooltipSound:"Ton abspielen bei neuen privaten Nachrichten",tooltipAutoscroll:"Autoscroll",tooltipStatusmessage:"Statusnachrichten anzeigen",tooltipAdministration:"Raum Administration",tooltipUsercount:"Anzahl Benutzer im Raum",enterRoomPassword:'Raum "%s" ist durch ein Passwort geschützt.',enterRoomPasswordSubmit:"Raum betreten",passwordEnteredInvalid:'Inkorrektes Passwort für Raum "%s".',nicknameConflict:"Der Benutzername wird bereits verwendet. Bitte wähle einen anderen.",errorMembersOnly:'Du kannst den Raum "%s" nicht betreten: Ungenügende Rechte.',errorMaxOccupantsReached:'Du kannst den Raum "%s" nicht betreten: Benutzerlimit erreicht.',errorAutojoinMissing:'Keine "autojoin" Konfiguration gefunden. Bitte setze eine konfiguration um fortzufahren.',antiSpamMessage:"Bitte nicht spammen. Du wurdest für eine kurze Zeit blockiert."},fr:{status:"Status : %s",statusConnecting:"Connexion…",statusConnected:"Connecté.",statusDisconnecting:"Déconnexion…",statusDisconnected:"Déconnecté.",statusAuthfail:"L'authentification a échoué",roomSubject:"Sujet :",messageSubmit:"Envoyer",labelUsername:"Nom d'utilisateur :",labelPassword:"Mot de passe :",loginSubmit:"Connexion",loginInvalid:"JID invalide",reason:"Motif :",subject:"Titre :",reasonWas:"Motif : %s.",kickActionLabel:"Kick",youHaveBeenKickedBy:"Vous avez été expulsé du salon %1$s (%2$s)",youHaveBeenKicked:"Vous avez été expulsé du salon %s",banActionLabel:"Ban",youHaveBeenBannedBy:"Vous avez été banni du salon %1$s (%2$s)",youHaveBeenBanned:"Vous avez été banni du salon %s",privateActionLabel:"Chat privé",ignoreActionLabel:"Ignorer",unignoreActionLabel:"Ne plus ignorer",setSubjectActionLabel:"Changer le sujet",administratorMessageSubject:"Administrateur",userJoinedRoom:"%s vient d'entrer dans le salon.",userLeftRoom:"%s vient de quitter le salon.",userHasBeenKickedFromRoom:"%s a été expulsé du salon.",userHasBeenBannedFromRoom:"%s a été banni du salon.",presenceUnknownWarningSubject:"Note :",presenceUnknownWarning:"Cet utilisateur n'est malheureusement plus connecté, le message ne sera pas envoyé.",dateFormat:"dd/mm/yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Modérateur",tooltipIgnored:"Vous ignorez cette personne",tooltipEmoticons:"Smileys",tooltipSound:"Jouer un son lors de la réception de nouveaux messages privés",tooltipAutoscroll:"Défilement automatique",tooltipStatusmessage:"Messages d'état",tooltipAdministration:"Administration du salon",tooltipUsercount:"Nombre d'utilisateurs dans le salon",enterRoomPassword:'Le salon "%s" est protégé par un mot de passe.',enterRoomPasswordSubmit:"Entrer dans le salon",passwordEnteredInvalid:'Le mot de passe pour le salon "%s" est invalide.',nicknameConflict:"Le nom d'utilisateur est déjà utilisé. Veuillez en choisir un autre.",errorMembersOnly:'Vous ne pouvez pas entrer dans le salon "%s" : droits insuffisants.',errorMaxOccupantsReached:'Vous ne pouvez pas entrer dans le salon "%s": Limite d\'utilisateur atteint.',antiSpamMessage:"Merci de ne pas envoyer de spam. Vous avez été bloqué pendant une courte période.."},nl:{status:"Status: %s",statusConnecting:"Verbinding maken...",statusConnected:"Verbinding is gereed",statusDisconnecting:"Verbinding verbreken...",statusDisconnected:"Verbinding is verbroken",statusAuthfail:"Authenticatie is mislukt",roomSubject:"Onderwerp:",messageSubmit:"Verstuur",labelUsername:"Gebruikersnaam:",labelPassword:"Wachtwoord:",loginSubmit:"Inloggen",loginInvalid:"JID is onjuist",reason:"Reden:",subject:"Onderwerp:",reasonWas:"De reden was: %s.",kickActionLabel:"Verwijderen",youHaveBeenKickedBy:"Je bent verwijderd van %1$s door %2$s",youHaveBeenKicked:"Je bent verwijderd van %s",banActionLabel:"Blokkeren",youHaveBeenBannedBy:"Je bent geblokkeerd van %1$s door %2$s",youHaveBeenBanned:"Je bent geblokkeerd van %s",privateActionLabel:"Prive gesprek",ignoreActionLabel:"Negeren",unignoreActionLabel:"Niet negeren",setSubjectActionLabel:"Onderwerp wijzigen",administratorMessageSubject:"Beheerder",userJoinedRoom:"%s komt de chat binnen.",userLeftRoom:"%s heeft de chat verlaten.",userHasBeenKickedFromRoom:"%s is verwijderd.",userHasBeenBannedFromRoom:"%s is geblokkeerd.",presenceUnknownWarningSubject:"Mededeling:",presenceUnknownWarning:"Deze gebruiker is waarschijnlijk offline, we kunnen zijn/haar aanwezigheid niet vaststellen.",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderator",tooltipIgnored:"Je negeert deze gebruiker",tooltipEmoticons:"Emotie-iconen",tooltipSound:"Speel een geluid af bij nieuwe privé berichten.",tooltipAutoscroll:"Automatisch scrollen",tooltipStatusmessage:"Statusberichten weergeven",tooltipAdministration:"Instellingen",tooltipUsercount:"Gebruikers",enterRoomPassword:'De Chatroom "%s" is met een wachtwoord beveiligd.',enterRoomPasswordSubmit:"Ga naar Chatroom",passwordEnteredInvalid:'Het wachtwoord voor de Chatroom "%s" is onjuist.',nicknameConflict:"De gebruikersnaam is reeds in gebruik. Probeer a.u.b. een andere gebruikersnaam.",errorMembersOnly:'Je kunt niet deelnemen aan de Chatroom "%s": Je hebt onvoldoende rechten.',errorMaxOccupantsReached:'Je kunt niet deelnemen aan de Chatroom "%s": Het maximum aantal gebruikers is bereikt.',antiSpamMessage:"Het is niet toegestaan om veel berichten naar de server te versturen. Je bent voor een korte periode geblokkeerd."},es:{status:"Estado: %s",statusConnecting:"Conectando...",statusConnected:"Conectado",statusDisconnecting:"Desconectando...",statusDisconnected:"Desconectado",statusAuthfail:"Falló la autenticación",roomSubject:"Asunto:",messageSubmit:"Enviar",labelUsername:"Usuario:",labelPassword:"Clave:",loginSubmit:"Entrar",loginInvalid:"JID no válido",reason:"Razón:",subject:"Asunto:",reasonWas:"La razón fue: %s.",kickActionLabel:"Expulsar",youHaveBeenKickedBy:"Has sido expulsado de %1$s por %2$s",youHaveBeenKicked:"Has sido expulsado de %s",banActionLabel:"Prohibir",youHaveBeenBannedBy:"Has sido expulsado permanentemente de %1$s por %2$s",youHaveBeenBanned:"Has sido expulsado permanentemente de %s",privateActionLabel:"Chat privado",ignoreActionLabel:"Ignorar",unignoreActionLabel:"No ignorar",setSubjectActionLabel:"Cambiar asunto",administratorMessageSubject:"Administrador",userJoinedRoom:"%s se ha unido a la sala.",userLeftRoom:"%s ha dejado la sala.",userHasBeenKickedFromRoom:"%s ha sido expulsado de la sala.",userHasBeenBannedFromRoom:"%s ha sido expulsado permanentemente de la sala.",presenceUnknownWarningSubject:"Atención:",presenceUnknownWarning:"Éste usuario podría estar desconectado..",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderador",tooltipIgnored:"Ignoras a éste usuario",tooltipEmoticons:"Emoticonos",tooltipSound:"Reproducir un sonido para nuevos mensajes privados",tooltipAutoscroll:"Desplazamiento automático",tooltipStatusmessage:"Mostrar mensajes de estado",tooltipAdministration:"Administración de la sala",tooltipUsercount:"Usuarios en la sala",enterRoomPassword:'La sala "%s" está protegida mediante contraseña.',enterRoomPasswordSubmit:"Unirse a la sala",passwordEnteredInvalid:'Contraseña incorrecta para la sala "%s".',nicknameConflict:"El nombre de usuario ya está siendo utilizado. Por favor elija otro.",errorMembersOnly:'No se puede unir a la sala "%s": no tiene privilegios suficientes.',errorMaxOccupantsReached:'No se puede unir a la sala "%s": demasiados participantes.',antiSpamMessage:"Por favor, no hagas spam. Has sido bloqueado temporalmente."},cn:{status:"状态: %s",statusConnecting:"连接中...",statusConnected:"已连接",statusDisconnecting:"断开连接中...",statusDisconnected:"已断开连接",statusAuthfail:"认证失败",roomSubject:"主题:",messageSubmit:"发送",labelUsername:"用户名:",labelPassword:"密码:",loginSubmit:"登录",loginInvalid:"用户名不合法",reason:"原因:",subject:"主题:",reasonWas:"原因是: %s.",kickActionLabel:"踢除",youHaveBeenKickedBy:"你在 %1$s 被管理者 %2$s 请出房间",banActionLabel:"禁言",youHaveBeenBannedBy:"你在 %1$s 被管理者 %2$s 禁言",privateActionLabel:"单独对话",ignoreActionLabel:"忽略",unignoreActionLabel:"不忽略",setSubjectActionLabel:"变更主题",administratorMessageSubject:"管理员",userJoinedRoom:"%s 加入房间",userLeftRoom:"%s 离开房间",userHasBeenKickedFromRoom:"%s 被请出这个房间",userHasBeenBannedFromRoom:"%s 被管理者禁言",presenceUnknownWarningSubject:"注意:",presenceUnknownWarning:"这个会员可能已经下线,不能追踪到他的连接信息",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"管理",tooltipIgnored:"你忽略了这个会员",tooltipEmoticons:"表情",tooltipSound:"新消息发音",tooltipAutoscroll:"滚动条",tooltipStatusmessage:"禁用状态消息",tooltipAdministration:"房间管理",tooltipUsercount:"房间占有者",enterRoomPassword:'登录房间 "%s" 需要密码.',enterRoomPasswordSubmit:"加入房间",passwordEnteredInvalid:'登录房间 "%s" 的密码不正确',nicknameConflict:"用户名已经存在,请另选一个",errorMembersOnly:'您的权限不够,不能登录房间 "%s" ',errorMaxOccupantsReached:'房间 "%s" 的人数已达上限,您不能登录',antiSpamMessage:"因为您在短时间内发送过多的消息 服务器要阻止您一小段时间。"},ja:{status:"ステータス: %s",statusConnecting:"接続中…",statusConnected:"接続されました",statusDisconnecting:"ディスコネクト中…",statusDisconnected:"ディスコネクトされました",statusAuthfail:"認証に失敗しました",roomSubject:"トピック:",messageSubmit:"送信",labelUsername:"ユーザーネーム:",labelPassword:"パスワード:",loginSubmit:"ログイン",loginInvalid:"ユーザーネームが正しくありません",reason:"理由:",subject:"トピック:",reasonWas:"理由: %s。",kickActionLabel:"キック",youHaveBeenKickedBy:"あなたは%2$sにより%1$sからキックされました。",youHaveBeenKicked:"あなたは%sからキックされました。",banActionLabel:"アカウントバン",youHaveBeenBannedBy:"あなたは%2$sにより%1$sからアカウントバンされました。",youHaveBeenBanned:"あなたは%sからアカウントバンされました。",privateActionLabel:"プライベートメッセージ",ignoreActionLabel:"無視する",unignoreActionLabel:"無視をやめる",setSubjectActionLabel:"トピックを変える",administratorMessageSubject:"管理者",userJoinedRoom:"%sは入室しました。",userLeftRoom:"%sは退室しました。",userHasBeenKickedFromRoom:"%sは部屋からキックされました。",userHasBeenBannedFromRoom:"%sは部屋からアカウントバンされました。",presenceUnknownWarningSubject:"忠告:",presenceUnknownWarning:"このユーザーのステータスは不明です。",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"モデレーター",tooltipIgnored:"このユーザーを無視設定にしている",tooltipEmoticons:"絵文字",tooltipSound:"新しいメッセージが届くたびに音を鳴らす",tooltipAutoscroll:"オートスクロール",tooltipStatusmessage:"ステータスメッセージを表示",tooltipAdministration:"部屋の管理",tooltipUsercount:"この部屋の参加者の数",enterRoomPassword:'"%s"の部屋に入るにはパスワードが必要です。',enterRoomPasswordSubmit:"部屋に入る",passwordEnteredInvalid:'"%s"のパスワードと異なるパスワードを入力しました。',nicknameConflict:"このユーザーネームはすでに利用されているため、別のユーザーネームを選んでください。",errorMembersOnly:'"%s"の部屋に入ることができません: 利用権限を満たしていません。',errorMaxOccupantsReached:'"%s"の部屋に入ることができません: 参加者の数はすでに上限に達しました。',antiSpamMessage:"スパムなどの行為はやめてください。あなたは一時的にブロックされました。"},sv:{status:"Status: %s",statusConnecting:"Ansluter...",statusConnected:"Ansluten",statusDisconnecting:"Kopplar från...",statusDisconnected:"Frånkopplad",statusAuthfail:"Autentisering misslyckades",roomSubject:"Ämne:",messageSubmit:"Skicka",labelUsername:"Användarnamn:",labelPassword:"Lösenord:",loginSubmit:"Logga in",loginInvalid:"Ogiltigt JID",reason:"Anledning:",subject:"Ämne:",reasonWas:"Anledningen var: %s.",kickActionLabel:"Sparka ut",youHaveBeenKickedBy:"Du har blivit utsparkad från %2$s av %1$s",youHaveBeenKicked:"Du har blivit utsparkad från %s",banActionLabel:"Bannlys",youHaveBeenBannedBy:"Du har blivit bannlyst från %1$s av %2$s",youHaveBeenBanned:"Du har blivit bannlyst från %s",privateActionLabel:"Privat chatt",ignoreActionLabel:"Blockera",unignoreActionLabel:"Avblockera",setSubjectActionLabel:"Ändra ämne",administratorMessageSubject:"Administratör",userJoinedRoom:"%s kom in i rummet.",userLeftRoom:"%s har lämnat rummet.",userHasBeenKickedFromRoom:"%s har blivit utsparkad ur rummet.",userHasBeenBannedFromRoom:"%s har blivit bannlyst från rummet.",presenceUnknownWarningSubject:"Notera:",presenceUnknownWarning:"Denna användare kan vara offline. Vi kan inte följa dennes närvaro.",dateFormat:"yyyy-mm-dd",timeFormat:"HH:MM:ss",tooltipRole:"Moderator",tooltipIgnored:"Du blockerar denna användare",tooltipEmoticons:"Smilies",tooltipSound:"Spela upp ett ljud vid nytt privat meddelande",tooltipAutoscroll:"Autoskrolla",tooltipStatusmessage:"Visa statusmeddelanden",tooltipAdministration:"Rumadministrering",tooltipUsercount:"Antal användare i rummet",enterRoomPassword:'Rummet "%s" är lösenordsskyddat.',enterRoomPasswordSubmit:"Anslut till rum",passwordEnteredInvalid:'Ogiltigt lösenord för rummet "%s".',nicknameConflict:"Upptaget användarnamn. Var god välj ett annat.",errorMembersOnly:'Du kan inte ansluta till rummet "%s": Otillräckliga rättigheter.',errorMaxOccupantsReached:'Du kan inte ansluta till rummet "%s": Rummet är fullt.',antiSpamMessage:"Var god avstå från att spamma. Du har blivit blockerad för en kort stund."},it:{status:"Stato: %s",statusConnecting:"Connessione...",statusConnected:"Connessione",statusDisconnecting:"Disconnessione...",statusDisconnected:"Disconnesso",statusAuthfail:"Autenticazione fallita",roomSubject:"Oggetto:",messageSubmit:"Invia",labelUsername:"Nome utente:",labelPassword:"Password:",loginSubmit:"Login",loginInvalid:"JID non valido",reason:"Ragione:",subject:"Oggetto:",reasonWas:"Ragione precedente: %s.",kickActionLabel:"Espelli",youHaveBeenKickedBy:"Sei stato espulso da %2$s da %1$s",youHaveBeenKicked:"Sei stato espulso da %s",banActionLabel:"Escluso",youHaveBeenBannedBy:"Sei stato escluso da %1$s da %2$s",youHaveBeenBanned:"Sei stato escluso da %s",privateActionLabel:"Stanza privata",ignoreActionLabel:"Ignora",unignoreActionLabel:"Non ignorare",setSubjectActionLabel:"Cambia oggetto",administratorMessageSubject:"Amministratore",userJoinedRoom:"%s si è unito alla stanza.",userLeftRoom:"%s ha lasciato la stanza.",userHasBeenKickedFromRoom:"%s è stato espulso dalla stanza.",userHasBeenBannedFromRoom:"%s è stato escluso dalla stanza.",presenceUnknownWarningSubject:"Nota:",presenceUnknownWarning:"Questo utente potrebbe essere offline. Non possiamo tracciare la sua presenza.",dateFormat:"dd/mm/yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderatore",tooltipIgnored:"Stai ignorando questo utente",tooltipEmoticons:"Emoticons",tooltipSound:"Riproduci un suono quando arrivano messaggi privati",tooltipAutoscroll:"Autoscroll",tooltipStatusmessage:"Mostra messaggi di stato",tooltipAdministration:"Amministrazione stanza",tooltipUsercount:"Partecipanti alla stanza",enterRoomPassword:'La stanza "%s" è protetta da password.',enterRoomPasswordSubmit:"Unisciti alla stanza",passwordEnteredInvalid:'Password non valida per la stanza "%s".',nicknameConflict:"Nome utente già in uso. Scegline un altro.",errorMembersOnly:'Non puoi unirti alla stanza "%s": Permessi insufficienti.',errorMaxOccupantsReached:'Non puoi unirti alla stanza "%s": Troppi partecipanti.',antiSpamMessage:"Per favore non scrivere messaggi pubblicitari. Sei stato bloccato per un po' di tempo."},pt:{status:"Status: %s",statusConnecting:"Conectando...",statusConnected:"Conectado",statusDisconnecting:"Desligando...",statusDisconnected:"Desligado",statusAuthfail:"Falha na autenticação",roomSubject:"Assunto:",messageSubmit:"Enviar",labelUsername:"Usuário:",labelPassword:"Senha:",loginSubmit:"Entrar",loginInvalid:"JID inválido",reason:"Motivo:",subject:"Assunto:",reasonWas:"O motivo foi: %s.",kickActionLabel:"Excluir",youHaveBeenKickedBy:"Você foi excluido de %1$s por %2$s",youHaveBeenKicked:"Você foi excluido de %s",banActionLabel:"Bloquear",youHaveBeenBannedBy:"Você foi excluido permanentemente de %1$s por %2$s",youHaveBeenBanned:"Você foi excluido permanentemente de %s",privateActionLabel:"Bate-papo privado",ignoreActionLabel:"Ignorar",unignoreActionLabel:"Não ignorar",setSubjectActionLabel:"Trocar Assunto",administratorMessageSubject:"Administrador",userJoinedRoom:"%s entrou na sala.",userLeftRoom:"%s saiu da sala.",userHasBeenKickedFromRoom:"%s foi excluido da sala.",userHasBeenBannedFromRoom:"%s foi excluido permanentemente da sala.",presenceUnknownWarning:"Este usuário pode estar desconectado. Não é possível determinar o status.",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderador",tooltipIgnored:"Você ignora este usuário",tooltipEmoticons:"Emoticons",tooltipSound:"Reproduzir o som para novas mensagens privados",tooltipAutoscroll:"Deslocamento automático",tooltipStatusmessage:"Mostrar mensagens de status",tooltipAdministration:"Administração da sala",tooltipUsercount:"Usuários na sala",enterRoomPassword:'A sala "%s" é protegida por senha.',enterRoomPasswordSubmit:"Junte-se à sala",passwordEnteredInvalid:'Senha incorreta para a sala "%s".',nicknameConflict:"O nome de usuário já está em uso. Por favor, escolha outro.",errorMembersOnly:'Você não pode participar da sala "%s": privilégios insuficientes.',errorMaxOccupantsReached:'Você não pode participar da sala "%s": muitos participantes.',antiSpamMessage:"Por favor, não envie spam. Você foi bloqueado temporariamente."},pt_br:{status:"Estado: %s",statusConnecting:"Conectando...",statusConnected:"Conectado",statusDisconnecting:"Desconectando...",statusDisconnected:"Desconectado",statusAuthfail:"Autenticação falhou",roomSubject:"Assunto:",messageSubmit:"Enviar",labelUsername:"Usuário:",labelPassword:"Senha:",loginSubmit:"Entrar",loginInvalid:"JID inválido",reason:"Motivo:",subject:"Assunto:",reasonWas:"Motivo foi: %s.",kickActionLabel:"Derrubar",youHaveBeenKickedBy:"Você foi derrubado de %2$s por %1$s",youHaveBeenKicked:"Você foi derrubado de %s",banActionLabel:"Banir",youHaveBeenBannedBy:"Você foi banido de %1$s por %2$s",youHaveBeenBanned:"Você foi banido de %s",privateActionLabel:"Conversa privada",ignoreActionLabel:"Ignorar",unignoreActionLabel:"Não ignorar",setSubjectActionLabel:"Mudar Assunto",administratorMessageSubject:"Administrador",userJoinedRoom:"%s entrou na sala.",userLeftRoom:"%s saiu da sala.",userHasBeenKickedFromRoom:"%s foi derrubado da sala.",userHasBeenBannedFromRoom:"%s foi banido da sala.",presenceUnknownWarningSubject:"Aviso:",presenceUnknownWarning:"Este usuário pode estar desconectado.. Não conseguimos rastrear sua presença..",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderador",tooltipIgnored:"Você ignora este usuário",tooltipEmoticons:"Emoticons",tooltipSound:"Tocar som para novas mensagens privadas",tooltipAutoscroll:"Auto-rolagem",tooltipStatusmessage:"Exibir mensagens de estados",tooltipAdministration:"Administração de Sala",tooltipUsercount:"Participantes da Sala",enterRoomPassword:'Sala "%s" é protegida por senha.',enterRoomPasswordSubmit:"Entrar na sala",passwordEnteredInvalid:'Senha inváida para sala "%s".',nicknameConflict:"Nome de usuário já em uso. Por favor escolha outro.",errorMembersOnly:'Você não pode entrar na sala "%s": privilégios insuficientes.',errorMaxOccupantsReached:'Você não pode entrar na sala "%s": máximo de participantes atingido.',antiSpamMessage:"Por favor, não faça spam. Você foi bloqueado temporariamente."},ru:{status:"Статус: %s",statusConnecting:"Подключение...",statusConnected:"Подключено",statusDisconnecting:"Отключение...",statusDisconnected:"Отключено",statusAuthfail:"Неверный логин",roomSubject:"Топик:",messageSubmit:"Послать",labelUsername:"Имя:",labelPassword:"Пароль:",loginSubmit:"Логин",loginInvalid:"Неверный JID",reason:"Причина:",subject:"Топик:",reasonWas:"Причина была: %s.",kickActionLabel:"Выбросить",youHaveBeenKickedBy:"Пользователь %1$s выбросил вас из чата %2$s",youHaveBeenKicked:"Вас выбросили из чата %s",banActionLabel:"Запретить доступ",youHaveBeenBannedBy:"Пользователь %1$s запретил вам доступ в чат %2$s",youHaveBeenBanned:"Вам запретили доступ в чат %s",privateActionLabel:"Один-на-один чат",ignoreActionLabel:"Игнорировать",unignoreActionLabel:"Отменить игнорирование",setSubjectActionLabel:"Изменить топик",administratorMessageSubject:"Администратор",userJoinedRoom:"%s вошёл в чат.",userLeftRoom:"%s вышел из чата.",userHasBeenKickedFromRoom:"%s выброшен из чата.",userHasBeenBannedFromRoom:"%s запрещён доступ в чат.",presenceUnknownWarningSubject:"Уведомление:",presenceUnknownWarning:"Этот пользователь вероятнее всего оффлайн.",dateFormat:"mm.dd.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Модератор",tooltipIgnored:"Вы игнорируете этого пользователя.",tooltipEmoticons:"Смайлики",tooltipSound:"Озвучивать новое частное сообщение",tooltipAutoscroll:"Авто-прокручивание",tooltipStatusmessage:"Показывать статус сообщения",tooltipAdministration:"Администрирование чат комнаты",tooltipUsercount:"Участники чата",enterRoomPassword:'Чат комната "%s" защищена паролем.',enterRoomPasswordSubmit:"Войти в чат",passwordEnteredInvalid:'Неверный пароль для комнаты "%s".',nicknameConflict:"Это имя уже используется. Пожалуйста выберите другое имя.",errorMembersOnly:'Вы не можете войти в чат "%s": Недостаточно прав доступа.',errorMaxOccupantsReached:'Вы не можете войти в чат "%s": Слишком много участников.',antiSpamMessage:"Пожалуйста не рассылайте спам. Вас заблокировали на короткое время."},ca:{status:"Estat: %s",statusConnecting:"Connectant...",statusConnected:"Connectat",statusDisconnecting:"Desconnectant...",statusDisconnected:"Desconnectat",statusAuthfail:"Ha fallat la autenticació",roomSubject:"Assumpte:",messageSubmit:"Enviar",labelUsername:"Usuari:",labelPassword:"Clau:",loginSubmit:"Entrar",loginInvalid:"JID no vàlid",reason:"Raó:",subject:"Assumpte:",reasonWas:"La raó ha estat: %s.",kickActionLabel:"Expulsar",youHaveBeenKickedBy:"Has estat expulsat de %1$s per %2$s",youHaveBeenKicked:"Has estat expulsat de %s",banActionLabel:"Prohibir",youHaveBeenBannedBy:"Has estat expulsat permanentment de %1$s per %2$s",youHaveBeenBanned:"Has estat expulsat permanentment de %s",privateActionLabel:"Xat privat",ignoreActionLabel:"Ignorar",unignoreActionLabel:"No ignorar",setSubjectActionLabel:"Canviar assumpte",administratorMessageSubject:"Administrador",userJoinedRoom:"%s ha entrat a la sala.",userLeftRoom:"%s ha deixat la sala.",userHasBeenKickedFromRoom:"%s ha estat expulsat de la sala.",userHasBeenBannedFromRoom:"%s ha estat expulsat permanentment de la sala.",presenceUnknownWarningSubject:"Atenció:",presenceUnknownWarning:"Aquest usuari podria estar desconnectat ...",dateFormat:"dd.mm.yyyy",timeFormat:"HH:MM:ss",tooltipRole:"Moderador",tooltipIgnored:"Estàs ignorant aquest usuari",tooltipEmoticons:"Emoticones",tooltipSound:"Reproduir un so per a nous missatges",tooltipAutoscroll:"Desplaçament automàtic",tooltipStatusmessage:"Mostrar missatges d'estat",tooltipAdministration:"Administració de la sala",tooltipUsercount:"Usuaris dins la sala",enterRoomPassword:'La sala "%s" està protegida amb contrasenya.',enterRoomPasswordSubmit:"Entrar a la sala",passwordEnteredInvalid:'Contrasenya incorrecta per a la sala "%s".',nicknameConflict:"El nom d'usuari ja s'està utilitzant. Si us plau, escolleix-ne un altre.",errorMembersOnly:'No pots unir-te a la sala "%s": no tens prous privilegis.',errorMaxOccupantsReached:'No pots unir-te a la sala "%s": hi ha masses participants.',antiSpamMessage:"Si us plau, no facis spam. Has estat bloquejat temporalment."}}; diff --git a/libs/libs.bundle.js b/libs/libs.bundle.js index 8aa84062..880c8760 100644 --- a/libs/libs.bundle.js +++ b/libs/libs.bundle.js @@ -1,69 +1,55 @@ // This code was written by Tyler Akins and has been placed in the // public domain. It would be nice if you left this header intact. // Base64 code from Tyler Akins -- http://rumkin.com - -var Base64 = (function () { +var Base64 = function() { var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - var obj = { /** * Encodes a string in base64 * @param {String} input The string to encode in base64. */ - encode: function (input) { + encode: function(input) { var output = ""; var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; - do { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); - enc1 = chr1 >> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc2 = (chr1 & 3) << 4 | chr2 >> 4; + enc3 = (chr2 & 15) << 2 | chr3 >> 6; enc4 = chr3 & 63; - if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } - - output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + - keyStr.charAt(enc3) + keyStr.charAt(enc4); + output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } while (i < input.length); - return output; }, - /** * Decodes a base64 string. * @param {String} input The string to decode. */ - decode: function (input) { + decode: function(input) { var output = ""; var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; - // remove all characters that are not A-Z, a-z, 0-9, +, /, or = input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); - do { enc1 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++)); enc4 = keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - + chr1 = enc1 << 2 | enc2 >> 4; + chr2 = (enc2 & 15) << 4 | enc3 >> 2; + chr3 = (enc3 & 3) << 6 | enc4; output = output + String.fromCharCode(chr1); - if (enc3 != 64) { output = output + String.fromCharCode(chr2); } @@ -71,13 +57,12 @@ var Base64 = (function () { output = output + String.fromCharCode(chr3); } } while (i < input.length); - return output; } }; - return obj; -})(); +}(); + /* * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined * in FIPS PUB 180-1 @@ -86,205 +71,211 @@ var Base64 = (function () { * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for details. */ - /* * Configurable variables. You may need to tweak these to be compatible with * the server-side, but the defaults work in most cases. */ -var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ -var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */ -var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ +var hexcase = 0; + +/* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = "="; + +/* base-64 pad character. "=" for strict RFC compliance */ +var chrsz = 8; +/* bits per input character. 8 - ASCII; 16 - Unicode */ /* * These are the functions you'll usually want to call * They take string arguments and return either hex or base-64 encoded strings */ -function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} -function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} -function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} -function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} -function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} -function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} +function hex_sha1(s) { + return binb2hex(core_sha1(str2binb(s), s.length * chrsz)); +} + +function b64_sha1(s) { + return binb2b64(core_sha1(str2binb(s), s.length * chrsz)); +} + +function str_sha1(s) { + return binb2str(core_sha1(str2binb(s), s.length * chrsz)); +} + +function hex_hmac_sha1(key, data) { + return binb2hex(core_hmac_sha1(key, data)); +} + +function b64_hmac_sha1(key, data) { + return binb2b64(core_hmac_sha1(key, data)); +} + +function str_hmac_sha1(key, data) { + return binb2str(core_hmac_sha1(key, data)); +} /* * Perform a simple self-test to see if the VM is working */ -function sha1_vm_test() -{ - return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; +function sha1_vm_test() { + return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; } /* * Calculate the SHA-1 of an array of big-endian words, and a bit length */ -function core_sha1(x, len) -{ - /* append padding */ - x[len >> 5] |= 0x80 << (24 - len % 32); - x[((len + 64 >> 9) << 4) + 15] = len; - - var w = new Array(80); - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - var e = -1009589776; - - var i, j, t, olda, oldb, oldc, oldd, olde; - for (i = 0; i < x.length; i += 16) - { - olda = a; - oldb = b; - oldc = c; - oldd = d; - olde = e; - - for (j = 0; j < 80; j++) - { - if (j < 16) { w[j] = x[i + j]; } - else { w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); } - t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), - safe_add(safe_add(e, w[j]), sha1_kt(j))); - e = d; - d = c; - c = rol(b, 30); - b = a; - a = t; +function core_sha1(x, len) { + /* append padding */ + x[len >> 5] |= 128 << 24 - len % 32; + x[(len + 64 >> 9 << 4) + 15] = len; + var w = new Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + var i, j, t, olda, oldb, oldc, oldd, olde; + for (i = 0; i < x.length; i += 16) { + olda = a; + oldb = b; + oldc = c; + oldd = d; + olde = e; + for (j = 0; j < 80; j++) { + if (j < 16) { + w[j] = x[i + j]; + } else { + w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); + } + t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); } - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - e = safe_add(e, olde); - } - return [a, b, c, d, e]; + return [ a, b, c, d, e ]; } /* * Perform the appropriate triplet combination function for the current * iteration */ -function sha1_ft(t, b, c, d) -{ - if (t < 20) { return (b & c) | ((~b) & d); } - if (t < 40) { return b ^ c ^ d; } - if (t < 60) { return (b & c) | (b & d) | (c & d); } - return b ^ c ^ d; +function sha1_ft(t, b, c, d) { + if (t < 20) { + return b & c | ~b & d; + } + if (t < 40) { + return b ^ c ^ d; + } + if (t < 60) { + return b & c | b & d | c & d; + } + return b ^ c ^ d; } /* * Determine the appropriate additive constant for the current iteration */ -function sha1_kt(t) -{ - return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : - (t < 60) ? -1894007588 : -899497514; +function sha1_kt(t) { + return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514; } /* * Calculate the HMAC-SHA1 of a key and some data */ -function core_hmac_sha1(key, data) -{ - var bkey = str2binb(key); - if (bkey.length > 16) { bkey = core_sha1(bkey, key.length * chrsz); } - - var ipad = new Array(16), opad = new Array(16); - for (var i = 0; i < 16; i++) - { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - - var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); - return core_sha1(opad.concat(hash), 512 + 160); +function core_hmac_sha1(key, data) { + var bkey = str2binb(key); + if (bkey.length > 16) { + bkey = core_sha1(bkey, key.length * chrsz); + } + var ipad = new Array(16), opad = new Array(16); + for (var i = 0; i < 16; i++) { + ipad[i] = bkey[i] ^ 909522486; + opad[i] = bkey[i] ^ 1549556828; + } + var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); + return core_sha1(opad.concat(hash), 512 + 160); } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ -function safe_add(x, y) -{ - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); +function safe_add(x, y) { + var lsw = (x & 65535) + (y & 65535); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return msw << 16 | lsw & 65535; } /* * Bitwise rotate a 32-bit number to the left. */ -function rol(num, cnt) -{ - return (num << cnt) | (num >>> (32 - cnt)); +function rol(num, cnt) { + return num << cnt | num >>> 32 - cnt; } /* * Convert an 8-bit or 16-bit string to an array of big-endian words * In 8-bit function, characters >255 have their hi-byte silently ignored. */ -function str2binb(str) -{ - var bin = []; - var mask = (1 << chrsz) - 1; - for (var i = 0; i < str.length * chrsz; i += chrsz) - { - bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); - } - return bin; +function str2binb(str) { + var bin = []; + var mask = (1 << chrsz) - 1; + for (var i = 0; i < str.length * chrsz; i += chrsz) { + bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << 32 - chrsz - i % 32; + } + return bin; } /* * Convert an array of big-endian words to a string */ -function binb2str(bin) -{ - var str = ""; - var mask = (1 << chrsz) - 1; - for (var i = 0; i < bin.length * 32; i += chrsz) - { - str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); - } - return str; +function binb2str(bin) { + var str = ""; + var mask = (1 << chrsz) - 1; + for (var i = 0; i < bin.length * 32; i += chrsz) { + str += String.fromCharCode(bin[i >> 5] >>> 32 - chrsz - i % 32 & mask); + } + return str; } /* * Convert an array of big-endian words to a hex string. */ -function binb2hex(binarray) -{ - var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; - var str = ""; - for (var i = 0; i < binarray.length * 4; i++) - { - str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + - hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); - } - return str; +function binb2hex(binarray) { + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for (var i = 0; i < binarray.length * 4; i++) { + str += hex_tab.charAt(binarray[i >> 2] >> (3 - i % 4) * 8 + 4 & 15) + hex_tab.charAt(binarray[i >> 2] >> (3 - i % 4) * 8 & 15); + } + return str; } /* * Convert an array of big-endian words to a base-64 string */ -function binb2b64(binarray) -{ - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var str = ""; - var triplet, j; - for (var i = 0; i < binarray.length * 4; i += 3) - { - triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) | - (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | - ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); - for (j = 0; j < 4; j++) - { - if (i * 8 + j * 6 > binarray.length * 32) { str += b64pad; } - else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } +function binb2b64(binarray) { + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + var triplet, j; + for (var i = 0; i < binarray.length * 4; i += 3) { + triplet = (binarray[i >> 2] >> 8 * (3 - i % 4) & 255) << 16 | (binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4) & 255) << 8 | binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4) & 255; + for (j = 0; j < 4; j++) { + if (i * 8 + j * 6 > binarray.length * 32) { + str += b64pad; + } else { + str += tab.charAt(triplet >> 6 * (3 - j) & 63); + } + } } - } - return str; + return str; } + /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. @@ -293,287 +284,252 @@ function binb2b64(binarray) * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. */ - -var MD5 = (function () { +var MD5 = function() { /* * Configurable variables. You may need to tweak these to be compatible with * the server-side, but the defaults work in most cases. */ - var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ - var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ - var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ - + var hexcase = 0; + /* hex output format. 0 - lowercase; 1 - uppercase */ + var b64pad = ""; + /* base-64 pad character. "=" for strict RFC compliance */ + var chrsz = 8; + /* bits per input character. 8 - ASCII; 16 - Unicode */ /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ - var safe_add = function (x, y) { - var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var safe_add = function(x, y) { + var lsw = (x & 65535) + (y & 65535); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); + return msw << 16 | lsw & 65535; }; - /* * Bitwise rotate a 32-bit number to the left. */ - var bit_rol = function (num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)); + var bit_rol = function(num, cnt) { + return num << cnt | num >>> 32 - cnt; }; - /* * Convert a string to an array of little-endian words * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. */ - var str2binl = function (str) { + var str2binl = function(str) { var bin = []; var mask = (1 << chrsz) - 1; - for(var i = 0; i < str.length * chrsz; i += chrsz) - { - bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); + for (var i = 0; i < str.length * chrsz; i += chrsz) { + bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << i % 32; } return bin; }; - /* * Convert an array of little-endian words to a string */ - var binl2str = function (bin) { + var binl2str = function(bin) { var str = ""; var mask = (1 << chrsz) - 1; - for(var i = 0; i < bin.length * 32; i += chrsz) - { - str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); + for (var i = 0; i < bin.length * 32; i += chrsz) { + str += String.fromCharCode(bin[i >> 5] >>> i % 32 & mask); } return str; }; - /* * Convert an array of little-endian words to a hex string. */ - var binl2hex = function (binarray) { + var binl2hex = function(binarray) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; - for(var i = 0; i < binarray.length * 4; i++) - { - str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + - hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); + for (var i = 0; i < binarray.length * 4; i++) { + str += hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 15) + hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 & 15); } return str; }; - /* * Convert an array of little-endian words to a base-64 string */ - var binl2b64 = function (binarray) { + var binl2b64 = function(binarray) { var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var str = ""; var triplet, j; - for(var i = 0; i < binarray.length * 4; i += 3) - { - triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) | - (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) | - ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); - for(j = 0; j < 4; j++) - { - if(i * 8 + j * 6 > binarray.length * 32) { str += b64pad; } - else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } + for (var i = 0; i < binarray.length * 4; i += 3) { + triplet = (binarray[i >> 2] >> 8 * (i % 4) & 255) << 16 | (binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4) & 255) << 8 | binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4) & 255; + for (j = 0; j < 4; j++) { + if (i * 8 + j * 6 > binarray.length * 32) { + str += b64pad; + } else { + str += tab.charAt(triplet >> 6 * (3 - j) & 63); + } } } return str; }; - /* * These functions implement the four basic operations the algorithm uses. */ - var md5_cmn = function (q, a, b, x, s, t) { - return safe_add(bit_rol(safe_add(safe_add(a, q),safe_add(x, t)), s),b); + var md5_cmn = function(q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); }; - - var md5_ff = function (a, b, c, d, x, s, t) { - return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); + var md5_ff = function(a, b, c, d, x, s, t) { + return md5_cmn(b & c | ~b & d, a, b, x, s, t); }; - - var md5_gg = function (a, b, c, d, x, s, t) { - return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); + var md5_gg = function(a, b, c, d, x, s, t) { + return md5_cmn(b & d | c & ~d, a, b, x, s, t); }; - - var md5_hh = function (a, b, c, d, x, s, t) { + var md5_hh = function(a, b, c, d, x, s, t) { return md5_cmn(b ^ c ^ d, a, b, x, s, t); }; - - var md5_ii = function (a, b, c, d, x, s, t) { - return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); + var md5_ii = function(a, b, c, d, x, s, t) { + return md5_cmn(c ^ (b | ~d), a, b, x, s, t); }; - /* * Calculate the MD5 of an array of little-endian words, and a bit length */ - var core_md5 = function (x, len) { + var core_md5 = function(x, len) { /* append padding */ - x[len >> 5] |= 0x80 << ((len) % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - var a = 1732584193; + x[len >> 5] |= 128 << len % 32; + x[(len + 64 >>> 9 << 4) + 14] = len; + var a = 1732584193; var b = -271733879; var c = -1732584194; - var d = 271733878; - + var d = 271733878; var olda, oldb, oldc, oldd; - for (var i = 0; i < x.length; i += 16) - { + for (var i = 0; i < x.length; i += 16) { olda = a; oldb = b; oldc = c; oldd = d; - - a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); - d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); - c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); - b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); - a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); - d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); - c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); - b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); - a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); - d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); - c = md5_ff(c, d, a, b, x[i+10], 17, -42063); - b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); - a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); - d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); - c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); - b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); - - a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); - d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); - c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); - b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); - a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); - d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); - c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); - b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); - a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); - d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); - c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); - b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); - a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); - d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); - c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); - b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); - - a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); - d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); - c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); - b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); - a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); - d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); - c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); - b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); - a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); - d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); - c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); - b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); - a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); - d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); - c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); - b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); - - a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); - d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); - c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); - b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); - a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); - d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); - c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); - b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); - a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); - d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); - c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); - b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); - a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); - d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); - c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); - b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); - + a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936); + d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); + d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); + d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); + b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); + d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); + a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); + d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); + c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); + d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); + c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); + d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); + c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); + d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); + c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); + a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); + d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); + d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); + d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); + d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); + a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844); + d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); + d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); + d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); + d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); } - return [a, b, c, d]; + return [ a, b, c, d ]; }; - - /* * Calculate the HMAC-MD5, of a key and some data */ - var core_hmac_md5 = function (key, data) { + var core_hmac_md5 = function(key, data) { var bkey = str2binl(key); - if(bkey.length > 16) { bkey = core_md5(bkey, key.length * chrsz); } - + if (bkey.length > 16) { + bkey = core_md5(bkey, key.length * chrsz); + } var ipad = new Array(16), opad = new Array(16); - for(var i = 0; i < 16; i++) - { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; + for (var i = 0; i < 16; i++) { + ipad[i] = bkey[i] ^ 909522486; + opad[i] = bkey[i] ^ 1549556828; } - var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); return core_md5(opad.concat(hash), 512 + 128); }; - var obj = { /* * These are the functions you'll usually want to call. * They take string arguments and return either hex or base-64 encoded * strings. */ - hexdigest: function (s) { + hexdigest: function(s) { return binl2hex(core_md5(str2binl(s), s.length * chrsz)); }, - - b64digest: function (s) { + b64digest: function(s) { return binl2b64(core_md5(str2binl(s), s.length * chrsz)); }, - - hash: function (s) { + hash: function(s) { return binl2str(core_md5(str2binl(s), s.length * chrsz)); }, - - hmac_hexdigest: function (key, data) { + hmac_hexdigest: function(key, data) { return binl2hex(core_hmac_md5(key, data)); }, - - hmac_b64digest: function (key, data) { + hmac_b64digest: function(key, data) { return binl2b64(core_hmac_md5(key, data)); }, - - hmac_hash: function (key, data) { + hmac_hash: function(key, data) { return binl2str(core_hmac_md5(key, data)); }, - /* * Perform a simple self-test to see if the VM is working */ - test: function () { + test: function() { return MD5.hexdigest("abc") === "900150983cd24fb0d6963f7d28e17f72"; } }; - return obj; -})(); +}(); + /* This program is distributed under the terms of the MIT license. Please see the LICENSE file for details. Copyright 2006-2008, OGG, LLC */ - /* jslint configuration: */ /*global document, window, setTimeout, clearTimeout, console, XMLHttpRequest, ActiveXObject, Base64, MD5, Strophe, $build, $msg, $iq, $pres */ - /** File: strophe.js * A JavaScript library for XMPP BOSH/XMPP over Websocket. * @@ -587,7 +543,6 @@ var MD5 = (function () { * For more information on XMPP-over WebSocket see this RFC draft: * http://tools.ietf.org/html/draft-ietf-xmpp-websocket-00 */ - /** PrivateFunction: Function.prototype.bind * Bind a function to an instance. * @@ -610,17 +565,13 @@ var MD5 = (function () { * The bound function. */ if (!Function.prototype.bind) { - Function.prototype.bind = function (obj /*, arg1, arg2, ... */) - { + Function.prototype.bind = function(obj) { var func = this; var _slice = Array.prototype.slice; var _concat = Array.prototype.concat; var _args = _slice.call(arguments, 1); - - return function () { - return func.apply(obj ? obj : this, - _concat.call(_args, - _slice.call(arguments, 0))); + return function() { + return func.apply(obj ? obj : this, _concat.call(_args, _slice.call(arguments, 0))); }; }; } @@ -639,24 +590,19 @@ if (!Function.prototype.bind) { * Returns: * The index of elt in the array or -1 if not found. */ -if (!Array.prototype.indexOf) -{ - Array.prototype.indexOf = function(elt /*, from*/) - { +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(elt) { var len = this.length; - var from = Number(arguments[1]) || 0; - from = (from < 0) ? Math.ceil(from) : Math.floor(from); + from = from < 0 ? Math.ceil(from) : Math.floor(from); if (from < 0) { from += len; } - - for (; from < len; from++) { + for (;from < len; from++) { if (from in this && this[from] === elt) { return from; } } - return -1; }; } @@ -666,11 +612,9 @@ if (!Array.prototype.indexOf) * on page reload, these references will still be available to callbacks * that are still executing. */ - -(function (callback) { -var Strophe; - -/** Function: $build +(function(callback) { + var Strophe; + /** Function: $build * Create a Strophe.Builder. * This is an alias for 'new Strophe.Builder(name, attrs)'. * @@ -681,8 +625,10 @@ var Strophe; * Returns: * A new Strophe.Builder object. */ -function $build(name, attrs) { return new Strophe.Builder(name, attrs); } -/** Function: $msg + function $build(name, attrs) { + return new Strophe.Builder(name, attrs); + } + /** Function: $msg * Create a Strophe.Builder with a element as the root. * * Parmaeters: @@ -691,8 +637,10 @@ function $build(name, attrs) { return new Strophe.Builder(name, attrs); } * Returns: * A new Strophe.Builder object. */ -function $msg(attrs) { return new Strophe.Builder("message", attrs); } -/** Function: $iq + function $msg(attrs) { + return new Strophe.Builder("message", attrs); + } + /** Function: $iq * Create a Strophe.Builder with an element as the root. * * Parameters: @@ -701,8 +649,10 @@ function $msg(attrs) { return new Strophe.Builder("message", attrs); } * Returns: * A new Strophe.Builder object. */ -function $iq(attrs) { return new Strophe.Builder("iq", attrs); } -/** Function: $pres + function $iq(attrs) { + return new Strophe.Builder("iq", attrs); + } + /** Function: $pres * Create a Strophe.Builder with a element as the root. * * Parameters: @@ -711,23 +661,23 @@ function $iq(attrs) { return new Strophe.Builder("iq", attrs); } * Returns: * A new Strophe.Builder object. */ -function $pres(attrs) { return new Strophe.Builder("presence", attrs); } - -/** Class: Strophe + function $pres(attrs) { + return new Strophe.Builder("presence", attrs); + } + /** Class: Strophe * An object container for all Strophe library functions. * * This class is just a container for all the objects and constants * used in the library. It is not meant to be instantiated, but to * provide a namespace for library objects, constants, and functions. */ -Strophe = { - /** Constant: VERSION + Strophe = { + /** Constant: VERSION * The version of the Strophe library. Unreleased builds will have * a version of head-HASH where HASH is a partial revision. */ - VERSION: "a1f13b2", - - /** Constants: XMPP Namespace Constants + VERSION: "a1f13b2", + /** Constants: XMPP Namespace Constants * Common namespace constants from the XMPP RFCs and XEPs. * * NS.HTTPBIND - HTTP BIND namespace from XEP 124. @@ -746,83 +696,77 @@ Strophe = { * NS.XHTML_IM - XHTML-IM namespace from XEP 71. * NS.XHTML - XHTML body namespace from XEP 71. */ - NS: { - HTTPBIND: "http://jabber.org/protocol/httpbind", - BOSH: "urn:xmpp:xbosh", - CLIENT: "jabber:client", - AUTH: "jabber:iq:auth", - ROSTER: "jabber:iq:roster", - PROFILE: "jabber:iq:profile", - DISCO_INFO: "http://jabber.org/protocol/disco#info", - DISCO_ITEMS: "http://jabber.org/protocol/disco#items", - MUC: "http://jabber.org/protocol/muc", - SASL: "urn:ietf:params:xml:ns:xmpp-sasl", - STREAM: "http://etherx.jabber.org/streams", - BIND: "urn:ietf:params:xml:ns:xmpp-bind", - SESSION: "urn:ietf:params:xml:ns:xmpp-session", - VERSION: "jabber:iq:version", - STANZAS: "urn:ietf:params:xml:ns:xmpp-stanzas", - XHTML_IM: "http://jabber.org/protocol/xhtml-im", - XHTML: "http://www.w3.org/1999/xhtml" - }, - - - /** Constants: XHTML_IM Namespace + NS: { + HTTPBIND: "http://jabber.org/protocol/httpbind", + BOSH: "urn:xmpp:xbosh", + CLIENT: "jabber:client", + AUTH: "jabber:iq:auth", + ROSTER: "jabber:iq:roster", + PROFILE: "jabber:iq:profile", + DISCO_INFO: "http://jabber.org/protocol/disco#info", + DISCO_ITEMS: "http://jabber.org/protocol/disco#items", + MUC: "http://jabber.org/protocol/muc", + SASL: "urn:ietf:params:xml:ns:xmpp-sasl", + STREAM: "http://etherx.jabber.org/streams", + BIND: "urn:ietf:params:xml:ns:xmpp-bind", + SESSION: "urn:ietf:params:xml:ns:xmpp-session", + VERSION: "jabber:iq:version", + STANZAS: "urn:ietf:params:xml:ns:xmpp-stanzas", + XHTML_IM: "http://jabber.org/protocol/xhtml-im", + XHTML: "http://www.w3.org/1999/xhtml" + }, + /** Constants: XHTML_IM Namespace * contains allowed tags, tag attributes, and css properties. * Used in the createHtml function to filter incoming html into the allowed XHTML-IM subset. * See http://xmpp.org/extensions/xep-0071.html#profile-summary for the list of recommended * allowed tags and their attributes. */ - XHTML: { - tags: ['a','blockquote','br','cite','em','img','li','ol','p','span','strong','ul','body'], - attributes: { - 'a': ['href'], - 'blockquote': ['style'], - 'br': [], - 'cite': ['style'], - 'em': [], - 'img': ['src', 'alt', 'style', 'height', 'width'], - 'li': ['style'], - 'ol': ['style'], - 'p': ['style'], - 'span': ['style'], - 'strong': [], - 'ul': ['style'], - 'body': [] - }, - css: ['background-color','color','font-family','font-size','font-style','font-weight','margin-left','margin-right','text-align','text-decoration'], - validTag: function(tag) - { - for(var i = 0; i < Strophe.XHTML.tags.length; i++) { - if(tag == Strophe.XHTML.tags[i]) { - return true; - } - } - return false; - }, - validAttribute: function(tag, attribute) - { - if(typeof Strophe.XHTML.attributes[tag] !== 'undefined' && Strophe.XHTML.attributes[tag].length > 0) { - for(var i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { - if(attribute == Strophe.XHTML.attributes[tag][i]) { - return true; - } - } - } - return false; - }, - validCSS: function(style) - { - for(var i = 0; i < Strophe.XHTML.css.length; i++) { - if(style == Strophe.XHTML.css[i]) { - return true; - } + XHTML: { + tags: [ "a", "blockquote", "br", "cite", "em", "img", "li", "ol", "p", "span", "strong", "ul", "body" ], + attributes: { + a: [ "href" ], + blockquote: [ "style" ], + br: [], + cite: [ "style" ], + em: [], + img: [ "src", "alt", "style", "height", "width" ], + li: [ "style" ], + ol: [ "style" ], + p: [ "style" ], + span: [ "style" ], + strong: [], + ul: [ "style" ], + body: [] + }, + css: [ "background-color", "color", "font-family", "font-size", "font-style", "font-weight", "margin-left", "margin-right", "text-align", "text-decoration" ], + validTag: function(tag) { + for (var i = 0; i < Strophe.XHTML.tags.length; i++) { + if (tag == Strophe.XHTML.tags[i]) { + return true; + } + } + return false; + }, + validAttribute: function(tag, attribute) { + if (typeof Strophe.XHTML.attributes[tag] !== "undefined" && Strophe.XHTML.attributes[tag].length > 0) { + for (var i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { + if (attribute == Strophe.XHTML.attributes[tag][i]) { + return true; } - return false; + } } - }, - - /** Constants: Connection Status Constants + return false; + }, + validCSS: function(style) { + for (var i = 0; i < Strophe.XHTML.css.length; i++) { + if (style == Strophe.XHTML.css[i]) { + return true; + } + } + return false; + } + }, + /** Constants: Connection Status Constants * Connection status constants for use by the connection handler * callback. * @@ -836,19 +780,18 @@ Strophe = { * Status.DISCONNECTING - The connection is currently being terminated * Status.ATTACHED - The connection has been attached */ - Status: { - ERROR: 0, - CONNECTING: 1, - CONNFAIL: 2, - AUTHENTICATING: 3, - AUTHFAIL: 4, - CONNECTED: 5, - DISCONNECTED: 6, - DISCONNECTING: 7, - ATTACHED: 8 - }, - - /** Constants: Log Level Constants + Status: { + ERROR: 0, + CONNECTING: 1, + CONNFAIL: 2, + AUTHENTICATING: 3, + AUTHFAIL: 4, + CONNECTED: 5, + DISCONNECTED: 6, + DISCONNECTING: 7, + ATTACHED: 8 + }, + /** Constants: Log Level Constants * Logging level indicators. * * LogLevel.DEBUG - Debug output @@ -857,29 +800,27 @@ Strophe = { * LogLevel.ERROR - Errors * LogLevel.FATAL - Fatal errors */ - LogLevel: { - DEBUG: 0, - INFO: 1, - WARN: 2, - ERROR: 3, - FATAL: 4 - }, - - /** PrivateConstants: DOM Element Type Constants + LogLevel: { + DEBUG: 0, + INFO: 1, + WARN: 2, + ERROR: 3, + FATAL: 4 + }, + /** PrivateConstants: DOM Element Type Constants * DOM element types. * * ElementType.NORMAL - Normal element. * ElementType.TEXT - Text data element. * ElementType.FRAGMENT - XHTML fragment element. */ - ElementType: { - NORMAL: 1, - TEXT: 3, - CDATA: 4, - FRAGMENT: 11 - }, - - /** PrivateConstants: Timeout Values + ElementType: { + NORMAL: 1, + TEXT: 3, + CDATA: 4, + FRAGMENT: 11 + }, + /** PrivateConstants: Timeout Values * Timeout values for error states. These values are in seconds. * These should not be changed unless you know exactly what you are * doing. @@ -893,10 +834,9 @@ Strophe = { * Math.floor(SECONDARY_TIMEOUT * wait) seconds have elapsed. * This defaults to 0.1, and with default wait, 6 seconds. */ - TIMEOUT: 1.1, - SECONDARY_TIMEOUT: 0.1, - - /** Function: addNamespace + TIMEOUT: 1.1, + SECONDARY_TIMEOUT: .1, + /** Function: addNamespace * This function is used to extend the current namespaces in * Strophe.NS. It takes a key and a value with the key being the * name of the new namespace, with its actual value. @@ -908,12 +848,10 @@ Strophe = { * referenced under Strophe.NS * (String) value - The actual namespace. */ - addNamespace: function (name, value) - { - Strophe.NS[name] = value; - }, - - /** Function: forEachChild + addNamespace: function(name, value) { + Strophe.NS[name] = value; + }, + /** Function: forEachChild * Map a function over some or all child elements of a given element. * * This is a small convenience function for mapping a function over @@ -927,20 +865,16 @@ Strophe = { * (Function) func - The function to apply to each child. This * function should take a single argument, a DOM element. */ - forEachChild: function (elem, elemName, func) - { - var i, childNode; - - for (i = 0; i < elem.childNodes.length; i++) { - childNode = elem.childNodes[i]; - if (childNode.nodeType == Strophe.ElementType.NORMAL && - (!elemName || this.isTagEqual(childNode, elemName))) { - func(childNode); + forEachChild: function(elem, elemName, func) { + var i, childNode; + for (i = 0; i < elem.childNodes.length; i++) { + childNode = elem.childNodes[i]; + if (childNode.nodeType == Strophe.ElementType.NORMAL && (!elemName || this.isTagEqual(childNode, elemName))) { + func(childNode); + } } - } - }, - - /** Function: isTagEqual + }, + /** Function: isTagEqual * Compare an element's tag name with a string. * * This function is case insensitive. @@ -953,53 +887,44 @@ Strophe = { * true if the element's tag name matches _el_, and false * otherwise. */ - isTagEqual: function (el, name) - { - return el.tagName.toLowerCase() == name.toLowerCase(); - }, - - /** PrivateVariable: _xmlGenerator + isTagEqual: function(el, name) { + return el.tagName.toLowerCase() == name.toLowerCase(); + }, + /** PrivateVariable: _xmlGenerator * _Private_ variable that caches a DOM document to * generate elements. */ - _xmlGenerator: null, - - /** PrivateFunction: _makeGenerator + _xmlGenerator: null, + /** PrivateFunction: _makeGenerator * _Private_ function that creates a dummy XML DOM document to serve as * an element and text node generator. */ - _makeGenerator: function () { - var doc; - - // IE9 does implement createDocument(); however, using it will cause the browser to leak memory on page unload. - // Here, we test for presence of createDocument() plus IE's proprietary documentMode attribute, which would be - // less than 10 in the case of IE9 and below. - if (document.implementation.createDocument === undefined || - document.implementation.createDocument && document.documentMode && document.documentMode < 10) { - doc = this._getIEXmlDom(); - doc.appendChild(doc.createElement('strophe')); - } else { - doc = document.implementation - .createDocument('jabber:client', 'strophe', null); - } - - return doc; - }, - - /** Function: xmlGenerator + _makeGenerator: function() { + var doc; + // IE9 does implement createDocument(); however, using it will cause the browser to leak memory on page unload. + // Here, we test for presence of createDocument() plus IE's proprietary documentMode attribute, which would be + // less than 10 in the case of IE9 and below. + if (document.implementation.createDocument === undefined || document.implementation.createDocument && document.documentMode && document.documentMode < 10) { + doc = this._getIEXmlDom(); + doc.appendChild(doc.createElement("strophe")); + } else { + doc = document.implementation.createDocument("jabber:client", "strophe", null); + } + return doc; + }, + /** Function: xmlGenerator * Get the DOM document to generate elements. * * Returns: * The currently used DOM document. */ - xmlGenerator: function () { - if (!Strophe._xmlGenerator) { - Strophe._xmlGenerator = Strophe._makeGenerator(); - } - return Strophe._xmlGenerator; - }, - - /** PrivateFunction: _getIEXmlDom + xmlGenerator: function() { + if (!Strophe._xmlGenerator) { + Strophe._xmlGenerator = Strophe._makeGenerator(); + } + return Strophe._xmlGenerator; + }, + /** PrivateFunction: _getIEXmlDom * Gets IE xml doc object * * Returns: @@ -1007,34 +932,23 @@ Strophe = { * See Also: * http://msdn.microsoft.com/en-us/library/ms757837%28VS.85%29.aspx */ - _getIEXmlDom : function() { - var doc = null; - var docStrings = [ - "Msxml2.DOMDocument.6.0", - "Msxml2.DOMDocument.5.0", - "Msxml2.DOMDocument.4.0", - "MSXML2.DOMDocument.3.0", - "MSXML2.DOMDocument", - "MSXML.DOMDocument", - "Microsoft.XMLDOM" - ]; - - for (var d = 0; d < docStrings.length; d++) { - if (doc === null) { - try { - doc = new ActiveXObject(docStrings[d]); - } catch (e) { - doc = null; + _getIEXmlDom: function() { + var doc = null; + var docStrings = [ "Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM" ]; + for (var d = 0; d < docStrings.length; d++) { + if (doc === null) { + try { + doc = new ActiveXObject(docStrings[d]); + } catch (e) { + doc = null; + } + } else { + break; } - } else { - break; } - } - - return doc; - }, - - /** Function: xmlElement + return doc; + }, + /** Function: xmlElement * Create an XML DOM element. * * This function creates an XML DOM element correctly across all @@ -1052,42 +966,37 @@ Strophe = { * Returns: * A new XML DOM element. */ - xmlElement: function (name) - { - if (!name) { return null; } - - var node = Strophe.xmlGenerator().createElement(name); - - // FIXME: this should throw errors if args are the wrong type or - // there are more than two optional args - var a, i, k; - for (a = 1; a < arguments.length; a++) { - if (!arguments[a]) { continue; } - if (typeof(arguments[a]) == "string" || - typeof(arguments[a]) == "number") { - node.appendChild(Strophe.xmlTextNode(arguments[a])); - } else if (typeof(arguments[a]) == "object" && - typeof(arguments[a].sort) == "function") { - for (i = 0; i < arguments[a].length; i++) { - if (typeof(arguments[a][i]) == "object" && - typeof(arguments[a][i].sort) == "function") { - node.setAttribute(arguments[a][i][0], - arguments[a][i][1]); - } + xmlElement: function(name) { + if (!name) { + return null; + } + var node = Strophe.xmlGenerator().createElement(name); + // FIXME: this should throw errors if args are the wrong type or + // there are more than two optional args + var a, i, k; + for (a = 1; a < arguments.length; a++) { + if (!arguments[a]) { + continue; } - } else if (typeof(arguments[a]) == "object") { - for (k in arguments[a]) { - if (arguments[a].hasOwnProperty(k)) { - node.setAttribute(k, arguments[a][k]); + if (typeof arguments[a] == "string" || typeof arguments[a] == "number") { + node.appendChild(Strophe.xmlTextNode(arguments[a])); + } else if (typeof arguments[a] == "object" && typeof arguments[a].sort == "function") { + for (i = 0; i < arguments[a].length; i++) { + if (typeof arguments[a][i] == "object" && typeof arguments[a][i].sort == "function") { + node.setAttribute(arguments[a][i][0], arguments[a][i][1]); + } + } + } else if (typeof arguments[a] == "object") { + for (k in arguments[a]) { + if (arguments[a].hasOwnProperty(k)) { + node.setAttribute(k, arguments[a][k]); + } } } } - } - - return node; - }, - - /* Function: xmlescape + return node; + }, + /* Function: xmlescape * Excapes invalid xml characters. * * Parameters: @@ -1096,17 +1005,15 @@ Strophe = { * Returns: * Escaped text. */ - xmlescape: function(text) - { - text = text.replace(/\&/g, "&"); - text = text.replace(//g, ">"); - text = text.replace(/'/g, "'"); - text = text.replace(/"/g, """); - return text; - }, - - /** Function: xmlTextNode + xmlescape: function(text) { + text = text.replace(/\&/g, "&"); + text = text.replace(//g, ">"); + text = text.replace(/'/g, "'"); + text = text.replace(/"/g, """); + return text; + }, + /** Function: xmlTextNode * Creates an XML DOM text node. * * Provides a cross implementation version of document.createTextNode. @@ -1117,12 +1024,10 @@ Strophe = { * Returns: * A new XML DOM text node. */ - xmlTextNode: function (text) - { - return Strophe.xmlGenerator().createTextNode(text); - }, - - /** Function: xmlHtmlNode + xmlTextNode: function(text) { + return Strophe.xmlGenerator().createTextNode(text); + }, + /** Function: xmlHtmlNode * Creates an XML DOM html node. * * Parameters: @@ -1131,21 +1036,19 @@ Strophe = { * Returns: * A new XML DOM text node. */ - xmlHtmlNode: function (html) - { - //ensure text is escaped - if (window.DOMParser) { - parser = new DOMParser(); - node = parser.parseFromString(html, "text/xml"); - } else { - node = new ActiveXObject("Microsoft.XMLDOM"); - node.async="false"; - node.loadXML(html); - } - return node; - }, - - /** Function: getText + xmlHtmlNode: function(html) { + //ensure text is escaped + if (window.DOMParser) { + parser = new DOMParser(); + node = parser.parseFromString(html, "text/xml"); + } else { + node = new ActiveXObject("Microsoft.XMLDOM"); + node.async = "false"; + node.loadXML(html); + } + return node; + }, + /** Function: getText * Get the concatenation of all text children of an element. * * Parameters: @@ -1154,26 +1057,22 @@ Strophe = { * Returns: * A String with the concatenated text of all text element children. */ - getText: function (elem) - { - if (!elem) { return null; } - - var str = ""; - if (elem.childNodes.length === 0 && elem.nodeType == - Strophe.ElementType.TEXT) { - str += elem.nodeValue; - } - - for (var i = 0; i < elem.childNodes.length; i++) { - if (elem.childNodes[i].nodeType == Strophe.ElementType.TEXT) { - str += elem.childNodes[i].nodeValue; + getText: function(elem) { + if (!elem) { + return null; } - } - - return Strophe.xmlescape(str); - }, - - /** Function: copyElement + var str = ""; + if (elem.childNodes.length === 0 && elem.nodeType == Strophe.ElementType.TEXT) { + str += elem.nodeValue; + } + for (var i = 0; i < elem.childNodes.length; i++) { + if (elem.childNodes[i].nodeType == Strophe.ElementType.TEXT) { + str += elem.childNodes[i].nodeValue; + } + } + return Strophe.xmlescape(str); + }, + /** Function: copyElement * Copy an XML DOM element. * * This function copies a DOM element and all its descendants and returns @@ -1185,29 +1084,22 @@ Strophe = { * Returns: * A new, copied DOM element tree. */ - copyElement: function (elem) - { - var i, el; - if (elem.nodeType == Strophe.ElementType.NORMAL) { - el = Strophe.xmlElement(elem.tagName); - - for (i = 0; i < elem.attributes.length; i++) { - el.setAttribute(elem.attributes[i].nodeName.toLowerCase(), - elem.attributes[i].value); - } - - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.copyElement(elem.childNodes[i])); + copyElement: function(elem) { + var i, el; + if (elem.nodeType == Strophe.ElementType.NORMAL) { + el = Strophe.xmlElement(elem.tagName); + for (i = 0; i < elem.attributes.length; i++) { + el.setAttribute(elem.attributes[i].nodeName.toLowerCase(), elem.attributes[i].value); + } + for (i = 0; i < elem.childNodes.length; i++) { + el.appendChild(Strophe.copyElement(elem.childNodes[i])); + } + } else if (elem.nodeType == Strophe.ElementType.TEXT) { + el = Strophe.xmlGenerator().createTextNode(elem.nodeValue); } - } else if (elem.nodeType == Strophe.ElementType.TEXT) { - el = Strophe.xmlGenerator().createTextNode(elem.nodeValue); - } - - return el; - }, - - - /** Function: createHtml + return el; + }, + /** Function: createHtml * Copy an HTML DOM element into an XML DOM. * * This function copies a DOM element and all its descendants and returns @@ -1219,71 +1111,68 @@ Strophe = { * Returns: * A new, copied DOM element tree. */ - createHtml: function (elem) - { - var i, el, j, tag, attribute, value, css, cssAttrs, attr, cssName, cssValue, children, child; - if (elem.nodeType == Strophe.ElementType.NORMAL) { - tag = elem.nodeName.toLowerCase(); - if(Strophe.XHTML.validTag(tag)) { - try { - el = Strophe.xmlElement(tag); - for(i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { - attribute = Strophe.XHTML.attributes[tag][i]; - value = elem.getAttribute(attribute); - if(typeof value == 'undefined' || value === null || value === '' || value === false || value === 0) { - continue; - } - if(attribute == 'style' && typeof value == 'object') { - if(typeof value.cssText != 'undefined') { - value = value.cssText; // we're dealing with IE, need to get CSS out + createHtml: function(elem) { + var i, el, j, tag, attribute, value, css, cssAttrs, attr, cssName, cssValue, children, child; + if (elem.nodeType == Strophe.ElementType.NORMAL) { + tag = elem.nodeName.toLowerCase(); + if (Strophe.XHTML.validTag(tag)) { + try { + el = Strophe.xmlElement(tag); + for (i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { + attribute = Strophe.XHTML.attributes[tag][i]; + value = elem.getAttribute(attribute); + if (typeof value == "undefined" || value === null || value === "" || value === false || value === 0) { + continue; } - } - // filter out invalid css styles - if(attribute == 'style') { - css = []; - cssAttrs = value.split(';'); - for(j = 0; j < cssAttrs.length; j++) { - attr = cssAttrs[j].split(':'); - cssName = attr[0].replace(/^\s*/, "").replace(/\s*$/, "").toLowerCase(); - if(Strophe.XHTML.validCSS(cssName)) { - cssValue = attr[1].replace(/^\s*/, "").replace(/\s*$/, ""); - css.push(cssName + ': ' + cssValue); + if (attribute == "style" && typeof value == "object") { + if (typeof value.cssText != "undefined") { + value = value.cssText; } } - if(css.length > 0) { - value = css.join('; '); + // filter out invalid css styles + if (attribute == "style") { + css = []; + cssAttrs = value.split(";"); + for (j = 0; j < cssAttrs.length; j++) { + attr = cssAttrs[j].split(":"); + cssName = attr[0].replace(/^\s*/, "").replace(/\s*$/, "").toLowerCase(); + if (Strophe.XHTML.validCSS(cssName)) { + cssValue = attr[1].replace(/^\s*/, "").replace(/\s*$/, ""); + css.push(cssName + ": " + cssValue); + } + } + if (css.length > 0) { + value = css.join("; "); + el.setAttribute(attribute, value); + } + } else { el.setAttribute(attribute, value); } - } else { - el.setAttribute(attribute, value); } + for (i = 0; i < elem.childNodes.length; i++) { + el.appendChild(Strophe.createHtml(elem.childNodes[i])); + } + } catch (e) { + // invalid elements + el = Strophe.xmlTextNode(""); } - + } else { + el = Strophe.xmlGenerator().createDocumentFragment(); for (i = 0; i < elem.childNodes.length; i++) { el.appendChild(Strophe.createHtml(elem.childNodes[i])); } - } catch(e) { // invalid elements - el = Strophe.xmlTextNode(''); } - } else { + } else if (elem.nodeType == Strophe.ElementType.FRAGMENT) { el = Strophe.xmlGenerator().createDocumentFragment(); for (i = 0; i < elem.childNodes.length; i++) { el.appendChild(Strophe.createHtml(elem.childNodes[i])); } + } else if (elem.nodeType == Strophe.ElementType.TEXT) { + el = Strophe.xmlTextNode(elem.nodeValue); } - } else if (elem.nodeType == Strophe.ElementType.FRAGMENT) { - el = Strophe.xmlGenerator().createDocumentFragment(); - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(Strophe.createHtml(elem.childNodes[i])); - } - } else if (elem.nodeType == Strophe.ElementType.TEXT) { - el = Strophe.xmlTextNode(elem.nodeValue); - } - - return el; - }, - - /** Function: escapeNode + return el; + }, + /** Function: escapeNode * Escape the node part (also called local part) of a JID. * * Parameters: @@ -1292,22 +1181,10 @@ Strophe = { * Returns: * An escaped node (or local part). */ - escapeNode: function (node) - { - return node.replace(/^\s+|\s+$/g, '') - .replace(/\\/g, "\\5c") - .replace(/ /g, "\\20") - .replace(/\"/g, "\\22") - .replace(/\&/g, "\\26") - .replace(/\'/g, "\\27") - .replace(/\//g, "\\2f") - .replace(/:/g, "\\3a") - .replace(//g, "\\3e") - .replace(/@/g, "\\40"); - }, - - /** Function: unescapeNode + escapeNode: function(node) { + return node.replace(/^\s+|\s+$/g, "").replace(/\\/g, "\\5c").replace(/ /g, "\\20").replace(/\"/g, "\\22").replace(/\&/g, "\\26").replace(/\'/g, "\\27").replace(/\//g, "\\2f").replace(/:/g, "\\3a").replace(//g, "\\3e").replace(/@/g, "\\40"); + }, + /** Function: unescapeNode * Unescape a node part (also called local part) of a JID. * * Parameters: @@ -1316,21 +1193,10 @@ Strophe = { * Returns: * An unescaped node (or local part). */ - unescapeNode: function (node) - { - return node.replace(/\\20/g, " ") - .replace(/\\22/g, '"') - .replace(/\\26/g, "&") - .replace(/\\27/g, "'") - .replace(/\\2f/g, "/") - .replace(/\\3a/g, ":") - .replace(/\\3c/g, "<") - .replace(/\\3e/g, ">") - .replace(/\\40/g, "@") - .replace(/\\5c/g, "\\"); - }, - - /** Function: getNodeFromJid + unescapeNode: function(node) { + return node.replace(/\\20/g, " ").replace(/\\22/g, '"').replace(/\\26/g, "&").replace(/\\27/g, "'").replace(/\\2f/g, "/").replace(/\\3a/g, ":").replace(/\\3c/g, "<").replace(/\\3e/g, ">").replace(/\\40/g, "@").replace(/\\5c/g, "\\"); + }, + /** Function: getNodeFromJid * Get the node portion of a JID String. * * Parameters: @@ -1339,13 +1205,13 @@ Strophe = { * Returns: * A String containing the node. */ - getNodeFromJid: function (jid) - { - if (jid.indexOf("@") < 0) { return null; } - return jid.split("@")[0]; - }, - - /** Function: getDomainFromJid + getNodeFromJid: function(jid) { + if (jid.indexOf("@") < 0) { + return null; + } + return jid.split("@")[0]; + }, + /** Function: getDomainFromJid * Get the domain portion of a JID String. * * Parameters: @@ -1354,19 +1220,17 @@ Strophe = { * Returns: * A String containing the domain. */ - getDomainFromJid: function (jid) - { - var bare = Strophe.getBareJidFromJid(jid); - if (bare.indexOf("@") < 0) { - return bare; - } else { - var parts = bare.split("@"); - parts.splice(0, 1); - return parts.join('@'); - } - }, - - /** Function: getResourceFromJid + getDomainFromJid: function(jid) { + var bare = Strophe.getBareJidFromJid(jid); + if (bare.indexOf("@") < 0) { + return bare; + } else { + var parts = bare.split("@"); + parts.splice(0, 1); + return parts.join("@"); + } + }, + /** Function: getResourceFromJid * Get the resource portion of a JID String. * * Parameters: @@ -1375,15 +1239,15 @@ Strophe = { * Returns: * A String containing the resource. */ - getResourceFromJid: function (jid) - { - var s = jid.split("/"); - if (s.length < 2) { return null; } - s.splice(0, 1); - return s.join('/'); - }, - - /** Function: getBareJidFromJid + getResourceFromJid: function(jid) { + var s = jid.split("/"); + if (s.length < 2) { + return null; + } + s.splice(0, 1); + return s.join("/"); + }, + /** Function: getBareJidFromJid * Get the bare JID from a JID String. * * Parameters: @@ -1392,12 +1256,10 @@ Strophe = { * Returns: * A String containing the bare JID. */ - getBareJidFromJid: function (jid) - { - return jid ? jid.split("/")[0] : null; - }, - - /** Function: log + getBareJidFromJid: function(jid) { + return jid ? jid.split("/")[0] : null; + }, + /** Function: log * User overrideable logging function. * * This function is called whenever the Strophe library calls any @@ -1426,67 +1288,55 @@ Strophe = { * be one of the values in Strophe.LogLevel. * (String) msg - The log message. */ - log: function (level, msg) - { - return; - }, - - /** Function: debug + log: function(level, msg) { + return; + }, + /** Function: debug * Log a message at the Strophe.LogLevel.DEBUG level. * * Parameters: * (String) msg - The log message. */ - debug: function(msg) - { - this.log(this.LogLevel.DEBUG, msg); - }, - - /** Function: info + debug: function(msg) { + this.log(this.LogLevel.DEBUG, msg); + }, + /** Function: info * Log a message at the Strophe.LogLevel.INFO level. * * Parameters: * (String) msg - The log message. */ - info: function (msg) - { - this.log(this.LogLevel.INFO, msg); - }, - - /** Function: warn + info: function(msg) { + this.log(this.LogLevel.INFO, msg); + }, + /** Function: warn * Log a message at the Strophe.LogLevel.WARN level. * * Parameters: * (String) msg - The log message. */ - warn: function (msg) - { - this.log(this.LogLevel.WARN, msg); - }, - - /** Function: error + warn: function(msg) { + this.log(this.LogLevel.WARN, msg); + }, + /** Function: error * Log a message at the Strophe.LogLevel.ERROR level. * * Parameters: * (String) msg - The log message. */ - error: function (msg) - { - this.log(this.LogLevel.ERROR, msg); - }, - - /** Function: fatal + error: function(msg) { + this.log(this.LogLevel.ERROR, msg); + }, + /** Function: fatal * Log a message at the Strophe.LogLevel.FATAL level. * * Parameters: * (String) msg - The log message. */ - fatal: function (msg) - { - this.log(this.LogLevel.FATAL, msg); - }, - - /** Function: serialize + fatal: function(msg) { + this.log(this.LogLevel.FATAL, msg); + }, + /** Function: serialize * Render a DOM element and all descendants to a String. * * Parameters: @@ -1495,87 +1345,73 @@ Strophe = { * Returns: * The serialized element tree as a String. */ - serialize: function (elem) - { - var result; - - if (!elem) { return null; } - - if (typeof(elem.tree) === "function") { - elem = elem.tree(); - } - - var nodeName = elem.nodeName; - var i, child; - - if (elem.getAttribute("_realname")) { - nodeName = elem.getAttribute("_realname"); - } - - result = "<" + nodeName; - for (i = 0; i < elem.attributes.length; i++) { - if(elem.attributes[i].nodeName != "_realname") { - result += " " + elem.attributes[i].nodeName.toLowerCase() + - "='" + elem.attributes[i].value - .replace(/&/g, "&") - .replace(/\'/g, "'") - .replace(/>/g, ">") - .replace(/ 0) { - result += ">"; - for (i = 0; i < elem.childNodes.length; i++) { - child = elem.childNodes[i]; - switch( child.nodeType ){ - case Strophe.ElementType.NORMAL: - // normal element, so recurse - result += Strophe.serialize(child); - break; - case Strophe.ElementType.TEXT: - // text element to escape values - result += Strophe.xmlescape(child.nodeValue); - break; - case Strophe.ElementType.CDATA: - // cdata section so don't escape values - result += ""; + serialize: function(elem) { + var result; + if (!elem) { + return null; + } + if (typeof elem.tree === "function") { + elem = elem.tree(); + } + var nodeName = elem.nodeName; + var i, child; + if (elem.getAttribute("_realname")) { + nodeName = elem.getAttribute("_realname"); + } + result = "<" + nodeName; + for (i = 0; i < elem.attributes.length; i++) { + if (elem.attributes[i].nodeName != "_realname") { + result += " " + elem.attributes[i].nodeName.toLowerCase() + "='" + elem.attributes[i].value.replace(/&/g, "&").replace(/\'/g, "'").replace(/>/g, ">").replace(/"; - } else { - result += "/>"; - } - - return result; - }, - - /** PrivateVariable: _requestId + if (elem.childNodes.length > 0) { + result += ">"; + for (i = 0; i < elem.childNodes.length; i++) { + child = elem.childNodes[i]; + switch (child.nodeType) { + case Strophe.ElementType.NORMAL: + // normal element, so recurse + result += Strophe.serialize(child); + break; + + case Strophe.ElementType.TEXT: + // text element to escape values + result += Strophe.xmlescape(child.nodeValue); + break; + + case Strophe.ElementType.CDATA: + // cdata section so don't escape values + result += ""; + } + } + result += ""; + } else { + result += "/>"; + } + return result; + }, + /** PrivateVariable: _requestId * _Private_ variable that keeps track of the request ids for * connections. */ - _requestId: 0, - - /** PrivateVariable: Strophe.connectionPlugins + _requestId: 0, + /** PrivateVariable: Strophe.connectionPlugins * _Private_ variable Used to store plugin names that need * initialization on Strophe.Connection construction. */ - _connectionPlugins: {}, - - /** Function: addConnectionPlugin + _connectionPlugins: {}, + /** Function: addConnectionPlugin * Extends the Strophe.Connection object with the given plugin. * * Parameters: * (String) name - The name of the extension. * (Object) ptype - The plugin's prototype. */ - addConnectionPlugin: function (name, ptype) - { - Strophe._connectionPlugins[name] = ptype; - } -}; - -/** Class: Strophe.Builder + addConnectionPlugin: function(name, ptype) { + Strophe._connectionPlugins[name] = ptype; + } + }; + /** Class: Strophe.Builder * XML DOM builder. * * This object provides an interface similar to JQuery but for building @@ -1600,8 +1436,7 @@ Strophe = { * > builder.c('child1', ...).up().c('child2', ...) * The next operation on the Builder will be relative to the second child. */ - -/** Constructor: Strophe.Builder + /** Constructor: Strophe.Builder * Create a Strophe.Builder object. * * The attributes should be passed in object notation. For example @@ -1616,26 +1451,24 @@ Strophe = { * Returns: * A new Strophe.Builder. */ -Strophe.Builder = function (name, attrs) -{ - // Set correct namespace for jabber:client elements - if (name == "presence" || name == "message" || name == "iq") { - if (attrs && !attrs.xmlns) { - attrs.xmlns = Strophe.NS.CLIENT; - } else if (!attrs) { - attrs = {xmlns: Strophe.NS.CLIENT}; + Strophe.Builder = function(name, attrs) { + // Set correct namespace for jabber:client elements + if (name == "presence" || name == "message" || name == "iq") { + if (attrs && !attrs.xmlns) { + attrs.xmlns = Strophe.NS.CLIENT; + } else if (!attrs) { + attrs = { + xmlns: Strophe.NS.CLIENT + }; + } } - } - - // Holds the tree being built. - this.nodeTree = Strophe.xmlElement(name, attrs); - - // Points to the current operation node. - this.node = this.nodeTree; -}; - -Strophe.Builder.prototype = { - /** Function: tree + // Holds the tree being built. + this.nodeTree = Strophe.xmlElement(name, attrs); + // Points to the current operation node. + this.node = this.nodeTree; + }; + Strophe.Builder.prototype = { + /** Function: tree * Return the DOM tree. * * This function returns the current DOM tree as an element object. This @@ -1644,12 +1477,10 @@ Strophe.Builder.prototype = { * Returns: * The DOM tree as a element object. */ - tree: function () - { - return this.nodeTree; - }, - - /** Function: toString + tree: function() { + return this.nodeTree; + }, + /** Function: toString * Serialize the DOM tree to a String. * * This function returns a string serialization of the current DOM @@ -1659,12 +1490,10 @@ Strophe.Builder.prototype = { * Returns: * The serialized DOM tree in a String. */ - toString: function () - { - return Strophe.serialize(this.nodeTree); - }, - - /** Function: up + toString: function() { + return Strophe.serialize(this.nodeTree); + }, + /** Function: up * Make the current parent element the new current element. * * This function is often used after c() to traverse back up the tree. @@ -1674,13 +1503,11 @@ Strophe.Builder.prototype = { * Returns: * The Stophe.Builder object. */ - up: function () - { - this.node = this.node.parentNode; - return this; - }, - - /** Function: attrs + up: function() { + this.node = this.node.parentNode; + return this; + }, + /** Function: attrs * Add or modify attributes of the current element. * * The attributes should be passed in object notation. This function @@ -1692,17 +1519,15 @@ Strophe.Builder.prototype = { * Returns: * The Strophe.Builder object. */ - attrs: function (moreattrs) - { - for (var k in moreattrs) { - if (moreattrs.hasOwnProperty(k)) { - this.node.setAttribute(k, moreattrs[k]); + attrs: function(moreattrs) { + for (var k in moreattrs) { + if (moreattrs.hasOwnProperty(k)) { + this.node.setAttribute(k, moreattrs[k]); + } } - } - return this; - }, - - /** Function: c + return this; + }, + /** Function: c * Add a child to the current element and make it the new current * element. * @@ -1718,17 +1543,15 @@ Strophe.Builder.prototype = { * Returns: * The Strophe.Builder object. */ - c: function (name, attrs, text) - { - var child = Strophe.xmlElement(name, attrs, text); - this.node.appendChild(child); - if (!text) { - this.node = child; - } - return this; - }, - - /** Function: cnode + c: function(name, attrs, text) { + var child = Strophe.xmlElement(name, attrs, text); + this.node.appendChild(child); + if (!text) { + this.node = child; + } + return this; + }, + /** Function: cnode * Add a child to the current element and make it the new current * element. * @@ -1742,25 +1565,20 @@ Strophe.Builder.prototype = { * Returns: * The Strophe.Builder object. */ - cnode: function (elem) - { - var impNode; - var xmlGen = Strophe.xmlGenerator(); - try { - impNode = (xmlGen.importNode !== undefined); - } - catch (e) { - impNode = false; - } - var newElem = impNode ? - xmlGen.importNode(elem, true) : - Strophe.copyElement(elem); - this.node.appendChild(newElem); - this.node = newElem; - return this; - }, - - /** Function: t + cnode: function(elem) { + var impNode; + var xmlGen = Strophe.xmlGenerator(); + try { + impNode = xmlGen.importNode !== undefined; + } catch (e) { + impNode = false; + } + var newElem = impNode ? xmlGen.importNode(elem, true) : Strophe.copyElement(elem); + this.node.appendChild(newElem); + this.node = newElem; + return this; + }, + /** Function: t * Add a child text element. * * This *does not* make the child the new current element since there @@ -1772,14 +1590,12 @@ Strophe.Builder.prototype = { * Returns: * The Strophe.Builder object. */ - t: function (text) - { - var child = Strophe.xmlTextNode(text); - this.node.appendChild(child); - return this; - }, - - /** Function: h + t: function(text) { + var child = Strophe.xmlTextNode(text); + this.node.appendChild(child); + return this; + }, + /** Function: h * Replace current element contents with the HTML passed in. * * This *does not* make the child the new current element @@ -1790,24 +1606,19 @@ Strophe.Builder.prototype = { * Returns: * The Strophe.Builder object. */ - h: function (html) - { - var fragment = document.createElement('body'); - - // force the browser to try and fix any invalid HTML tags - fragment.innerHTML = html; - - // copy cleaned html into an xml dom - var xhtml = Strophe.createHtml(fragment); - - while(xhtml.childNodes.length > 0) { - this.node.appendChild(xhtml.childNodes[0]); + h: function(html) { + var fragment = document.createElement("body"); + // force the browser to try and fix any invalid HTML tags + fragment.innerHTML = html; + // copy cleaned html into an xml dom + var xhtml = Strophe.createHtml(fragment); + while (xhtml.childNodes.length > 0) { + this.node.appendChild(xhtml.childNodes[0]); + } + return this; } - return this; - } -}; - -/** PrivateClass: Strophe.Handler + }; + /** PrivateClass: Strophe.Handler * _Private_ helper class for managing stanza handlers. * * A Strophe.Handler encapsulates a user provided callback function to be @@ -1820,8 +1631,7 @@ Strophe.Builder.prototype = { * will use Strophe.Connection.addHandler() and * Strophe.Connection.deleteHandler(). */ - -/** PrivateConstructor: Strophe.Handler + /** PrivateConstructor: Strophe.Handler * Create and initialize a new Strophe.Handler. * * Parameters: @@ -1836,32 +1646,29 @@ Strophe.Builder.prototype = { * Returns: * A new Strophe.Handler object. */ -Strophe.Handler = function (handler, ns, name, type, id, from, options) -{ - this.handler = handler; - this.ns = ns; - this.name = name; - this.type = type; - this.id = id; - this.options = options || {matchBare: false}; - - // default matchBare to false if undefined - if (!this.options.matchBare) { - this.options.matchBare = false; - } - - if (this.options.matchBare) { - this.from = from ? Strophe.getBareJidFromJid(from) : null; - } else { - this.from = from; - } - - // whether the handler is a user handler or a system handler - this.user = true; -}; - -Strophe.Handler.prototype = { - /** PrivateFunction: isMatch + Strophe.Handler = function(handler, ns, name, type, id, from, options) { + this.handler = handler; + this.ns = ns; + this.name = name; + this.type = type; + this.id = id; + this.options = options || { + matchBare: false + }; + // default matchBare to false if undefined + if (!this.options.matchBare) { + this.options.matchBare = false; + } + if (this.options.matchBare) { + this.from = from ? Strophe.getBareJidFromJid(from) : null; + } else { + this.from = from; + } + // whether the handler is a user handler or a system handler + this.user = true; + }; + Strophe.Handler.prototype = { + /** PrivateFunction: isMatch * Tests if a stanza matches the Strophe.Handler. * * Parameters: @@ -1870,43 +1677,32 @@ Strophe.Handler.prototype = { * Returns: * true if the stanza matches and false otherwise. */ - isMatch: function (elem) - { - var nsMatch; - var from = null; - - if (this.options.matchBare) { - from = Strophe.getBareJidFromJid(elem.getAttribute('from')); - } else { - from = elem.getAttribute('from'); - } - - nsMatch = false; - if (!this.ns) { - nsMatch = true; - } else { - var that = this; - Strophe.forEachChild(elem, null, function (elem) { - if (elem.getAttribute("xmlns") == that.ns) { - nsMatch = true; - } - }); - - nsMatch = nsMatch || elem.getAttribute("xmlns") == this.ns; - } - - if (nsMatch && - (!this.name || Strophe.isTagEqual(elem, this.name)) && - (!this.type || elem.getAttribute("type") == this.type) && - (!this.id || elem.getAttribute("id") == this.id) && - (!this.from || from == this.from)) { + isMatch: function(elem) { + var nsMatch; + var from = null; + if (this.options.matchBare) { + from = Strophe.getBareJidFromJid(elem.getAttribute("from")); + } else { + from = elem.getAttribute("from"); + } + nsMatch = false; + if (!this.ns) { + nsMatch = true; + } else { + var that = this; + Strophe.forEachChild(elem, null, function(elem) { + if (elem.getAttribute("xmlns") == that.ns) { + nsMatch = true; + } + }); + nsMatch = nsMatch || elem.getAttribute("xmlns") == this.ns; + } + if (nsMatch && (!this.name || Strophe.isTagEqual(elem, this.name)) && (!this.type || elem.getAttribute("type") == this.type) && (!this.id || elem.getAttribute("id") == this.id) && (!this.from || from == this.from)) { return true; - } - - return false; - }, - - /** PrivateFunction: run + } + return false; + }, + /** PrivateFunction: run * Run the callback on a matching stanza. * * Parameters: @@ -1916,48 +1712,37 @@ Strophe.Handler.prototype = { * Returns: * A boolean indicating if the handler should remain active. */ - run: function (elem) - { - var result = null; - try { - result = this.handler(elem); - } catch (e) { - if (e.sourceURL) { - Strophe.fatal("error: " + this.handler + - " " + e.sourceURL + ":" + - e.line + " - " + e.name + ": " + e.message); - } else if (e.fileName) { - if (typeof(console) != "undefined") { - console.trace(); - console.error(this.handler, " - error - ", e, e.message); + run: function(elem) { + var result = null; + try { + result = this.handler(elem); + } catch (e) { + if (e.sourceURL) { + Strophe.fatal("error: " + this.handler + " " + e.sourceURL + ":" + e.line + " - " + e.name + ": " + e.message); + } else if (e.fileName) { + if (typeof console != "undefined") { + console.trace(); + console.error(this.handler, " - error - ", e, e.message); + } + Strophe.fatal("error: " + this.handler + " " + e.fileName + ":" + e.lineNumber + " - " + e.name + ": " + e.message); + } else { + Strophe.fatal("error: " + e.message + "\n" + e.stack); } - Strophe.fatal("error: " + this.handler + " " + - e.fileName + ":" + e.lineNumber + " - " + - e.name + ": " + e.message); - } else { - Strophe.fatal("error: " + e.message + "\n" + e.stack); + throw e; } - - throw e; - } - - return result; - }, - - /** PrivateFunction: toString + return result; + }, + /** PrivateFunction: toString * Get a String representation of the Strophe.Handler object. * * Returns: * A String. */ - toString: function () - { - return "{Handler: " + this.handler + "(" + this.name + "," + - this.id + "," + this.ns + ")}"; - } -}; - -/** PrivateClass: Strophe.TimedHandler + toString: function() { + return "{Handler: " + this.handler + "(" + this.name + "," + this.id + "," + this.ns + ")}"; + } + }; + /** PrivateClass: Strophe.TimedHandler * _Private_ helper class for managing timed handlers. * * A Strophe.TimedHandler encapsulates a user provided callback that @@ -1969,8 +1754,7 @@ Strophe.Handler.prototype = { * they will use Strophe.Connection.addTimedHandler() and * Strophe.Connection.deleteTimedHandler(). */ - -/** PrivateConstructor: Strophe.TimedHandler + /** PrivateConstructor: Strophe.TimedHandler * Create and initialize a new Strophe.TimedHandler object. * * Parameters: @@ -1982,50 +1766,41 @@ Strophe.Handler.prototype = { * Returns: * A new Strophe.TimedHandler object. */ -Strophe.TimedHandler = function (period, handler) -{ - this.period = period; - this.handler = handler; - - this.lastCalled = new Date().getTime(); - this.user = true; -}; - -Strophe.TimedHandler.prototype = { - /** PrivateFunction: run + Strophe.TimedHandler = function(period, handler) { + this.period = period; + this.handler = handler; + this.lastCalled = new Date().getTime(); + this.user = true; + }; + Strophe.TimedHandler.prototype = { + /** PrivateFunction: run * Run the callback for the Strophe.TimedHandler. * * Returns: * true if the Strophe.TimedHandler should be called again, and false * otherwise. */ - run: function () - { - this.lastCalled = new Date().getTime(); - return this.handler(); - }, - - /** PrivateFunction: reset + run: function() { + this.lastCalled = new Date().getTime(); + return this.handler(); + }, + /** PrivateFunction: reset * Reset the last called time for the Strophe.TimedHandler. */ - reset: function () - { - this.lastCalled = new Date().getTime(); - }, - - /** PrivateFunction: toString + reset: function() { + this.lastCalled = new Date().getTime(); + }, + /** PrivateFunction: toString * Get a string representation of the Strophe.TimedHandler object. * * Returns: * The string representation. */ - toString: function () - { - return "{TimedHandler: " + this.handler + "(" + this.period +")}"; - } -}; - -/** Class: Strophe.Connection + toString: function() { + return "{TimedHandler: " + this.handler + "(" + this.period + ")}"; + } + }; + /** Class: Strophe.Connection * XMPP Connection manager. * * This class is the main part of Strophe. It manages a BOSH connection @@ -2046,8 +1821,7 @@ Strophe.TimedHandler.prototype = { * * To send data to the connection, use send(). */ - -/** Constructor: Strophe.Connection + /** Constructor: Strophe.Connection * Create and initialize a Strophe.Connection object. * * The transport-protocol for this connection will be chosen automatically @@ -2094,96 +1868,28 @@ Strophe.TimedHandler.prototype = { * Returns: * A new Strophe.Connection object. */ -Strophe.Connection = function (service, options) -{ - // The service URL - this.service = service; - - // Configuration options - this.options = options || {}; - var proto = this.options.protocol || ""; - - // Select protocal based on service or options - if (service.indexOf("ws:") === 0 || service.indexOf("wss:") === 0 || - proto.indexOf("ws") === 0) { - this._proto = new Strophe.Websocket(this); - } else { - this._proto = new Strophe.Bosh(this); - } - /* The connected JID. */ - this.jid = ""; - /* the JIDs domain */ - this.domain = null; - /* stream:features */ - this.features = null; - - // SASL - this._sasl_data = {}; - this.do_session = false; - this.do_bind = false; - - // handler lists - this.timedHandlers = []; - this.handlers = []; - this.removeTimeds = []; - this.removeHandlers = []; - this.addTimeds = []; - this.addHandlers = []; - - this._authentication = {}; - this._idleTimeout = null; - this._disconnectTimeout = null; - - this.do_authentication = true; - this.authenticated = false; - this.disconnecting = false; - this.connected = false; - - this.errors = 0; - - this.paused = false; - - this._data = []; - this._uniqueId = 0; - - this._sasl_success_handler = null; - this._sasl_failure_handler = null; - this._sasl_challenge_handler = null; - - // Max retries before disconnecting - this.maxRetries = 5; - - // setup onIdle callback every 1/10th of a second - this._idleTimeout = setTimeout(this._onIdle.bind(this), 100); - - // initialize plugins - for (var k in Strophe._connectionPlugins) { - if (Strophe._connectionPlugins.hasOwnProperty(k)) { - var ptype = Strophe._connectionPlugins[k]; - // jslint complaints about the below line, but this is fine - var F = function () {}; - F.prototype = ptype; - this[k] = new F(); - this[k].init(this); - } - } -}; - -Strophe.Connection.prototype = { - /** Function: reset - * Reset the connection. - * - * This function should be called after a connection is disconnected - * before that connection is reused. - */ - reset: function () - { - this._proto._reset(); - + Strophe.Connection = function(service, options) { + // The service URL + this.service = service; + // Configuration options + this.options = options || {}; + var proto = this.options.protocol || ""; + // Select protocal based on service or options + if (service.indexOf("ws:") === 0 || service.indexOf("wss:") === 0 || proto.indexOf("ws") === 0) { + this._proto = new Strophe.Websocket(this); + } else { + this._proto = new Strophe.Bosh(this); + } + /* The connected JID. */ + this.jid = ""; + /* the JIDs domain */ + this.domain = null; + /* stream:features */ + this.features = null; // SASL + this._sasl_data = {}; this.do_session = false; this.do_bind = false; - // handler lists this.timedHandlers = []; this.handlers = []; @@ -2192,18 +1898,63 @@ Strophe.Connection.prototype = { this.addTimeds = []; this.addHandlers = []; this._authentication = {}; - + this._idleTimeout = null; + this._disconnectTimeout = null; + this.do_authentication = true; this.authenticated = false; this.disconnecting = false; this.connected = false; - this.errors = 0; - - this._requests = []; + this.paused = false; + this._data = []; this._uniqueId = 0; - }, - - /** Function: pause + this._sasl_success_handler = null; + this._sasl_failure_handler = null; + this._sasl_challenge_handler = null; + // Max retries before disconnecting + this.maxRetries = 5; + // setup onIdle callback every 1/10th of a second + this._idleTimeout = setTimeout(this._onIdle.bind(this), 100); + // initialize plugins + for (var k in Strophe._connectionPlugins) { + if (Strophe._connectionPlugins.hasOwnProperty(k)) { + var ptype = Strophe._connectionPlugins[k]; + // jslint complaints about the below line, but this is fine + var F = function() {}; + F.prototype = ptype; + this[k] = new F(); + this[k].init(this); + } + } + }; + Strophe.Connection.prototype = { + /** Function: reset + * Reset the connection. + * + * This function should be called after a connection is disconnected + * before that connection is reused. + */ + reset: function() { + this._proto._reset(); + // SASL + this.do_session = false; + this.do_bind = false; + // handler lists + this.timedHandlers = []; + this.handlers = []; + this.removeTimeds = []; + this.removeHandlers = []; + this.addTimeds = []; + this.addHandlers = []; + this._authentication = {}; + this.authenticated = false; + this.disconnecting = false; + this.connected = false; + this.errors = 0; + this._requests = []; + this._uniqueId = 0; + }, + /** Function: pause * Pause the request manager. * * This will prevent Strophe from sending any more requests to the @@ -2212,22 +1963,18 @@ Strophe.Connection.prototype = { * This causes Strophe to send the data in a single request, saving * many request trips. */ - pause: function () - { - this.paused = true; - }, - - /** Function: resume + pause: function() { + this.paused = true; + }, + /** Function: resume * Resume the request manager. * * This resumes after pause() has been called. */ - resume: function () - { - this.paused = false; - }, - - /** Function: getUniqueId + resume: function() { + this.paused = false; + }, + /** Function: getUniqueId * Generate a unique ID for use in elements. * * All stanzas are required to have unique id attributes. This @@ -2249,18 +1996,16 @@ Strophe.Connection.prototype = { * Returns: * A unique string to be used for the id attribute. */ - getUniqueId: function (suffix) - { - if (typeof(suffix) == "string" || typeof(suffix) == "number") { - return ++this._uniqueId + ":" + suffix; - } else { - return ++this._uniqueId + ""; - } - }, - - /** Function: connect - * Starts the connection process. - * + getUniqueId: function(suffix) { + if (typeof suffix == "string" || typeof suffix == "number") { + return ++this._uniqueId + ":" + suffix; + } else { + return ++this._uniqueId + ""; + } + }, + /** Function: connect + * Starts the connection process. + * * As the connection process proceeds, the user supplied callback will * be triggered multiple times with status updates. The callback * should take two arguments - the status code and the error condition. @@ -2287,40 +2032,35 @@ Strophe.Connection.prototype = { * should almost always be set to 1 (the default). * (String) route - The optional route value. */ - connect: function (jid, pass, callback, wait, hold, route) - { - this.jid = jid; - /** Variable: authzid + connect: function(jid, pass, callback, wait, hold, route) { + this.jid = jid; + /** Variable: authzid * Authorization identity. */ - this.authzid = Strophe.getBareJidFromJid(this.jid); - /** Variable: authcid + this.authzid = Strophe.getBareJidFromJid(this.jid); + /** Variable: authcid * Authentication identity (User name). */ - this.authcid = Strophe.getNodeFromJid(this.jid); - /** Variable: pass + this.authcid = Strophe.getNodeFromJid(this.jid); + /** Variable: pass * Authentication identity (User password). */ - this.pass = pass; - /** Variable: servtype + this.pass = pass; + /** Variable: servtype * Digest MD5 compatibility. */ - this.servtype = "xmpp"; - this.connect_callback = callback; - this.disconnecting = false; - this.connected = false; - this.authenticated = false; - this.errors = 0; - - // parse jid for domain and resource - this.domain = this.domain || Strophe.getDomainFromJid(this.jid); - - this._changeConnectStatus(Strophe.Status.CONNECTING, null); - - this._proto._connect(wait, hold, route); - }, - - /** Function: attach + this.servtype = "xmpp"; + this.connect_callback = callback; + this.disconnecting = false; + this.connected = false; + this.authenticated = false; + this.errors = 0; + // parse jid for domain and resource + this.domain = this.domain || Strophe.getDomainFromJid(this.jid); + this._changeConnectStatus(Strophe.Status.CONNECTING, null); + this._proto._connect(wait, hold, route); + }, + /** Function: attach * Attach to an already created and authenticated BOSH session. * * This function is provided to allow Strophe to attach to BOSH @@ -2344,12 +2084,10 @@ Strophe.Connection.prototype = { * (Integer) wind - The optional HTTBIND window value. This is the * allowed range of request ids that are valid. The default is 5. */ - attach: function (jid, sid, rid, callback, wait, hold, wind) - { - this._proto._attach(jid, sid, rid, callback, wait, hold, wind); - }, - - /** Function: xmlInput + attach: function(jid, sid, rid, callback, wait, hold, wind) { + this._proto._attach(jid, sid, rid, callback, wait, hold, wind); + }, + /** Function: xmlInput * User overrideable function that receives XML data coming into the * connection. * @@ -2367,12 +2105,10 @@ Strophe.Connection.prototype = { * Parameters: * (XMLElement) elem - The XML data received by the connection. */ - xmlInput: function (elem) - { - return; - }, - - /** Function: xmlOutput + xmlInput: function(elem) { + return; + }, + /** Function: xmlOutput * User overrideable function that receives XML data sent to the * connection. * @@ -2390,12 +2126,10 @@ Strophe.Connection.prototype = { * Parameters: * (XMLElement) elem - The XMLdata sent by the connection. */ - xmlOutput: function (elem) - { - return; - }, - - /** Function: rawInput + xmlOutput: function(elem) { + return; + }, + /** Function: rawInput * User overrideable function that receives raw data coming into the * connection. * @@ -2407,12 +2141,10 @@ Strophe.Connection.prototype = { * Parameters: * (String) data - The data received by the connection. */ - rawInput: function (data) - { - return; - }, - - /** Function: rawOutput + rawInput: function(data) { + return; + }, + /** Function: rawOutput * User overrideable function that receives raw data sent to the * connection. * @@ -2424,12 +2156,10 @@ Strophe.Connection.prototype = { * Parameters: * (String) data - The data sent by the connection. */ - rawOutput: function (data) - { - return; - }, - - /** Function: send + rawOutput: function(data) { + return; + }, + /** Function: send * Send a stanza. * * This function is called to push data onto the send queue to @@ -2441,23 +2171,22 @@ Strophe.Connection.prototype = { * [XMLElement] | * Strophe.Builder) elem - The stanza to send. */ - send: function (elem) - { - if (elem === null) { return ; } - if (typeof(elem.sort) === "function") { - for (var i = 0; i < elem.length; i++) { - this._queueData(elem[i]); + send: function(elem) { + if (elem === null) { + return; } - } else if (typeof(elem.tree) === "function") { - this._queueData(elem.tree()); - } else { - this._queueData(elem); - } - - this._proto._send(); - }, - - /** Function: flush + if (typeof elem.sort === "function") { + for (var i = 0; i < elem.length; i++) { + this._queueData(elem[i]); + } + } else if (typeof elem.tree === "function") { + this._queueData(elem.tree()); + } else { + this._queueData(elem); + } + this._proto._send(); + }, + /** Function: flush * Immediately send any pending outgoing data. * * Normally send() queues outgoing data until the next idle period @@ -2465,15 +2194,13 @@ Strophe.Connection.prototype = { * several send()s are called in succession. flush() can be used to * immediately send all pending data. */ - flush: function () - { - // cancel the pending idle period and run the idle function - // immediately - clearTimeout(this._idleTimeout); - this._onIdle(); - }, - - /** Function: sendIQ + flush: function() { + // cancel the pending idle period and run the idle function + // immediately + clearTimeout(this._idleTimeout); + this._onIdle(); + }, + /** Function: sendIQ * Helper function to send IQ stanzas. * * Parameters: @@ -2487,93 +2214,76 @@ Strophe.Connection.prototype = { * Returns: * The id used to send the IQ. */ - sendIQ: function(elem, callback, errback, timeout) { - var timeoutHandler = null; - var that = this; - - if (typeof(elem.tree) === "function") { - elem = elem.tree(); - } - var id = elem.getAttribute('id'); - - // inject id if not found - if (!id) { - id = this.getUniqueId("sendIQ"); - elem.setAttribute("id", id); - } - - var handler = this.addHandler(function (stanza) { - // remove timeout handler if there is one - if (timeoutHandler) { - that.deleteTimedHandler(timeoutHandler); + sendIQ: function(elem, callback, errback, timeout) { + var timeoutHandler = null; + var that = this; + if (typeof elem.tree === "function") { + elem = elem.tree(); } - - var iqtype = stanza.getAttribute('type'); - if (iqtype == 'result') { - if (callback) { - callback(stanza); + var id = elem.getAttribute("id"); + // inject id if not found + if (!id) { + id = this.getUniqueId("sendIQ"); + elem.setAttribute("id", id); + } + var handler = this.addHandler(function(stanza) { + // remove timeout handler if there is one + if (timeoutHandler) { + that.deleteTimedHandler(timeoutHandler); } - } else if (iqtype == 'error') { - if (errback) { - errback(stanza); + var iqtype = stanza.getAttribute("type"); + if (iqtype == "result") { + if (callback) { + callback(stanza); + } + } else if (iqtype == "error") { + if (errback) { + errback(stanza); + } + } else { + throw { + name: "StropheError", + message: "Got bad IQ type of " + iqtype + }; } - } else { - throw { - name: "StropheError", - message: "Got bad IQ type of " + iqtype - }; + }, null, "iq", null, id); + // if timeout specified, setup timeout handler. + if (timeout) { + timeoutHandler = this.addTimedHandler(timeout, function() { + // get rid of normal handler + that.deleteHandler(handler); + // call errback on timeout with null stanza + if (errback) { + errback(null); + } + return false; + }); } - }, null, 'iq', null, id); - - // if timeout specified, setup timeout handler. - if (timeout) { - timeoutHandler = this.addTimedHandler(timeout, function () { - // get rid of normal handler - that.deleteHandler(handler); - - // call errback on timeout with null stanza - if (errback) { - errback(null); - } - return false; - }); - } - - this.send(elem); - - return id; - }, - - /** PrivateFunction: _queueData + this.send(elem); + return id; + }, + /** PrivateFunction: _queueData * Queue outgoing data for later sending. Also ensures that the data * is a DOMElement. */ - _queueData: function (element) { - if (element === null || - !element.tagName || - !element.childNodes) { - throw { - name: "StropheError", - message: "Cannot queue non-DOMElement." - }; - } - - this._data.push(element); - }, - - /** PrivateFunction: _sendRestart + _queueData: function(element) { + if (element === null || !element.tagName || !element.childNodes) { + throw { + name: "StropheError", + message: "Cannot queue non-DOMElement." + }; + } + this._data.push(element); + }, + /** PrivateFunction: _sendRestart * Send an xmpp:restart stanza. */ - _sendRestart: function () - { - this._data.push("restart"); - - this._proto._sendRestart(); - - this._idleTimeout = setTimeout(this._onIdle.bind(this), 100); - }, - - /** Function: addTimedHandler + _sendRestart: function() { + this._data.push("restart"); + this._proto._sendRestart(); + this._idleTimeout = setTimeout(this._onIdle.bind(this), 100); + }, + /** Function: addTimedHandler * Add a timed handler to the connection. * * This function adds a timed handler. The provided handler will @@ -2595,14 +2305,12 @@ Strophe.Connection.prototype = { * Returns: * A reference to the handler that can be used to remove it. */ - addTimedHandler: function (period, handler) - { - var thand = new Strophe.TimedHandler(period, handler); - this.addTimeds.push(thand); - return thand; - }, - - /** Function: deleteTimedHandler + addTimedHandler: function(period, handler) { + var thand = new Strophe.TimedHandler(period, handler); + this.addTimeds.push(thand); + return thand; + }, + /** Function: deleteTimedHandler * Delete a timed handler for a connection. * * This function removes a timed handler from the connection. The @@ -2612,14 +2320,12 @@ Strophe.Connection.prototype = { * Parameters: * (Strophe.TimedHandler) handRef - The handler reference. */ - deleteTimedHandler: function (handRef) - { - // this must be done in the Idle loop so that we don't change - // the handlers during iteration - this.removeTimeds.push(handRef); - }, - - /** Function: addHandler + deleteTimedHandler: function(handRef) { + // this must be done in the Idle loop so that we don't change + // the handlers during iteration + this.removeTimeds.push(handRef); + }, + /** Function: addHandler * Add a stanza handler for the connection. * * This function adds a stanza handler to the connection. The @@ -2657,14 +2363,12 @@ Strophe.Connection.prototype = { * Returns: * A reference to the handler that can be used to remove it. */ - addHandler: function (handler, ns, name, type, id, from, options) - { - var hand = new Strophe.Handler(handler, ns, name, type, id, from, options); - this.addHandlers.push(hand); - return hand; - }, - - /** Function: deleteHandler + addHandler: function(handler, ns, name, type, id, from, options) { + var hand = new Strophe.Handler(handler, ns, name, type, id, from, options); + this.addHandlers.push(hand); + return hand; + }, + /** Function: deleteHandler * Delete a stanza handler for a connection. * * This function removes a stanza handler from the connection. The @@ -2674,14 +2378,12 @@ Strophe.Connection.prototype = { * Parameters: * (Strophe.Handler) handRef - The handler reference. */ - deleteHandler: function (handRef) - { - // this must be done in the Idle loop so that we don't change - // the handlers during iteration - this.removeHandlers.push(handRef); - }, - - /** Function: disconnect + deleteHandler: function(handRef) { + // this must be done in the Idle loop so that we don't change + // the handlers during iteration + this.removeHandlers.push(handRef); + }, + /** Function: disconnect * Start the graceful disconnection process. * * This function starts the disconnection process. This process starts @@ -2695,28 +2397,24 @@ Strophe.Connection.prototype = { * Parameters: * (String) reason - The reason the disconnect is occuring. */ - disconnect: function (reason) - { - this._changeConnectStatus(Strophe.Status.DISCONNECTING, reason); - - Strophe.info("Disconnect was called because: " + reason); - if (this.connected) { - var pres = false; - this.disconnecting = true; - if (this.authenticated) { - pres = $pres({ - xmlns: Strophe.NS.CLIENT, - type: 'unavailable' - }); + disconnect: function(reason) { + this._changeConnectStatus(Strophe.Status.DISCONNECTING, reason); + Strophe.info("Disconnect was called because: " + reason); + if (this.connected) { + var pres = false; + this.disconnecting = true; + if (this.authenticated) { + pres = $pres({ + xmlns: Strophe.NS.CLIENT, + type: "unavailable" + }); + } + // setup timeout handler + this._disconnectTimeout = this._addSysTimedHandler(3e3, this._onDisconnectTimeout.bind(this)); + this._proto._disconnect(pres); } - // setup timeout handler - this._disconnectTimeout = this._addSysTimedHandler( - 3000, this._onDisconnectTimeout.bind(this)); - this._proto._disconnect(pres); - } - }, - - /** PrivateFunction: _changeConnectStatus + }, + /** PrivateFunction: _changeConnectStatus * _Private_ helper function that makes sure plugins and the user's * callback are notified of connection status changes. * @@ -2725,68 +2423,57 @@ Strophe.Connection.prototype = { * in Strophe.Status * (String) condition - the error condition or null */ - _changeConnectStatus: function (status, condition) - { - // notify all plugins listening for status changes - for (var k in Strophe._connectionPlugins) { - if (Strophe._connectionPlugins.hasOwnProperty(k)) { - var plugin = this[k]; - if (plugin.statusChanged) { - try { - plugin.statusChanged(status, condition); - } catch (err) { - Strophe.error("" + k + " plugin caused an exception " + - "changing status: " + err); + _changeConnectStatus: function(status, condition) { + // notify all plugins listening for status changes + for (var k in Strophe._connectionPlugins) { + if (Strophe._connectionPlugins.hasOwnProperty(k)) { + var plugin = this[k]; + if (plugin.statusChanged) { + try { + plugin.statusChanged(status, condition); + } catch (err) { + Strophe.error("" + k + " plugin caused an exception " + "changing status: " + err); + } } } } - } - - // notify the user's callback - if (this.connect_callback) { - try { - this.connect_callback(status, condition); - } catch (e) { - Strophe.error("User connection callback caused an " + - "exception: " + e); + // notify the user's callback + if (this.connect_callback) { + try { + this.connect_callback(status, condition); + } catch (e) { + Strophe.error("User connection callback caused an " + "exception: " + e); + } } - } - }, - - /** PrivateFunction: _doDisconnect + }, + /** PrivateFunction: _doDisconnect * _Private_ function to disconnect. * * This is the last piece of the disconnection logic. This resets the * connection and alerts the user's connection callback. */ - _doDisconnect: function () - { - // Cancel Disconnect Timeout - if (this._disconnectTimeout !== null) { - this.deleteTimedHandler(this._disconnectTimeout); - this._disconnectTimeout = null; - } - - Strophe.info("_doDisconnect was called"); - this._proto._doDisconnect(); - - this.authenticated = false; - this.disconnecting = false; - - // delete handlers - this.handlers = []; - this.timedHandlers = []; - this.removeTimeds = []; - this.removeHandlers = []; - this.addTimeds = []; - this.addHandlers = []; - - // tell the parent we disconnected - this._changeConnectStatus(Strophe.Status.DISCONNECTED, null); - this.connected = false; - }, - - /** PrivateFunction: _dataRecv + _doDisconnect: function() { + // Cancel Disconnect Timeout + if (this._disconnectTimeout !== null) { + this.deleteTimedHandler(this._disconnectTimeout); + this._disconnectTimeout = null; + } + Strophe.info("_doDisconnect was called"); + this._proto._doDisconnect(); + this.authenticated = false; + this.disconnecting = false; + // delete handlers + this.handlers = []; + this.timedHandlers = []; + this.removeTimeds = []; + this.removeHandlers = []; + this.addTimeds = []; + this.addHandlers = []; + // tell the parent we disconnected + this._changeConnectStatus(Strophe.Status.DISCONNECTED, null); + this.connected = false; + }, + /** PrivateFunction: _dataRecv * _Private_ handler to processes incoming data from the the connection. * * Except for _connect_cb handling the initial connection request, @@ -2798,106 +2485,96 @@ Strophe.Connection.prototype = { * (Strophe.Request) req - The request that has data ready. * (string) req - The stanza a raw string (optiona). */ - _dataRecv: function (req, raw) - { - Strophe.info("_dataRecv called"); - var elem = this._proto._reqToData(req); - if (elem === null) { return; } - - if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { - if (elem.nodeName === this._proto.strip && elem.childNodes.length) { - this.xmlInput(elem.childNodes[0]); - } else { - this.xmlInput(elem); + _dataRecv: function(req, raw) { + Strophe.info("_dataRecv called"); + var elem = this._proto._reqToData(req); + if (elem === null) { + return; } - } - if (this.rawInput !== Strophe.Connection.prototype.rawInput) { - if (raw) { - this.rawInput(raw); - } else { - this.rawInput(Strophe.serialize(elem)); + if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { + if (elem.nodeName === this._proto.strip && elem.childNodes.length) { + this.xmlInput(elem.childNodes[0]); + } else { + this.xmlInput(elem); + } } - } - - // remove handlers scheduled for deletion - var i, hand; - while (this.removeHandlers.length > 0) { - hand = this.removeHandlers.pop(); - i = this.handlers.indexOf(hand); - if (i >= 0) { - this.handlers.splice(i, 1); + if (this.rawInput !== Strophe.Connection.prototype.rawInput) { + if (raw) { + this.rawInput(raw); + } else { + this.rawInput(Strophe.serialize(elem)); + } } - } - - // add handlers scheduled for addition - while (this.addHandlers.length > 0) { - this.handlers.push(this.addHandlers.pop()); - } - - // handle graceful disconnect - if (this.disconnecting && this._proto._emptyQueue()) { - this._doDisconnect(); - return; - } - - var typ = elem.getAttribute("type"); - var cond, conflict; - if (typ !== null && typ == "terminate") { - // Don't process stanzas that come in after disconnect - if (this.disconnecting) { + // remove handlers scheduled for deletion + var i, hand; + while (this.removeHandlers.length > 0) { + hand = this.removeHandlers.pop(); + i = this.handlers.indexOf(hand); + if (i >= 0) { + this.handlers.splice(i, 1); + } + } + // add handlers scheduled for addition + while (this.addHandlers.length > 0) { + this.handlers.push(this.addHandlers.pop()); + } + // handle graceful disconnect + if (this.disconnecting && this._proto._emptyQueue()) { + this._doDisconnect(); return; } - - // an error occurred - cond = elem.getAttribute("condition"); - conflict = elem.getElementsByTagName("conflict"); - if (cond !== null) { - if (cond == "remote-stream-error" && conflict.length > 0) { - cond = "conflict"; + var typ = elem.getAttribute("type"); + var cond, conflict; + if (typ !== null && typ == "terminate") { + // Don't process stanzas that come in after disconnect + if (this.disconnecting) { + return; } - this._changeConnectStatus(Strophe.Status.CONNFAIL, cond); - } else { - this._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown"); + // an error occurred + cond = elem.getAttribute("condition"); + conflict = elem.getElementsByTagName("conflict"); + if (cond !== null) { + if (cond == "remote-stream-error" && conflict.length > 0) { + cond = "conflict"; + } + this._changeConnectStatus(Strophe.Status.CONNFAIL, cond); + } else { + this._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown"); + } + this.disconnect("unknown stream-error"); + return; } - this.disconnect('unknown stream-error'); - return; - } - - // send each incoming stanza through the handler chain - var that = this; - Strophe.forEachChild(elem, null, function (child) { - var i, newList; - // process handlers - newList = that.handlers; - that.handlers = []; - for (i = 0; i < newList.length; i++) { - var hand = newList[i]; - // encapsulate 'handler.run' not to lose the whole handler list if - // one of the handlers throws an exception - try { - if (hand.isMatch(child) && - (that.authenticated || !hand.user)) { - if (hand.run(child)) { + // send each incoming stanza through the handler chain + var that = this; + Strophe.forEachChild(elem, null, function(child) { + var i, newList; + // process handlers + newList = that.handlers; + that.handlers = []; + for (i = 0; i < newList.length; i++) { + var hand = newList[i]; + // encapsulate 'handler.run' not to lose the whole handler list if + // one of the handlers throws an exception + try { + if (hand.isMatch(child) && (that.authenticated || !hand.user)) { + if (hand.run(child)) { + that.handlers.push(hand); + } + } else { that.handlers.push(hand); } - } else { - that.handlers.push(hand); + } catch (e) { + // if the handler throws an exception, we consider it as false + Strophe.warn("Removing Strophe handlers due to uncaught exception: " + e.message); } - } catch(e) { - // if the handler throws an exception, we consider it as false - Strophe.warn('Removing Strophe handlers due to uncaught exception: ' + e.message); } - } - }); - }, - - - /** Attribute: mechanisms + }); + }, + /** Attribute: mechanisms * SASL Mechanisms available for Conncection. */ - mechanisms: {}, - - /** PrivateFunction: _connect_cb + mechanisms: {}, + /** PrivateFunction: _connect_cb * _Private_ handler for initial connection request. * * This handler is used to process the initial connection request @@ -2913,74 +2590,63 @@ Strophe.Connection.prototype = { * Useful for plugins with their own xmpp connect callback (when their) * want to do something special). */ - _connect_cb: function (req, _callback, raw) - { - Strophe.info("_connect_cb was called"); - - this.connected = true; - - var bodyWrap = this._proto._reqToData(req); - if (!bodyWrap) { return; } - - if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { - if (bodyWrap.nodeName === this._proto.strip && bodyWrap.childNodes.length) { - this.xmlInput(bodyWrap.childNodes[0]); - } else { - this.xmlInput(bodyWrap); + _connect_cb: function(req, _callback, raw) { + Strophe.info("_connect_cb was called"); + this.connected = true; + var bodyWrap = this._proto._reqToData(req); + if (!bodyWrap) { + return; } - } - if (this.rawInput !== Strophe.Connection.prototype.rawInput) { - if (raw) { - this.rawInput(raw); - } else { - this.rawInput(Strophe.serialize(bodyWrap)); + if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { + if (bodyWrap.nodeName === this._proto.strip && bodyWrap.childNodes.length) { + this.xmlInput(bodyWrap.childNodes[0]); + } else { + this.xmlInput(bodyWrap); + } } - } - - var conncheck = this._proto._connect_cb(bodyWrap); - if (conncheck === Strophe.Status.CONNFAIL) { - return; - } - - this._authentication.sasl_scram_sha1 = false; - this._authentication.sasl_plain = false; - this._authentication.sasl_digest_md5 = false; - this._authentication.sasl_anonymous = false; - - this._authentication.legacy_auth = false; - - // Check for the stream:features tag - var hasFeatures = bodyWrap.getElementsByTagName("stream:features").length > 0; - if (!hasFeatures) { - hasFeatures = bodyWrap.getElementsByTagName("features").length > 0; - } - var mechanisms = bodyWrap.getElementsByTagName("mechanism"); - var matched = []; - var i, mech, auth_str, hashed_auth_str, - found_authentication = false; - if (!hasFeatures) { - this._proto._no_auth_received(_callback); - return; - } - if (mechanisms.length > 0) { - for (i = 0; i < mechanisms.length; i++) { - mech = Strophe.getText(mechanisms[i]); - if (this.mechanisms[mech]) matched.push(this.mechanisms[mech]); + if (this.rawInput !== Strophe.Connection.prototype.rawInput) { + if (raw) { + this.rawInput(raw); + } else { + this.rawInput(Strophe.serialize(bodyWrap)); + } } - } - this._authentication.legacy_auth = - bodyWrap.getElementsByTagName("auth").length > 0; - found_authentication = this._authentication.legacy_auth || - matched.length > 0; - if (!found_authentication) { - this._proto._no_auth_received(_callback); - return; - } - if (this.do_authentication !== false) - this.authenticate(matched); - }, - - /** Function: authenticate + var conncheck = this._proto._connect_cb(bodyWrap); + if (conncheck === Strophe.Status.CONNFAIL) { + return; + } + this._authentication.sasl_scram_sha1 = false; + this._authentication.sasl_plain = false; + this._authentication.sasl_digest_md5 = false; + this._authentication.sasl_anonymous = false; + this._authentication.legacy_auth = false; + // Check for the stream:features tag + var hasFeatures = bodyWrap.getElementsByTagName("stream:features").length > 0; + if (!hasFeatures) { + hasFeatures = bodyWrap.getElementsByTagName("features").length > 0; + } + var mechanisms = bodyWrap.getElementsByTagName("mechanism"); + var matched = []; + var i, mech, auth_str, hashed_auth_str, found_authentication = false; + if (!hasFeatures) { + this._proto._no_auth_received(_callback); + return; + } + if (mechanisms.length > 0) { + for (i = 0; i < mechanisms.length; i++) { + mech = Strophe.getText(mechanisms[i]); + if (this.mechanisms[mech]) matched.push(this.mechanisms[mech]); + } + } + this._authentication.legacy_auth = bodyWrap.getElementsByTagName("auth").length > 0; + found_authentication = this._authentication.legacy_auth || matched.length > 0; + if (!found_authentication) { + this._proto._no_auth_received(_callback); + return; + } + if (this.do_authentication !== false) this.authenticate(matched); + }, + /** Function: authenticate * Set up authentication * * Contiunues the initial connection request by setting up authentication @@ -2990,100 +2656,77 @@ Strophe.Connection.prototype = { * the code will fall back to legacy authentication. * */ - authenticate: function (matched) - { - var i; - // Sorting matched mechanisms according to priority. - for (i = 0; i < matched.length - 1; ++i) { - var higher = i; - for (var j = i + 1; j < matched.length; ++j) { - if (matched[j].prototype.priority > matched[higher].prototype.priority) { - higher = j; - } - } - if (higher != i) { - var swap = matched[i]; - matched[i] = matched[higher]; - matched[higher] = swap; - } - } - - // run each mechanism - var mechanism_found = false; - for (i = 0; i < matched.length; ++i) { - if (!matched[i].test(this)) continue; - - this._sasl_success_handler = this._addSysHandler( - this._sasl_success_cb.bind(this), null, - "success", null, null); - this._sasl_failure_handler = this._addSysHandler( - this._sasl_failure_cb.bind(this), null, - "failure", null, null); - this._sasl_challenge_handler = this._addSysHandler( - this._sasl_challenge_cb.bind(this), null, - "challenge", null, null); - - this._sasl_mechanism = new matched[i](); - this._sasl_mechanism.onStart(this); - - var request_auth_exchange = $build("auth", { - xmlns: Strophe.NS.SASL, - mechanism: this._sasl_mechanism.name - }); - - if (this._sasl_mechanism.isClientFirst) { - var response = this._sasl_mechanism.onChallenge(this, null); - request_auth_exchange.t(Base64.encode(response)); - } - - this.send(request_auth_exchange.tree()); - - mechanism_found = true; - break; - } - - if (!mechanism_found) { - // if none of the mechanism worked - if (Strophe.getNodeFromJid(this.jid) === null) { - // we don't have a node, which is required for non-anonymous - // client connections - this._changeConnectStatus(Strophe.Status.CONNFAIL, - 'x-strophe-bad-non-anon-jid'); - this.disconnect('x-strophe-bad-non-anon-jid'); - } else { - // fall back to legacy authentication - this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); - this._addSysHandler(this._auth1_cb.bind(this), null, null, - null, "_auth_1"); - - this.send($iq({ - type: "get", - to: this.domain, - id: "_auth_1" - }).c("query", { - xmlns: Strophe.NS.AUTH - }).c("username", {}).t(Strophe.getNodeFromJid(this.jid)).tree()); - } - } - - }, - - _sasl_challenge_cb: function(elem) { - var challenge = Base64.decode(Strophe.getText(elem)); - var response = this._sasl_mechanism.onChallenge(this, challenge); - - var stanza = $build('response', { - xmlns: Strophe.NS.SASL - }); - if (response !== "") { - stanza.t(Base64.encode(response)); - } - this.send(stanza.tree()); - - return true; - }, - - /** PrivateFunction: _auth1_cb + authenticate: function(matched) { + var i; + // Sorting matched mechanisms according to priority. + for (i = 0; i < matched.length - 1; ++i) { + var higher = i; + for (var j = i + 1; j < matched.length; ++j) { + if (matched[j].prototype.priority > matched[higher].prototype.priority) { + higher = j; + } + } + if (higher != i) { + var swap = matched[i]; + matched[i] = matched[higher]; + matched[higher] = swap; + } + } + // run each mechanism + var mechanism_found = false; + for (i = 0; i < matched.length; ++i) { + if (!matched[i].test(this)) continue; + this._sasl_success_handler = this._addSysHandler(this._sasl_success_cb.bind(this), null, "success", null, null); + this._sasl_failure_handler = this._addSysHandler(this._sasl_failure_cb.bind(this), null, "failure", null, null); + this._sasl_challenge_handler = this._addSysHandler(this._sasl_challenge_cb.bind(this), null, "challenge", null, null); + this._sasl_mechanism = new matched[i](); + this._sasl_mechanism.onStart(this); + var request_auth_exchange = $build("auth", { + xmlns: Strophe.NS.SASL, + mechanism: this._sasl_mechanism.name + }); + if (this._sasl_mechanism.isClientFirst) { + var response = this._sasl_mechanism.onChallenge(this, null); + request_auth_exchange.t(Base64.encode(response)); + } + this.send(request_auth_exchange.tree()); + mechanism_found = true; + break; + } + if (!mechanism_found) { + // if none of the mechanism worked + if (Strophe.getNodeFromJid(this.jid) === null) { + // we don't have a node, which is required for non-anonymous + // client connections + this._changeConnectStatus(Strophe.Status.CONNFAIL, "x-strophe-bad-non-anon-jid"); + this.disconnect("x-strophe-bad-non-anon-jid"); + } else { + // fall back to legacy authentication + this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); + this._addSysHandler(this._auth1_cb.bind(this), null, null, null, "_auth_1"); + this.send($iq({ + type: "get", + to: this.domain, + id: "_auth_1" + }).c("query", { + xmlns: Strophe.NS.AUTH + }).c("username", {}).t(Strophe.getNodeFromJid(this.jid)).tree()); + } + } + }, + _sasl_challenge_cb: function(elem) { + var challenge = Base64.decode(Strophe.getText(elem)); + var response = this._sasl_mechanism.onChallenge(this, challenge); + var stanza = $build("response", { + xmlns: Strophe.NS.SASL + }); + if (response !== "") { + stanza.t(Base64.encode(response)); + } + this.send(stanza.tree()); + return true; + }, + /** PrivateFunction: _auth1_cb * _Private_ handler for legacy authentication. * * This handler is called in response to the initial @@ -3097,32 +2740,26 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _auth1_cb: function (elem) - { - // build plaintext auth iq - var iq = $iq({type: "set", id: "_auth_2"}) - .c('query', {xmlns: Strophe.NS.AUTH}) - .c('username', {}).t(Strophe.getNodeFromJid(this.jid)) - .up() - .c('password').t(this.pass); - - if (!Strophe.getResourceFromJid(this.jid)) { - // since the user has not supplied a resource, we pick - // a default one here. unlike other auth methods, the server - // cannot do this for us. - this.jid = Strophe.getBareJidFromJid(this.jid) + '/strophe'; - } - iq.up().c('resource', {}).t(Strophe.getResourceFromJid(this.jid)); - - this._addSysHandler(this._auth2_cb.bind(this), null, - null, null, "_auth_2"); - - this.send(iq.tree()); - - return false; - }, - - /** PrivateFunction: _sasl_success_cb + _auth1_cb: function(elem) { + // build plaintext auth iq + var iq = $iq({ + type: "set", + id: "_auth_2" + }).c("query", { + xmlns: Strophe.NS.AUTH + }).c("username", {}).t(Strophe.getNodeFromJid(this.jid)).up().c("password").t(this.pass); + if (!Strophe.getResourceFromJid(this.jid)) { + // since the user has not supplied a resource, we pick + // a default one here. unlike other auth methods, the server + // cannot do this for us. + this.jid = Strophe.getBareJidFromJid(this.jid) + "/strophe"; + } + iq.up().c("resource", {}).t(Strophe.getResourceFromJid(this.jid)); + this._addSysHandler(this._auth2_cb.bind(this), null, null, null, "_auth_2"); + this.send(iq.tree()); + return false; + }, + /** PrivateFunction: _sasl_success_cb * _Private_ handler for succesful SASL authentication. * * Parameters: @@ -3131,54 +2768,42 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _sasl_success_cb: function (elem) - { - if (this._sasl_data["server-signature"]) { - var serverSignature; - var success = Base64.decode(Strophe.getText(elem)); - var attribMatch = /([a-z]+)=([^,]+)(,|$)/; - matches = success.match(attribMatch); - if (matches[1] == "v") { - serverSignature = matches[2]; + _sasl_success_cb: function(elem) { + if (this._sasl_data["server-signature"]) { + var serverSignature; + var success = Base64.decode(Strophe.getText(elem)); + var attribMatch = /([a-z]+)=([^,]+)(,|$)/; + matches = success.match(attribMatch); + if (matches[1] == "v") { + serverSignature = matches[2]; + } + if (serverSignature != this._sasl_data["server-signature"]) { + // remove old handlers + this.deleteHandler(this._sasl_failure_handler); + this._sasl_failure_handler = null; + if (this._sasl_challenge_handler) { + this.deleteHandler(this._sasl_challenge_handler); + this._sasl_challenge_handler = null; + } + this._sasl_data = {}; + return this._sasl_failure_cb(null); + } } - - if (serverSignature != this._sasl_data["server-signature"]) { - // remove old handlers - this.deleteHandler(this._sasl_failure_handler); - this._sasl_failure_handler = null; - if (this._sasl_challenge_handler) { + Strophe.info("SASL authentication succeeded."); + if (this._sasl_mechanism) this._sasl_mechanism.onSuccess(); + // remove old handlers + this.deleteHandler(this._sasl_failure_handler); + this._sasl_failure_handler = null; + if (this._sasl_challenge_handler) { this.deleteHandler(this._sasl_challenge_handler); this._sasl_challenge_handler = null; - } - - this._sasl_data = {}; - return this._sasl_failure_cb(null); } - } - - Strophe.info("SASL authentication succeeded."); - - if(this._sasl_mechanism) - this._sasl_mechanism.onSuccess(); - - // remove old handlers - this.deleteHandler(this._sasl_failure_handler); - this._sasl_failure_handler = null; - if (this._sasl_challenge_handler) { - this.deleteHandler(this._sasl_challenge_handler); - this._sasl_challenge_handler = null; - } - - this._addSysHandler(this._sasl_auth1_cb.bind(this), null, - "stream:features", null, null); - - // we must send an xmpp:restart now - this._sendRestart(); - - return false; - }, - - /** PrivateFunction: _sasl_auth1_cb + this._addSysHandler(this._sasl_auth1_cb.bind(this), null, "stream:features", null, null); + // we must send an xmpp:restart now + this._sendRestart(); + return false; + }, + /** PrivateFunction: _sasl_auth1_cb * _Private_ handler to start stream binding. * * Parameters: @@ -3187,47 +2812,44 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _sasl_auth1_cb: function (elem) - { - // save stream:features for future usage - this.features = elem; - - var i, child; - - for (i = 0; i < elem.childNodes.length; i++) { - child = elem.childNodes[i]; - if (child.nodeName == 'bind') { - this.do_bind = true; - } - - if (child.nodeName == 'session') { - this.do_session = true; + _sasl_auth1_cb: function(elem) { + // save stream:features for future usage + this.features = elem; + var i, child; + for (i = 0; i < elem.childNodes.length; i++) { + child = elem.childNodes[i]; + if (child.nodeName == "bind") { + this.do_bind = true; + } + if (child.nodeName == "session") { + this.do_session = true; + } } - } - - if (!this.do_bind) { - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - return false; - } else { - this._addSysHandler(this._sasl_bind_cb.bind(this), null, null, - null, "_bind_auth_2"); - - var resource = Strophe.getResourceFromJid(this.jid); - if (resource) { - this.send($iq({type: "set", id: "_bind_auth_2"}) - .c('bind', {xmlns: Strophe.NS.BIND}) - .c('resource', {}).t(resource).tree()); + if (!this.do_bind) { + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); + return false; } else { - this.send($iq({type: "set", id: "_bind_auth_2"}) - .c('bind', {xmlns: Strophe.NS.BIND}) - .tree()); + this._addSysHandler(this._sasl_bind_cb.bind(this), null, null, null, "_bind_auth_2"); + var resource = Strophe.getResourceFromJid(this.jid); + if (resource) { + this.send($iq({ + type: "set", + id: "_bind_auth_2" + }).c("bind", { + xmlns: Strophe.NS.BIND + }).c("resource", {}).t(resource).tree()); + } else { + this.send($iq({ + type: "set", + id: "_bind_auth_2" + }).c("bind", { + xmlns: Strophe.NS.BIND + }).tree()); + } } - } - - return false; - }, - - /** PrivateFunction: _sasl_bind_cb + return false; + }, + /** PrivateFunction: _sasl_bind_cb * _Private_ handler for binding result and session start. * * Parameters: @@ -3236,47 +2858,44 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _sasl_bind_cb: function (elem) - { - if (elem.getAttribute("type") == "error") { - Strophe.info("SASL binding failed."); - var conflict = elem.getElementsByTagName("conflict"), condition; - if (conflict.length > 0) { - condition = 'conflict'; + _sasl_bind_cb: function(elem) { + if (elem.getAttribute("type") == "error") { + Strophe.info("SASL binding failed."); + var conflict = elem.getElementsByTagName("conflict"), condition; + if (conflict.length > 0) { + condition = "conflict"; + } + this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition); + return false; } - this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition); - return false; - } - - // TODO - need to grab errors - var bind = elem.getElementsByTagName("bind"); - var jidNode; - if (bind.length > 0) { - // Grab jid - jidNode = bind[0].getElementsByTagName("jid"); - if (jidNode.length > 0) { - this.jid = Strophe.getText(jidNode[0]); - - if (this.do_session) { - this._addSysHandler(this._sasl_session_cb.bind(this), - null, null, null, "_session_auth_2"); - - this.send($iq({type: "set", id: "_session_auth_2"}) - .c('session', {xmlns: Strophe.NS.SESSION}) - .tree()); - } else { - this.authenticated = true; - this._changeConnectStatus(Strophe.Status.CONNECTED, null); + // TODO - need to grab errors + var bind = elem.getElementsByTagName("bind"); + var jidNode; + if (bind.length > 0) { + // Grab jid + jidNode = bind[0].getElementsByTagName("jid"); + if (jidNode.length > 0) { + this.jid = Strophe.getText(jidNode[0]); + if (this.do_session) { + this._addSysHandler(this._sasl_session_cb.bind(this), null, null, null, "_session_auth_2"); + this.send($iq({ + type: "set", + id: "_session_auth_2" + }).c("session", { + xmlns: Strophe.NS.SESSION + }).tree()); + } else { + this.authenticated = true; + this._changeConnectStatus(Strophe.Status.CONNECTED, null); + } } + } else { + Strophe.info("SASL binding failed."); + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); + return false; } - } else { - Strophe.info("SASL binding failed."); - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - return false; - } - }, - - /** PrivateFunction: _sasl_session_cb + }, + /** PrivateFunction: _sasl_session_cb * _Private_ handler to finish successful SASL connection. * * This sets Connection.authenticated to true on success, which @@ -3288,21 +2907,18 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _sasl_session_cb: function (elem) - { - if (elem.getAttribute("type") == "result") { - this.authenticated = true; - this._changeConnectStatus(Strophe.Status.CONNECTED, null); - } else if (elem.getAttribute("type") == "error") { - Strophe.info("Session creation failed."); - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); + _sasl_session_cb: function(elem) { + if (elem.getAttribute("type") == "result") { + this.authenticated = true; + this._changeConnectStatus(Strophe.Status.CONNECTED, null); + } else if (elem.getAttribute("type") == "error") { + Strophe.info("Session creation failed."); + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); + return false; + } return false; - } - - return false; - }, - - /** PrivateFunction: _sasl_failure_cb + }, + /** PrivateFunction: _sasl_failure_cb * _Private_ handler for SASL authentication failure. * * Parameters: @@ -3311,25 +2927,21 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _sasl_failure_cb: function (elem) - { - // delete unneeded handlers - if (this._sasl_success_handler) { - this.deleteHandler(this._sasl_success_handler); - this._sasl_success_handler = null; - } - if (this._sasl_challenge_handler) { - this.deleteHandler(this._sasl_challenge_handler); - this._sasl_challenge_handler = null; - } - - if(this._sasl_mechanism) - this._sasl_mechanism.onFailure(); - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - return false; - }, - - /** PrivateFunction: _auth2_cb + _sasl_failure_cb: function(elem) { + // delete unneeded handlers + if (this._sasl_success_handler) { + this.deleteHandler(this._sasl_success_handler); + this._sasl_success_handler = null; + } + if (this._sasl_challenge_handler) { + this.deleteHandler(this._sasl_challenge_handler); + this._sasl_challenge_handler = null; + } + if (this._sasl_mechanism) this._sasl_mechanism.onFailure(); + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); + return false; + }, + /** PrivateFunction: _auth2_cb * _Private_ handler to finish legacy authentication. * * This handler is called when the result from the jabber:iq:auth @@ -3341,20 +2953,17 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _auth2_cb: function (elem) - { - if (elem.getAttribute("type") == "result") { - this.authenticated = true; - this._changeConnectStatus(Strophe.Status.CONNECTED, null); - } else if (elem.getAttribute("type") == "error") { - this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); - this.disconnect('authentication failed'); - } - - return false; - }, - - /** PrivateFunction: _addSysTimedHandler + _auth2_cb: function(elem) { + if (elem.getAttribute("type") == "result") { + this.authenticated = true; + this._changeConnectStatus(Strophe.Status.CONNECTED, null); + } else if (elem.getAttribute("type") == "error") { + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); + this.disconnect("authentication failed"); + } + return false; + }, + /** PrivateFunction: _addSysTimedHandler * _Private_ function to add a system level timed handler. * * This function is used to add a Strophe.TimedHandler for the @@ -3365,15 +2974,13 @@ Strophe.Connection.prototype = { * (Integer) period - The period of the handler. * (Function) handler - The callback function. */ - _addSysTimedHandler: function (period, handler) - { - var thand = new Strophe.TimedHandler(period, handler); - thand.user = false; - this.addTimeds.push(thand); - return thand; - }, - - /** PrivateFunction: _addSysHandler + _addSysTimedHandler: function(period, handler) { + var thand = new Strophe.TimedHandler(period, handler); + thand.user = false; + this.addTimeds.push(thand); + return thand; + }, + /** PrivateFunction: _addSysHandler * _Private_ function to add a system level stanza handler. * * This function is used to add a Strophe.Handler for the @@ -3387,15 +2994,13 @@ Strophe.Connection.prototype = { * (String) type - The stanza type attribute to match. * (String) id - The stanza id attribute to match. */ - _addSysHandler: function (handler, ns, name, type, id) - { - var hand = new Strophe.Handler(handler, ns, name, type, id); - hand.user = false; - this.addHandlers.push(hand); - return hand; - }, - - /** PrivateFunction: _onDisconnectTimeout + _addSysHandler: function(handler, ns, name, type, id) { + var hand = new Strophe.Handler(handler, ns, name, type, id); + hand.user = false; + this.addHandlers.push(hand); + return hand; + }, + /** PrivateFunction: _onDisconnectTimeout * _Private_ timeout handler for handling non-graceful disconnection. * * If the graceful disconnect process does not complete within the @@ -3404,80 +3009,65 @@ Strophe.Connection.prototype = { * Returns: * false to remove the handler. */ - _onDisconnectTimeout: function () - { - Strophe.info("_onDisconnectTimeout was called"); - - this._proto._onDisconnectTimeout(); - - // actually disconnect - this._doDisconnect(); - - return false; - }, - - /** PrivateFunction: _onIdle + _onDisconnectTimeout: function() { + Strophe.info("_onDisconnectTimeout was called"); + this._proto._onDisconnectTimeout(); + // actually disconnect + this._doDisconnect(); + return false; + }, + /** PrivateFunction: _onIdle * _Private_ handler to process events during idle cycle. * * This handler is called every 100ms to fire timed handlers that * are ready and keep poll requests going. */ - _onIdle: function () - { - var i, thand, since, newList; - - // add timed handlers scheduled for addition - // NOTE: we add before remove in the case a timed handler is - // added and then deleted before the next _onIdle() call. - while (this.addTimeds.length > 0) { - this.timedHandlers.push(this.addTimeds.pop()); - } - - // remove timed handlers that have been scheduled for deletion - while (this.removeTimeds.length > 0) { - thand = this.removeTimeds.pop(); - i = this.timedHandlers.indexOf(thand); - if (i >= 0) { - this.timedHandlers.splice(i, 1); + _onIdle: function() { + var i, thand, since, newList; + // add timed handlers scheduled for addition + // NOTE: we add before remove in the case a timed handler is + // added and then deleted before the next _onIdle() call. + while (this.addTimeds.length > 0) { + this.timedHandlers.push(this.addTimeds.pop()); } - } - - // call ready timed handlers - var now = new Date().getTime(); - newList = []; - for (i = 0; i < this.timedHandlers.length; i++) { - thand = this.timedHandlers[i]; - if (this.authenticated || !thand.user) { - since = thand.lastCalled + thand.period; - if (since - now <= 0) { - if (thand.run()) { + // remove timed handlers that have been scheduled for deletion + while (this.removeTimeds.length > 0) { + thand = this.removeTimeds.pop(); + i = this.timedHandlers.indexOf(thand); + if (i >= 0) { + this.timedHandlers.splice(i, 1); + } + } + // call ready timed handlers + var now = new Date().getTime(); + newList = []; + for (i = 0; i < this.timedHandlers.length; i++) { + thand = this.timedHandlers[i]; + if (this.authenticated || !thand.user) { + since = thand.lastCalled + thand.period; + if (since - now <= 0) { + if (thand.run()) { + newList.push(thand); + } + } else { newList.push(thand); } - } else { - newList.push(thand); } } + this.timedHandlers = newList; + var body, time_elapsed; + clearTimeout(this._idleTimeout); + this._proto._onIdle(); + // reactivate the timer only if connected + if (this.connected) { + this._idleTimeout = setTimeout(this._onIdle.bind(this), 100); + } } - this.timedHandlers = newList; - - var body, time_elapsed; - - clearTimeout(this._idleTimeout); - - this._proto._onIdle(); - - // reactivate the timer only if connected - if (this.connected) { - this._idleTimeout = setTimeout(this._onIdle.bind(this), 100); - } + }; + if (callback) { + callback(Strophe, $build, $msg, $iq, $pres); } -}; - -if (callback) { - callback(Strophe, $build, $msg, $iq, $pres); -} - -/** Class: Strophe.SASLMechanism + /** Class: Strophe.SASLMechanism * * encapsulates SASL authentication mechanisms. * @@ -3491,8 +3081,7 @@ if (callback) { * DIGEST-MD5 - 30 * Plain - 20 */ - -/** + /** * PrivateConstructor: Strophe.SASLMechanism * SASL auth mechanism abstraction. * @@ -3504,16 +3093,16 @@ if (callback) { * Returns: * A new Strophe.SASLMechanism object. */ -Strophe.SASLMechanism = function(name, isClientFirst, priority) { - /** PrivateVariable: name + Strophe.SASLMechanism = function(name, isClientFirst, priority) { + /** PrivateVariable: name * Mechanism name. */ - this.name = name; - /** PrivateVariable: isClientFirst + this.name = name; + /** PrivateVariable: isClientFirst * If client sends response without initial server challenge. */ - this.isClientFirst = isClientFirst; - /** Variable: priority + this.isClientFirst = isClientFirst; + /** Variable: priority * Determines which is chosen for authentication (Higher is better). * Users may override this to prioritize mechanisms differently. * @@ -3530,13 +3119,11 @@ Strophe.SASLMechanism = function(name, isClientFirst, priority) { * See for a list of available mechanisms. * */ - this.priority = priority; -}; - -Strophe.SASLMechanism.prototype = { - _sasl_data: {}, - - /** + this.priority = priority; + }; + Strophe.SASLMechanism.prototype = { + _sasl_data: {}, + /** * Function: test * Checks if mechanism able to run. * To disable a mechanism, make this return false; @@ -3554,22 +3141,19 @@ Strophe.SASLMechanism.prototype = { * Returns: * (Boolean) If mechanism was able to run. */ - test: function(connection) { - return true; - }, - - /** PrivateFunction: onStart + test: function(connection) { + return true; + }, + /** PrivateFunction: onStart * Called before starting mechanism on some connection. * * Parameters: * (Strophe.Connection) connection - Target Connection. */ - onStart: function(connection) - { - this._connection = connection; - }, - - /** PrivateFunction: onChallenge + onStart: function(connection) { + this._connection = connection; + }, + /** PrivateFunction: onChallenge * Called by protocol implementation on incoming challenge. If client is * first (isClientFirst == true) challenge will be null on the first call. * @@ -3580,26 +3164,23 @@ Strophe.SASLMechanism.prototype = { * Returns: * (String) Mechanism response. */ - onChallenge: function(connection, challenge) { - throw new Error("You should implement challenge handling!"); - }, - - /** PrivateFunction: onFailure + onChallenge: function(connection, challenge) { + throw new Error("You should implement challenge handling!"); + }, + /** PrivateFunction: onFailure * Protocol informs mechanism implementation about SASL failure. */ - onFailure: function() { - this._connection = null; - }, - - /** PrivateFunction: onSuccess + onFailure: function() { + this._connection = null; + }, + /** PrivateFunction: onSuccess * Protocol informs mechanism implementation about SASL success. */ - onSuccess: function() { - this._connection = null; - } -}; - - /** Constants: SASL mechanisms + onSuccess: function() { + this._connection = null; + } + }; + /** Constants: SASL mechanisms * Available authentication mechanisms * * Strophe.SASLAnonymous - SASL Anonymous authentication. @@ -3607,50 +3188,38 @@ Strophe.SASLMechanism.prototype = { * Strophe.SASLMD5 - SASL Digest-MD5 authentication * Strophe.SASLSHA1 - SASL SCRAM-SHA1 authentication */ - -// Building SASL callbacks - -/** PrivateConstructor: SASLAnonymous + // Building SASL callbacks + /** PrivateConstructor: SASLAnonymous * SASL Anonymous authentication. */ -Strophe.SASLAnonymous = function() {}; - -Strophe.SASLAnonymous.prototype = new Strophe.SASLMechanism("ANONYMOUS", false, 10); - -Strophe.SASLAnonymous.test = function(connection) { - return connection.authcid === null; -}; - -Strophe.Connection.prototype.mechanisms[Strophe.SASLAnonymous.prototype.name] = Strophe.SASLAnonymous; - -/** PrivateConstructor: SASLPlain + Strophe.SASLAnonymous = function() {}; + Strophe.SASLAnonymous.prototype = new Strophe.SASLMechanism("ANONYMOUS", false, 10); + Strophe.SASLAnonymous.test = function(connection) { + return connection.authcid === null; + }; + Strophe.Connection.prototype.mechanisms[Strophe.SASLAnonymous.prototype.name] = Strophe.SASLAnonymous; + /** PrivateConstructor: SASLPlain * SASL Plain authentication. */ -Strophe.SASLPlain = function() {}; - -Strophe.SASLPlain.prototype = new Strophe.SASLMechanism("PLAIN", true, 20); - -Strophe.SASLPlain.test = function(connection) { - return connection.authcid !== null; -}; - -Strophe.SASLPlain.prototype.onChallenge = function(connection, challenge) { - var auth_str = connection.authzid; - auth_str = auth_str + "\u0000"; - auth_str = auth_str + connection.authcid; - auth_str = auth_str + "\u0000"; - auth_str = auth_str + connection.pass; - return auth_str; -}; - -Strophe.Connection.prototype.mechanisms[Strophe.SASLPlain.prototype.name] = Strophe.SASLPlain; - -/** PrivateConstructor: SASLSHA1 + Strophe.SASLPlain = function() {}; + Strophe.SASLPlain.prototype = new Strophe.SASLMechanism("PLAIN", true, 20); + Strophe.SASLPlain.test = function(connection) { + return connection.authcid !== null; + }; + Strophe.SASLPlain.prototype.onChallenge = function(connection, challenge) { + var auth_str = connection.authzid; + auth_str = auth_str + "\x00"; + auth_str = auth_str + connection.authcid; + auth_str = auth_str + "\x00"; + auth_str = auth_str + connection.pass; + return auth_str; + }; + Strophe.Connection.prototype.mechanisms[Strophe.SASLPlain.prototype.name] = Strophe.SASLPlain; + /** PrivateConstructor: SASLSHA1 * SASL SCRAM SHA 1 authentication. */ -Strophe.SASLSHA1 = function() {}; - -/* TEST: + Strophe.SASLSHA1 = function() {}; + /* TEST: * This is a simple example of a SCRAM-SHA-1 authentication exchange * when the client doesn't support channel bindings (username 'user' and * password 'pencil' are used): @@ -3663,103 +3232,81 @@ Strophe.SASLSHA1 = function() {}; * S: v=rmF9pqV8S7suAoZWja4dJRkFsKQ= * */ + Strophe.SASLSHA1.prototype = new Strophe.SASLMechanism("SCRAM-SHA-1", true, 40); + Strophe.SASLSHA1.test = function(connection) { + return connection.authcid !== null; + }; + Strophe.SASLSHA1.prototype.onChallenge = function(connection, challenge, test_cnonce) { + var cnonce = test_cnonce || MD5.hexdigest(Math.random() * 1234567890); + var auth_str = "n=" + connection.authcid; + auth_str += ",r="; + auth_str += cnonce; + this._sasl_data.cnonce = cnonce; + this._sasl_data["client-first-message-bare"] = auth_str; + auth_str = "n,," + auth_str; + this.onChallenge = function(connection, challenge) { + var nonce, salt, iter, Hi, U, U_old; + var clientKey, serverKey, clientSignature; + var responseText = "c=biws,"; + var authMessage = this._sasl_data["client-first-message-bare"] + "," + challenge + ","; + var cnonce = this._sasl_data.cnonce; + var attribMatch = /([a-z]+)=([^,]+)(,|$)/; + while (challenge.match(attribMatch)) { + matches = challenge.match(attribMatch); + challenge = challenge.replace(matches[0], ""); + switch (matches[1]) { + case "r": + nonce = matches[2]; + break; -Strophe.SASLSHA1.prototype = new Strophe.SASLMechanism("SCRAM-SHA-1", true, 40); - -Strophe.SASLSHA1.test = function(connection) { - return connection.authcid !== null; -}; - -Strophe.SASLSHA1.prototype.onChallenge = function(connection, challenge, test_cnonce) { - var cnonce = test_cnonce || MD5.hexdigest(Math.random() * 1234567890); - - var auth_str = "n=" + connection.authcid; - auth_str += ",r="; - auth_str += cnonce; - - this._sasl_data.cnonce = cnonce; - this._sasl_data["client-first-message-bare"] = auth_str; - - auth_str = "n,," + auth_str; - - this.onChallenge = function (connection, challenge) - { - var nonce, salt, iter, Hi, U, U_old; - var clientKey, serverKey, clientSignature; - var responseText = "c=biws,"; - var authMessage = this._sasl_data["client-first-message-bare"] + "," + - challenge + ","; - var cnonce = this._sasl_data.cnonce; - var attribMatch = /([a-z]+)=([^,]+)(,|$)/; - - while (challenge.match(attribMatch)) { - matches = challenge.match(attribMatch); - challenge = challenge.replace(matches[0], ""); - switch (matches[1]) { - case "r": - nonce = matches[2]; - break; - case "s": - salt = matches[2]; - break; - case "i": - iter = matches[2]; - break; - } - } - - if (nonce.substr(0, cnonce.length) !== cnonce) { - this._sasl_data = {}; - return connection._sasl_failure_cb(); - } - - responseText += "r=" + nonce; - authMessage += responseText; - - salt = Base64.decode(salt); - salt += "\x00\x00\x00\x01"; - - Hi = U_old = core_hmac_sha1(connection.pass, salt); - for (i = 1; i < iter; i++) { - U = core_hmac_sha1(connection.pass, binb2str(U_old)); - for (k = 0; k < 5; k++) { - Hi[k] ^= U[k]; - } - U_old = U; - } - Hi = binb2str(Hi); - - clientKey = core_hmac_sha1(Hi, "Client Key"); - serverKey = str_hmac_sha1(Hi, "Server Key"); - clientSignature = core_hmac_sha1(str_sha1(binb2str(clientKey)), authMessage); - connection._sasl_data["server-signature"] = b64_hmac_sha1(serverKey, authMessage); - - for (k = 0; k < 5; k++) { - clientKey[k] ^= clientSignature[k]; - } - - responseText += ",p=" + Base64.encode(binb2str(clientKey)); - - return responseText; - }.bind(this); - - return auth_str; -}; - -Strophe.Connection.prototype.mechanisms[Strophe.SASLSHA1.prototype.name] = Strophe.SASLSHA1; + case "s": + salt = matches[2]; + break; -/** PrivateConstructor: SASLMD5 + case "i": + iter = matches[2]; + break; + } + } + if (nonce.substr(0, cnonce.length) !== cnonce) { + this._sasl_data = {}; + return connection._sasl_failure_cb(); + } + responseText += "r=" + nonce; + authMessage += responseText; + salt = Base64.decode(salt); + salt += "\x00\x00\x00"; + Hi = U_old = core_hmac_sha1(connection.pass, salt); + for (i = 1; i < iter; i++) { + U = core_hmac_sha1(connection.pass, binb2str(U_old)); + for (k = 0; k < 5; k++) { + Hi[k] ^= U[k]; + } + U_old = U; + } + Hi = binb2str(Hi); + clientKey = core_hmac_sha1(Hi, "Client Key"); + serverKey = str_hmac_sha1(Hi, "Server Key"); + clientSignature = core_hmac_sha1(str_sha1(binb2str(clientKey)), authMessage); + connection._sasl_data["server-signature"] = b64_hmac_sha1(serverKey, authMessage); + for (k = 0; k < 5; k++) { + clientKey[k] ^= clientSignature[k]; + } + responseText += ",p=" + Base64.encode(binb2str(clientKey)); + return responseText; + }.bind(this); + return auth_str; + }; + Strophe.Connection.prototype.mechanisms[Strophe.SASLSHA1.prototype.name] = Strophe.SASLSHA1; + /** PrivateConstructor: SASLMD5 * SASL DIGEST MD5 authentication. */ -Strophe.SASLMD5 = function() {}; - -Strophe.SASLMD5.prototype = new Strophe.SASLMechanism("DIGEST-MD5", false, 30); - -Strophe.SASLMD5.test = function(connection) { - return connection.authcid !== null; -}; - -/** PrivateFunction: _quote + Strophe.SASLMD5 = function() {}; + Strophe.SASLMD5.prototype = new Strophe.SASLMechanism("DIGEST-MD5", false, 30); + Strophe.SASLMD5.test = function(connection) { + return connection.authcid !== null; + }; + /** PrivateFunction: _quote * _Private_ utility function to backslash escape and quote strings. * * Parameters: @@ -3768,98 +3315,80 @@ Strophe.SASLMD5.test = function(connection) { * Returns: * quoted string */ -Strophe.SASLMD5.prototype._quote = function (str) - { - return '"' + str.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"'; - //" end string workaround for emacs - }; - - -Strophe.SASLMD5.prototype.onChallenge = function(connection, challenge, test_cnonce) { - var attribMatch = /([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/; - var cnonce = test_cnonce || MD5.hexdigest("" + (Math.random() * 1234567890)); - var realm = ""; - var host = null; - var nonce = ""; - var qop = ""; - var matches; - - while (challenge.match(attribMatch)) { - matches = challenge.match(attribMatch); - challenge = challenge.replace(matches[0], ""); - matches[2] = matches[2].replace(/^"(.+)"$/, "$1"); - switch (matches[1]) { - case "realm": - realm = matches[2]; - break; - case "nonce": - nonce = matches[2]; - break; - case "qop": - qop = matches[2]; - break; - case "host": - host = matches[2]; - break; - } - } - - var digest_uri = connection.servtype + "/" + connection.domain; - if (host !== null) { - digest_uri = digest_uri + "/" + host; - } - - var A1 = MD5.hash(connection.authcid + - ":" + realm + ":" + this._connection.pass) + - ":" + nonce + ":" + cnonce; - var A2 = 'AUTHENTICATE:' + digest_uri; + Strophe.SASLMD5.prototype._quote = function(str) { + return '"' + str.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"'; + }; + Strophe.SASLMD5.prototype.onChallenge = function(connection, challenge, test_cnonce) { + var attribMatch = /([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/; + var cnonce = test_cnonce || MD5.hexdigest("" + Math.random() * 1234567890); + var realm = ""; + var host = null; + var nonce = ""; + var qop = ""; + var matches; + while (challenge.match(attribMatch)) { + matches = challenge.match(attribMatch); + challenge = challenge.replace(matches[0], ""); + matches[2] = matches[2].replace(/^"(.+)"$/, "$1"); + switch (matches[1]) { + case "realm": + realm = matches[2]; + break; - var responseText = ""; - responseText += 'charset=utf-8,'; - responseText += 'username=' + - this._quote(connection.authcid) + ','; - responseText += 'realm=' + this._quote(realm) + ','; - responseText += 'nonce=' + this._quote(nonce) + ','; - responseText += 'nc=00000001,'; - responseText += 'cnonce=' + this._quote(cnonce) + ','; - responseText += 'digest-uri=' + this._quote(digest_uri) + ','; - responseText += 'response=' + MD5.hexdigest(MD5.hexdigest(A1) + ":" + - nonce + ":00000001:" + - cnonce + ":auth:" + - MD5.hexdigest(A2)) + ","; - responseText += 'qop=auth'; + case "nonce": + nonce = matches[2]; + break; - this.onChallenge = function (connection, challenge) - { - return ""; - }.bind(this); + case "qop": + qop = matches[2]; + break; - return responseText; -}; - -Strophe.Connection.prototype.mechanisms[Strophe.SASLMD5.prototype.name] = Strophe.SASLMD5; - -})(function () { + case "host": + host = matches[2]; + break; + } + } + var digest_uri = connection.servtype + "/" + connection.domain; + if (host !== null) { + digest_uri = digest_uri + "/" + host; + } + var A1 = MD5.hash(connection.authcid + ":" + realm + ":" + this._connection.pass) + ":" + nonce + ":" + cnonce; + var A2 = "AUTHENTICATE:" + digest_uri; + var responseText = ""; + responseText += "charset=utf-8,"; + responseText += "username=" + this._quote(connection.authcid) + ","; + responseText += "realm=" + this._quote(realm) + ","; + responseText += "nonce=" + this._quote(nonce) + ","; + responseText += "nc=00000001,"; + responseText += "cnonce=" + this._quote(cnonce) + ","; + responseText += "digest-uri=" + this._quote(digest_uri) + ","; + responseText += "response=" + MD5.hexdigest(MD5.hexdigest(A1) + ":" + nonce + ":00000001:" + cnonce + ":auth:" + MD5.hexdigest(A2)) + ","; + responseText += "qop=auth"; + this.onChallenge = function(connection, challenge) { + return ""; + }.bind(this); + return responseText; + }; + Strophe.Connection.prototype.mechanisms[Strophe.SASLMD5.prototype.name] = Strophe.SASLMD5; +})(function() { window.Strophe = arguments[0]; window.$build = arguments[1]; window.$msg = arguments[2]; window.$iq = arguments[3]; window.$pres = arguments[4]; }); + /* This program is distributed under the terms of the MIT license. Please see the LICENSE file for details. Copyright 2006-2008, OGG, LLC */ - /* jslint configuration: */ /*global document, window, setTimeout, clearTimeout, console, XMLHttpRequest, ActiveXObject, Base64, MD5, Strophe, $build, $msg, $iq, $pres */ - - /** PrivateClass: Strophe.Request * _Private_ helper class that provides a cross implementation abstraction * for a BOSH related XMLHttpRequest. @@ -3867,7 +3396,6 @@ Strophe.Connection.prototype.mechanisms[Strophe.SASLMD5.prototype.name] = Stroph * The Strophe.Request class is used internally to encapsulate BOSH request * information. It is not meant to be used from user's code. */ - /** PrivateConstructor: Strophe.Request * Create and initialize a new Strophe.Request object. * @@ -3879,8 +3407,7 @@ Strophe.Connection.prototype.mechanisms[Strophe.SASLMD5.prototype.name] = Stroph * (Integer) sends - The number of times this same request has been * sent. */ -Strophe.Request = function (elem, func, rid, sends) -{ +Strophe.Request = function(elem, func, rid, sends) { this.id = ++Strophe._requestId; this.xmlData = elem; this.data = Strophe.serialize(elem); @@ -3893,16 +3420,19 @@ Strophe.Request = function (elem, func, rid, sends) this.sends = sends || 0; this.abort = false; this.dead = null; - - this.age = function () { - if (!this.date) { return 0; } + this.age = function() { + if (!this.date) { + return 0; + } var now = new Date(); - return (now - this.date) / 1000; + return (now - this.date) / 1e3; }; - this.timeDead = function () { - if (!this.dead) { return 0; } + this.timeDead = function() { + if (!this.dead) { + return 0; + } var now = new Date(); - return (now - this.dead) / 1000; + return (now - this.dead) / 1e3; }; this.xhr = this._newXHR(); }; @@ -3920,28 +3450,23 @@ Strophe.Request.prototype = { * Returns: * The DOM element tree of the response. */ - getResponse: function () - { + getResponse: function() { var node = null; if (this.xhr.responseXML && this.xhr.responseXML.documentElement) { node = this.xhr.responseXML.documentElement; if (node.tagName == "parsererror") { Strophe.error("invalid response received"); Strophe.error("responseText: " + this.xhr.responseText); - Strophe.error("responseXML: " + - Strophe.serialize(this.xhr.responseXML)); + Strophe.error("responseXML: " + Strophe.serialize(this.xhr.responseXML)); throw "parsererror"; } } else if (this.xhr.responseText) { Strophe.error("invalid response received"); Strophe.error("responseText: " + this.xhr.responseText); - Strophe.error("responseXML: " + - Strophe.serialize(this.xhr.responseXML)); + Strophe.error("responseXML: " + Strophe.serialize(this.xhr.responseXML)); } - return node; }, - /** PrivateFunction: _newXHR * _Private_ helper function to create XMLHttpRequests. * @@ -3950,8 +3475,7 @@ Strophe.Request.prototype = { * Returns: * A new XMLHttpRequest. */ - _newXHR: function () - { + _newXHR: function() { var xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); @@ -3961,10 +3485,8 @@ Strophe.Request.prototype = { } else if (window.ActiveXObject) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } - // use Function.bind() to prepend ourselves as an argument xhr.onreadystatechange = this.func.bind(null, this); - return xhr; } }; @@ -3975,7 +3497,6 @@ Strophe.Request.prototype = { * The Strophe.Bosh class is used internally by Strophe.Connection * to encapsulate BOSH sessions. It is not meant to be used from user's code. */ - /** File: bosh.js * A JavaScript library to enable BOSH in Strophejs. * @@ -3983,7 +3504,6 @@ Strophe.Request.prototype = { * to emulate a persistent, stateful, two-way connection to an XMPP server. * More information on BOSH can be found in XEP 124. */ - /** PrivateConstructor: Strophe.Bosh * Create and initialize a Strophe.Bosh object. * @@ -3999,12 +3519,10 @@ Strophe.Bosh = function(connection) { this.rid = Math.floor(Math.random() * 4294967295); /* The current session ID. */ this.sid = null; - // default BOSH values this.hold = 1; this.wait = 60; this.window = 5; - this._requests = []; }; @@ -4021,48 +3539,41 @@ Strophe.Bosh.prototype = { * and . */ strip: null, - /** PrivateFunction: _buildBody * _Private_ helper function to generate the wrapper for BOSH. * * Returns: * A Strophe.Builder with a element. */ - _buildBody: function () - { - var bodyWrap = $build('body', { + _buildBody: function() { + var bodyWrap = $build("body", { rid: this.rid++, xmlns: Strophe.NS.HTTPBIND }); - if (this.sid !== null) { - bodyWrap.attrs({sid: this.sid}); + bodyWrap.attrs({ + sid: this.sid + }); } - return bodyWrap; }, - /** PrivateFunction: _reset * Reset the connection. * * This function is called by the reset function of the Strophe Connection */ - _reset: function () - { + _reset: function() { this.rid = Math.floor(Math.random() * 4294967295); this.sid = null; }, - /** PrivateFunction: _connect * _Private_ function that initializes the BOSH connection. * * Creates and sends the Request that initializes the BOSH connection. */ - _connect: function (wait, hold, route) - { + _connect: function(wait, hold, route) { this.wait = wait || this.wait; this.hold = hold || this.hold; - // build the body tag var body = this._buildBody().attrs({ to: this._conn.domain, @@ -4074,23 +3585,15 @@ Strophe.Bosh.prototype = { "xmpp:version": "1.0", "xmlns:xmpp": Strophe.NS.BOSH }); - - if(route){ + if (route) { body.attrs({ route: route }); } - var _connect_cb = this._conn._connect_cb; - - this._requests.push( - new Strophe.Request(body.tree(), - this._onRequestStateChange.bind( - this, _connect_cb.bind(this._conn)), - body.tree().getAttribute("rid"))); + this._requests.push(new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, _connect_cb.bind(this._conn)), body.tree().getAttribute("rid"))); this._throttledRequestHandler(); }, - /** PrivateFunction: _attach * Attach to an already created and authenticated BOSH session. * @@ -4115,26 +3618,19 @@ Strophe.Bosh.prototype = { * (Integer) wind - The optional HTTBIND window value. This is the * allowed range of request ids that are valid. The default is 5. */ - _attach: function (jid, sid, rid, callback, wait, hold, wind) - { + _attach: function(jid, sid, rid, callback, wait, hold, wind) { this._conn.jid = jid; this.sid = sid; this.rid = rid; - this._conn.connect_callback = callback; - this._conn.domain = Strophe.getDomainFromJid(this._conn.jid); - this._conn.authenticated = true; this._conn.connected = true; - this.wait = wait || this.wait; this.hold = hold || this.hold; this.window = wind || this.window; - this._conn._changeConnectStatus(Strophe.Status.ATTACHED, null); }, - /** PrivateFunction: _connect_cb * _Private_ handler for initial connection request. * @@ -4142,8 +3638,7 @@ Strophe.Bosh.prototype = { * Parameters: * (Strophe.Request) bodyWrap - The received stanza. */ - _connect_cb: function (bodyWrap) - { + _connect_cb: function(bodyWrap) { var typ = bodyWrap.getAttribute("type"); var cond, conflict; if (typ !== null && typ == "terminate") { @@ -4162,53 +3657,51 @@ Strophe.Bosh.prototype = { this._conn._doDisconnect(); return Strophe.Status.CONNFAIL; } - // check to make sure we don't overwrite these if _connect_cb is // called multiple times in the case of missing stream:features if (!this.sid) { this.sid = bodyWrap.getAttribute("sid"); } - var wind = bodyWrap.getAttribute('requests'); - if (wind) { this.window = parseInt(wind, 10); } - var hold = bodyWrap.getAttribute('hold'); - if (hold) { this.hold = parseInt(hold, 10); } - var wait = bodyWrap.getAttribute('wait'); - if (wait) { this.wait = parseInt(wait, 10); } + var wind = bodyWrap.getAttribute("requests"); + if (wind) { + this.window = parseInt(wind, 10); + } + var hold = bodyWrap.getAttribute("hold"); + if (hold) { + this.hold = parseInt(hold, 10); + } + var wait = bodyWrap.getAttribute("wait"); + if (wait) { + this.wait = parseInt(wait, 10); + } }, - /** PrivateFunction: _disconnect * _Private_ part of Connection.disconnect for Bosh * * Parameters: * (Request) pres - This stanza will be sent before disconnecting. */ - _disconnect: function (pres) - { + _disconnect: function(pres) { this._sendTerminate(pres); }, - /** PrivateFunction: _doDisconnect * _Private_ function to disconnect. * * Resets the SID and RID. */ - _doDisconnect: function () - { + _doDisconnect: function() { this.sid = null; this.rid = Math.floor(Math.random() * 4294967295); }, - /** PrivateFunction: _emptyQueue * _Private_ function to check if the Request queue is empty. * * Returns: * True, if there are no Requests queued, False otherwise. */ - _emptyQueue: function () - { + _emptyQueue: function() { return this._requests.length === 0; }, - /** PrivateFunction: _hitError * _Private_ function to handle the error count. * @@ -4219,44 +3712,34 @@ Strophe.Bosh.prototype = { * Parameters: * (Integer) reqStatus - The request status. */ - _hitError: function (reqStatus) - { + _hitError: function(reqStatus) { this.errors++; - Strophe.warn("request errored, status: " + reqStatus + - ", number of errors: " + this.errors); + Strophe.warn("request errored, status: " + reqStatus + ", number of errors: " + this.errors); if (this.errors > 4) { this._onDisconnectTimeout(); } }, - /** PrivateFunction: _no_auth_received * * Called on stream start/restart when no stream:features * has been received and sends a blank poll request. */ - _no_auth_received: function (_callback) - { + _no_auth_received: function(_callback) { if (_callback) { _callback = _callback.bind(this._conn); } else { _callback = this._conn._connect_cb.bind(this._conn); } var body = this._buildBody(); - this._requests.push( - new Strophe.Request(body.tree(), - this._onRequestStateChange.bind( - this, _callback.bind(this._conn)), - body.tree().getAttribute("rid"))); + this._requests.push(new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, _callback.bind(this._conn)), body.tree().getAttribute("rid"))); this._throttledRequestHandler(); }, - /** PrivateFunction: _onDisconnectTimeout * _Private_ timeout handler for handling non-graceful disconnection. * * Cancels all remaining Requests and clears the queue. */ - _onDisconnectTimeout: function () - { + _onDisconnectTimeout: function() { var req; while (this._requests.length > 0) { req = this._requests.pop(); @@ -4264,28 +3747,22 @@ Strophe.Bosh.prototype = { req.xhr.abort(); // jslint complains, but this is fine. setting to empty func // is necessary for IE6 - req.xhr.onreadystatechange = function () {}; + req.xhr.onreadystatechange = function() {}; } }, - /** PrivateFunction: _onIdle * _Private_ handler called by Strophe.Connection._onIdle * * Sends all queued Requests or polls with empty Request if there are none. */ - _onIdle: function () { + _onIdle: function() { var data = this._conn._data; - // if no requests are in progress, poll - if (this._conn.authenticated && this._requests.length === 0 && - data.length === 0 && !this._conn.disconnecting) { - Strophe.info("no requests during idle cycle, sending " + - "blank request"); + if (this._conn.authenticated && this._requests.length === 0 && data.length === 0 && !this._conn.disconnecting) { + Strophe.info("no requests during idle cycle, sending " + "blank request"); data.push(null); } - - if (this._requests.length < 2 && data.length > 0 && - !this._conn.paused) { + if (this._requests.length < 2 && data.length > 0 && !this._conn.paused) { body = this._buildBody(); for (i = 0; i < data.length; i++) { if (data[i] !== null) { @@ -4303,33 +3780,22 @@ Strophe.Bosh.prototype = { } delete this._conn._data; this._conn._data = []; - this._requests.push( - new Strophe.Request(body.tree(), - this._onRequestStateChange.bind( - this, this._conn._dataRecv.bind(this._conn)), - body.tree().getAttribute("rid"))); + this._requests.push(new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, this._conn._dataRecv.bind(this._conn)), body.tree().getAttribute("rid"))); this._processRequest(this._requests.length - 1); } - if (this._requests.length > 0) { time_elapsed = this._requests[0].age(); if (this._requests[0].dead !== null) { - if (this._requests[0].timeDead() > - Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)) { + if (this._requests[0].timeDead() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)) { this._throttledRequestHandler(); } } - if (time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait)) { - Strophe.warn("Request " + - this._requests[0].id + - " timed out, over " + Math.floor(Strophe.TIMEOUT * this.wait) + - " seconds since last activity"); + Strophe.warn("Request " + this._requests[0].id + " timed out, over " + Math.floor(Strophe.TIMEOUT * this.wait) + " seconds since last activity"); this._throttledRequestHandler(); } } }, - /** PrivateFunction: _onRequestStateChange * _Private_ handler for Strophe.Request state changes. * @@ -4342,91 +3808,63 @@ Strophe.Bosh.prototype = { * (Function) func - The handler for the request. * (Strophe.Request) req - The request that is changing readyState. */ - _onRequestStateChange: function (func, req) - { - Strophe.debug("request id " + req.id + - "." + req.sends + " state changed to " + - req.xhr.readyState); - + _onRequestStateChange: function(func, req) { + Strophe.debug("request id " + req.id + "." + req.sends + " state changed to " + req.xhr.readyState); if (req.abort) { req.abort = false; return; } - // request complete var reqStatus; if (req.xhr.readyState == 4) { reqStatus = 0; try { reqStatus = req.xhr.status; - } catch (e) { - // ignore errors from undefined status attribute. works - // around a browser bug - } - - if (typeof(reqStatus) == "undefined") { + } catch (e) {} + if (typeof reqStatus == "undefined") { reqStatus = 0; } - if (this.disconnecting) { if (reqStatus >= 400) { this._hitError(reqStatus); return; } } - - var reqIs0 = (this._requests[0] == req); - var reqIs1 = (this._requests[1] == req); - - if ((reqStatus > 0 && reqStatus < 500) || req.sends > 5) { + var reqIs0 = this._requests[0] == req; + var reqIs1 = this._requests[1] == req; + if (reqStatus > 0 && reqStatus < 500 || req.sends > 5) { // remove from internal queue this._removeRequest(req); - Strophe.debug("request id " + - req.id + - " should now be removed"); + Strophe.debug("request id " + req.id + " should now be removed"); } - // request succeeded if (reqStatus == 200) { // if request 1 finished, or request 0 finished and request // 1 is over Strophe.SECONDARY_TIMEOUT seconds old, we need to // restart the other - both will be in the first spot, as the // completed request has been removed from the queue already - if (reqIs1 || - (reqIs0 && this._requests.length > 0 && - this._requests[0].age() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait))) { + if (reqIs1 || reqIs0 && this._requests.length > 0 && this._requests[0].age() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)) { this._restartRequest(0); } // call handler - Strophe.debug("request id " + - req.id + "." + - req.sends + " got 200"); + Strophe.debug("request id " + req.id + "." + req.sends + " got 200"); func(req); this.errors = 0; } else { - Strophe.error("request id " + - req.id + "." + - req.sends + " error " + reqStatus + - " happened"); - if (reqStatus === 0 || - (reqStatus >= 400 && reqStatus < 600) || - reqStatus >= 12000) { + Strophe.error("request id " + req.id + "." + req.sends + " error " + reqStatus + " happened"); + if (reqStatus === 0 || reqStatus >= 400 && reqStatus < 600 || reqStatus >= 12e3) { this._hitError(reqStatus); if (reqStatus >= 400 && reqStatus < 500) { - this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING, - null); + this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING, null); this._conn._doDisconnect(); } } } - - if (!((reqStatus > 0 && reqStatus < 500) || - req.sends > 5)) { + if (!(reqStatus > 0 && reqStatus < 500 || req.sends > 5)) { this._throttledRequestHandler(); } } }, - /** PrivateFunction: _processRequest * _Private_ function to process a request in the queue. * @@ -4436,78 +3874,57 @@ Strophe.Bosh.prototype = { * Parameters: * (Integer) i - The index of the request in the queue. */ - _processRequest: function (i) - { + _processRequest: function(i) { var self = this; var req = this._requests[i]; var reqStatus = -1; - try { if (req.xhr.readyState == 4) { reqStatus = req.xhr.status; } } catch (e) { - Strophe.error("caught an error in _requests[" + i + - "], reqStatus: " + reqStatus); + Strophe.error("caught an error in _requests[" + i + "], reqStatus: " + reqStatus); } - - if (typeof(reqStatus) == "undefined") { + if (typeof reqStatus == "undefined") { reqStatus = -1; } - // make sure we limit the number of retries if (req.sends > this.maxRetries) { this._onDisconnectTimeout(); return; } - var time_elapsed = req.age(); - var primaryTimeout = (!isNaN(time_elapsed) && - time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait)); - var secondaryTimeout = (req.dead !== null && - req.timeDead() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait)); - var requestCompletedWithServerError = (req.xhr.readyState == 4 && - (reqStatus < 1 || - reqStatus >= 500)); - if (primaryTimeout || secondaryTimeout || - requestCompletedWithServerError) { + var primaryTimeout = !isNaN(time_elapsed) && time_elapsed > Math.floor(Strophe.TIMEOUT * this.wait); + var secondaryTimeout = req.dead !== null && req.timeDead() > Math.floor(Strophe.SECONDARY_TIMEOUT * this.wait); + var requestCompletedWithServerError = req.xhr.readyState == 4 && (reqStatus < 1 || reqStatus >= 500); + if (primaryTimeout || secondaryTimeout || requestCompletedWithServerError) { if (secondaryTimeout) { - Strophe.error("Request " + - this._requests[i].id + - " timed out (secondary), restarting"); + Strophe.error("Request " + this._requests[i].id + " timed out (secondary), restarting"); } req.abort = true; req.xhr.abort(); // setting to null fails on IE6, so set to empty function - req.xhr.onreadystatechange = function () {}; - this._requests[i] = new Strophe.Request(req.xmlData, - req.origFunc, - req.rid, - req.sends); + req.xhr.onreadystatechange = function() {}; + this._requests[i] = new Strophe.Request(req.xmlData, req.origFunc, req.rid, req.sends); req = this._requests[i]; } - if (req.xhr.readyState === 0) { - Strophe.debug("request id " + req.id + - "." + req.sends + " posting"); - + Strophe.debug("request id " + req.id + "." + req.sends + " posting"); try { req.xhr.open("POST", this._conn.service, this._conn.options.sync ? false : true); } catch (e2) { Strophe.error("XHR open failed."); if (!this._conn.connected) { - this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, - "bad-service"); + this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, "bad-service"); } this._conn.disconnect(); return; } - // Fires the XHR request -- may be invoked immediately // or on a gradually expanding retry window for reconnects - var sendFunc = function () { + var sendFunc = function() { req.date = new Date(); - if (self._conn.options.customHeaders){ + if (self._conn.options.customHeaders) { var headers = self._conn.options.customHeaders; for (var header in headers) { if (headers.hasOwnProperty(header)) { @@ -4517,21 +3934,17 @@ Strophe.Bosh.prototype = { } req.xhr.send(req.data); }; - // Implement progressive backoff for reconnects -- // First retry (send == 1) should also be instantaneous if (req.sends > 1) { // Using a cube of the retry number creates a nicely // expanding retry window - var backoff = Math.min(Math.floor(Strophe.TIMEOUT * this.wait), - Math.pow(req.sends, 3)) * 1000; + var backoff = Math.min(Math.floor(Strophe.TIMEOUT * this.wait), Math.pow(req.sends, 3)) * 1e3; setTimeout(sendFunc, backoff); } else { sendFunc(); } - req.sends++; - if (this._conn.xmlOutput !== Strophe.Connection.prototype.xmlOutput) { if (req.xmlData.nodeName === this.strip && req.xmlData.childNodes.length) { this._conn.xmlOutput(req.xmlData.childNodes[0]); @@ -4543,52 +3956,40 @@ Strophe.Bosh.prototype = { this._conn.rawOutput(req.data); } } else { - Strophe.debug("_processRequest: " + - (i === 0 ? "first" : "second") + - " request has readyState of " + - req.xhr.readyState); + Strophe.debug("_processRequest: " + (i === 0 ? "first" : "second") + " request has readyState of " + req.xhr.readyState); } }, - /** PrivateFunction: _removeRequest * _Private_ function to remove a request from the queue. * * Parameters: * (Strophe.Request) req - The request to remove. */ - _removeRequest: function (req) - { + _removeRequest: function(req) { Strophe.debug("removing request"); - var i; for (i = this._requests.length - 1; i >= 0; i--) { if (req == this._requests[i]) { this._requests.splice(i, 1); } } - // IE6 fails on setting to null, so set to empty function - req.xhr.onreadystatechange = function () {}; - + req.xhr.onreadystatechange = function() {}; this._throttledRequestHandler(); }, - /** PrivateFunction: _restartRequest * _Private_ function to restart a request that is presumed dead. * * Parameters: * (Integer) i - The index of the request in the queue. */ - _restartRequest: function (i) - { + _restartRequest: function(i) { var req = this._requests[i]; if (req.dead === null) { req.dead = new Date(); } - this._processRequest(i); }, - /** PrivateFunction: _reqToData * _Private_ function to get a stanza out of a request. * @@ -4601,16 +4002,16 @@ Strophe.Bosh.prototype = { * Returns: * The stanza that was passed. */ - _reqToData: function (req) - { + _reqToData: function(req) { try { return req.getResponse(); } catch (e) { - if (e != "parsererror") { throw e; } + if (e != "parsererror") { + throw e; + } this._conn.disconnect("strophe-parsererror"); } }, - /** PrivateFunction: _sendTerminate * _Private_ function to send initial disconnect sequence. * @@ -4618,45 +4019,36 @@ Strophe.Bosh.prototype = { * the BOSH server a terminate body and includes an unavailable * presence if authentication has completed. */ - _sendTerminate: function (pres) - { + _sendTerminate: function(pres) { Strophe.info("_sendTerminate was called"); - var body = this._buildBody().attrs({type: "terminate"}); - + var body = this._buildBody().attrs({ + type: "terminate" + }); if (pres) { body.cnode(pres.tree()); } - - var req = new Strophe.Request(body.tree(), - this._onRequestStateChange.bind( - this, this._conn._dataRecv.bind(this._conn)), - body.tree().getAttribute("rid")); - + var req = new Strophe.Request(body.tree(), this._onRequestStateChange.bind(this, this._conn._dataRecv.bind(this._conn)), body.tree().getAttribute("rid")); this._requests.push(req); this._throttledRequestHandler(); }, - /** PrivateFunction: _send * _Private_ part of the Connection.send function for BOSH * * Just triggers the RequestHandler to send the messages that are in the queue */ - _send: function () { + _send: function() { clearTimeout(this._conn._idleTimeout); this._throttledRequestHandler(); this._conn._idleTimeout = setTimeout(this._conn._onIdle.bind(this._conn), 100); }, - /** PrivateFunction: _sendRestart * * Send an xmpp:restart stanza. */ - _sendRestart: function () - { + _sendRestart: function() { this._throttledRequestHandler(); clearTimeout(this._conn._idleTimeout); }, - /** PrivateFunction: _throttledRequestHandler * _Private_ function to throttle requests to the connection window. * @@ -4664,50 +4056,40 @@ Strophe.Bosh.prototype = { * request ids overflow the connection window in the case that one * request died. */ - _throttledRequestHandler: function () - { + _throttledRequestHandler: function() { if (!this._requests) { - Strophe.debug("_throttledRequestHandler called with " + - "undefined requests"); + Strophe.debug("_throttledRequestHandler called with " + "undefined requests"); } else { - Strophe.debug("_throttledRequestHandler called with " + - this._requests.length + " requests"); + Strophe.debug("_throttledRequestHandler called with " + this._requests.length + " requests"); } - if (!this._requests || this._requests.length === 0) { return; } - if (this._requests.length > 0) { this._processRequest(0); } - - if (this._requests.length > 1 && - Math.abs(this._requests[0].rid - - this._requests[1].rid) < this.window) { + if (this._requests.length > 1 && Math.abs(this._requests[0].rid - this._requests[1].rid) < this.window) { this._processRequest(1); } } }; + /* This program is distributed under the terms of the MIT license. Please see the LICENSE file for details. Copyright 2006-2008, OGG, LLC */ - /*global document, window, setTimeout, clearTimeout, console, XMLHttpRequest, ActiveXObject, Base64, MD5, Strophe, $build, $msg, $iq, $pres */ - /** Class: Strophe.WebSocket * _Private_ helper class that handles WebSocket Connections * * The Strophe.WebSocket class is used internally by Strophe.Connection * to encapsulate WebSocket sessions. It is not meant to be used from user's code. */ - /** File: websocket.js * A JavaScript library to enable XMPP over Websocket in Strophejs. * @@ -4719,7 +4101,6 @@ Strophe.Bosh.prototype = { * * WebSocket support implemented by Andreas Guth (andreas.guth@rwth-aachen.de) */ - /** PrivateConstructor: Strophe.Websocket * Create and initialize a Strophe.WebSocket object. * Currently only sets the connection Object. @@ -4733,27 +4114,22 @@ Strophe.Bosh.prototype = { Strophe.Websocket = function(connection) { this._conn = connection; this.strip = "stream:stream"; - var service = connection.service; if (service.indexOf("ws:") !== 0 && service.indexOf("wss:") !== 0) { // If the service is not an absolute URL, assume it is a path and put the absolute // URL together from options, current URL and the path. var new_service = ""; - if (connection.options.protocol === "ws" && window.location.protocol !== "https:") { new_service += "ws"; } else { new_service += "wss"; } - new_service += "://" + window.location.host; - if (service.indexOf("/") !== 0) { new_service += window.location.pathname + service; } else { new_service += service; } - connection.service = new_service; } }; @@ -4765,16 +4141,14 @@ Strophe.Websocket.prototype = { * Returns: * A Strophe.Builder with a element. */ - _buildStream: function () - { + _buildStream: function() { return $build("stream:stream", { - "to": this._conn.domain, - "xmlns": Strophe.NS.CLIENT, + to: this._conn.domain, + xmlns: Strophe.NS.CLIENT, "xmlns:stream": Strophe.NS.STREAM, - "version": '1.0' + version: "1.0" }); }, - /** PrivateFunction: _check_streamerror * _Private_ checks a message for stream:error * @@ -4784,69 +4158,59 @@ Strophe.Websocket.prototype = { * Returns: * true if there was a streamerror, false otherwise. */ - _check_streamerror: function (bodyWrap, connectstatus) { + _check_streamerror: function(bodyWrap, connectstatus) { var errors = bodyWrap.getElementsByTagName("stream:error"); if (errors.length === 0) { return false; } var error = errors[0]; - var condition = ""; var text = ""; - ns = "urn:ietf:params:xml:ns:xmpp-streams"; for (i = 0; i < error.childNodes.length; i++) { e = error.childNodes[i]; if (e.getAttribute("xmlns") !== ns) { break; - } if (e.nodeName === "text") { + } + if (e.nodeName === "text") { text = e.textContent; } else { condition = e.nodeName; } } - errorString = "WebSocket stream error: "; - if (condition) { errorString += condition; } else { errorString += "unknown"; } - if (text) { errorString += " - " + condition; } - Strophe.error(errorString); - // close the connection on stream_error this._conn._changeConnectStatus(connectstatus, condition); this._conn._doDisconnect(); return true; }, - /** PrivateFunction: _reset * Reset the connection. * * This function is called by the reset function of the Strophe Connection. * Is not needed by WebSockets. */ - _reset: function () - { + _reset: function() { return; }, - /** PrivateFunction: _connect * _Private_ function called by Strophe.Connection.connect * * Creates a WebSocket for a connection and assigns Callbacks to it. * Does nothing if there already is a WebSocket. */ - _connect: function () { + _connect: function() { // Ensure that there is no open WebSocket from a previous Connection. this._closeSocket(); - // Create the new WobSocket this.socket = new WebSocket(this._conn.service, "xmpp"); this.socket.onopen = this._onOpen.bind(this); @@ -4854,7 +4218,6 @@ Strophe.Websocket.prototype = { this.socket.onclose = this._onClose.bind(this); this.socket.onmessage = this._connect_cb_wrapper.bind(this); }, - /** PrivateFunction: _connect_cb * _Private_ function called by Strophe.Connection._connect_cb * @@ -4869,7 +4232,6 @@ Strophe.Websocket.prototype = { return Strophe.Status.CONNFAIL; } }, - /** PrivateFunction: _handleStreamStart * _Private_ function that checks the opening stream:stream tag for errors. * @@ -4887,30 +4249,25 @@ Strophe.Websocket.prototype = { } else if (ns !== Strophe.NS.CLIENT) { error = "Wrong xmlns in stream:stream: " + ns; } - var ns_stream = message.namespaceURI; if (typeof ns_stream !== "string") { error = "Missing xmlns:stream in stream:stream"; } else if (ns_stream !== Strophe.NS.STREAM) { error = "Wrong xmlns:stream in stream:stream: " + ns_stream; } - var ver = message.getAttribute("version"); if (typeof ver !== "string") { error = "Missing version in stream:stream"; } else if (ver !== "1.0") { error = "Wrong version in stream:stream: " + ver; } - if (error) { this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, error); this._conn._doDisconnect(); return false; } - return true; }, - /** PrivateFunction: _connect_cb_wrapper * _Private_ function that handles the first connection messages. * @@ -4921,21 +4278,16 @@ Strophe.Websocket.prototype = { if (message.data.indexOf("\s*)*/, ""); - if (data === '') return; - + if (data === "") return; //Make the initial stream:stream selfclosing to parse it without a SAX parser. data = message.data.replace(//, ""); - var streamStart = new DOMParser().parseFromString(data, "text/xml").documentElement; this._conn.xmlInput(streamStart); this._conn.rawInput(message.data); - //_handleStreamSteart will check for XML errors and disconnect on error if (this._handleStreamStart(streamStart)) { - //_connect_cb will check for stream:error and disconnect on error this._connect_cb(streamStart); - // ensure received stream:stream is NOT selfclosing and save it for following messages this.streamStart = message.data.replace(/^$/, ""); } @@ -4952,7 +4304,6 @@ Strophe.Websocket.prototype = { this._conn._connect_cb(elem, null, message.data); } }, - /** PrivateFunction: _disconnect * _Private_ function called by Strophe.Connection.disconnect * @@ -4961,13 +4312,12 @@ Strophe.Websocket.prototype = { * Parameters: * (Request) pres - This stanza will be sent before disconnecting. */ - _disconnect: function (pres) - { + _disconnect: function(pres) { if (this.socket.readyState !== WebSocket.CLOSED) { if (pres) { this._conn.send(pres); } - var close = ''; + var close = ""; this._conn.xmlOutput(document.createElement("stream:stream")); this._conn.rawOutput(close); try { @@ -4976,76 +4326,65 @@ Strophe.Websocket.prototype = { Strophe.info("Couldn't send closing stream tag."); } } - this._conn._doDisconnect(); }, - /** PrivateFunction: _doDisconnect * _Private_ function to disconnect. * * Just closes the Socket for WebSockets */ - _doDisconnect: function () - { + _doDisconnect: function() { Strophe.info("WebSockets _doDisconnect was called"); this._closeSocket(); }, - /** PrivateFunction _streamWrap * _Private_ helper function to wrap a stanza in a tag. * This is used so Strophe can process stanzas from WebSockets like BOSH */ - _streamWrap: function (stanza) - { - return this.streamStart + stanza + ''; + _streamWrap: function(stanza) { + return this.streamStart + stanza + ""; }, - - /** PrivateFunction: _closeSocket * _Private_ function to close the WebSocket. * * Closes the socket if it is still open and deletes it */ - _closeSocket: function () - { - if (this.socket) { try { - this.socket.close(); - } catch (e) {} } + _closeSocket: function() { + if (this.socket) { + try { + this.socket.close(); + } catch (e) {} + } this.socket = null; }, - /** PrivateFunction: _emptyQueue * _Private_ function to check if the message queue is empty. * * Returns: * True, because WebSocket messages are send immediately after queueing. */ - _emptyQueue: function () - { + _emptyQueue: function() { return true; }, - /** PrivateFunction: _onClose * _Private_ function to handle websockets closing. * * Nothing to do here for WebSockets */ _onClose: function(event) { - if(this._conn.connected && !this._conn.disconnecting) { + if (this._conn.connected && !this._conn.disconnecting) { Strophe.error("Websocket closed unexcectedly"); this._conn._doDisconnect(); } else { Strophe.info("Websocket closed"); } }, - /** PrivateFunction: _no_auth_received * * Called on stream start/restart when no stream:features * has been received. */ - _no_auth_received: function (_callback) - { + _no_auth_received: function(_callback) { Strophe.error("Server did not send any auth methods"); this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, "Server did not send any auth methods"); if (_callback) { @@ -5054,14 +4393,12 @@ Strophe.Websocket.prototype = { } this._conn._doDisconnect(); }, - /** PrivateFunction: _onDisconnectTimeout * _Private_ timeout handler for handling non-graceful disconnection. * * This does nothing for WebSockets */ - _onDisconnectTimeout: function () {}, - + _onDisconnectTimeout: function() {}, /** PrivateFunction: _onError * _Private_ function to handle websockets errors. * @@ -5073,13 +4410,12 @@ Strophe.Websocket.prototype = { this._conn._changeConnectStatus(Strophe.Status.CONNFAIL, "The WebSocket connection could not be established was disconnected."); this._disconnect(); }, - /** PrivateFunction: _onIdle * _Private_ function called by Strophe.Connection._onIdle * * sends all queued stanzas */ - _onIdle: function () { + _onIdle: function() { var data = this._conn._data; if (data.length > 0 && !this._conn.paused) { for (i = 0; i < data.length; i++) { @@ -5101,7 +4437,6 @@ Strophe.Websocket.prototype = { this._conn._data = []; } }, - /** PrivateFunction: _onMessage * _Private_ function to handle websockets messages. * @@ -5129,7 +4464,6 @@ Strophe.Websocket.prototype = { //Make the initial stream:stream selfclosing to parse it without a SAX parser. data = message.data.replace(//, ""); elem = new DOMParser().parseFromString(data, "text/xml").documentElement; - if (!this._handleStreamStart(elem)) { return; } @@ -5137,15 +4471,11 @@ Strophe.Websocket.prototype = { data = this._streamWrap(message.data); elem = new DOMParser().parseFromString(data, "text/xml").documentElement; } - if (this._check_streamerror(elem, Strophe.Status.ERROR)) { return; } - //handle unavailable presence stanza before disconnecting - if (this._conn.disconnecting && - elem.firstChild.nodeName === "presence" && - elem.firstChild.getAttribute("type") === "unavailable") { + if (this._conn.disconnecting && elem.firstChild.nodeName === "presence" && elem.firstChild.getAttribute("type") === "unavailable") { this._conn.xmlInput(elem); this._conn.rawInput(Strophe.serialize(elem)); // if we are already disconnecting we will ignore the unavailable stanza and @@ -5154,7 +4484,6 @@ Strophe.Websocket.prototype = { } this._conn._dataRecv(elem, message.data); }, - /** PrivateFunction: _onOpen * _Private_ function to handle websockets connection setup. * @@ -5164,12 +4493,10 @@ Strophe.Websocket.prototype = { Strophe.info("Websocket open"); var start = this._buildStream(); this._conn.xmlOutput(start.tree()); - var startString = this._removeClosingTag(start); this._conn.rawOutput(startString); this.socket.send(startString); }, - /** PrivateFunction: _removeClosingTag * _Private_ function to Make the first non-selfclosing * @@ -5184,7 +4511,6 @@ Strophe.Websocket.prototype = { string = string.replace(/<(stream:stream .*[^\/])\/>$/, "<$1>"); return string; }, - /** PrivateFunction: _reqToData * _Private_ function to get a stanza out of a request. * @@ -5196,26 +4522,22 @@ Strophe.Websocket.prototype = { * Returns: * The stanza that was passed. */ - _reqToData: function (stanza) - { + _reqToData: function(stanza) { return stanza; }, - /** PrivateFunction: _send * _Private_ part of the Connection.send function for WebSocket * * Just flushes the messages that are in the queue */ - _send: function () { + _send: function() { this._conn.flush(); }, - /** PrivateFunction: _sendRestart * * Send an xmpp:restart stanza. */ - _sendRestart: function () - { + _sendRestart: function() { clearTimeout(this._conn._idleTimeout); this._conn._onIdle.bind(this._conn)(); } @@ -5230,30 +4552,29 @@ Strophe.Websocket.prototype = { *Complete CoffeeScript rewrite: Andreas Guth */ - - (function() { - var Occupant, RoomConfig, XmppRoom, - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - Strophe.addConnectionPlugin('muc', { - _connection: null, - rooms: {}, - roomNames: [], - /*Function + var Occupant, RoomConfig, XmppRoom, __bind = function(fn, me) { + return function() { + return fn.apply(me, arguments); + }; + }; + Strophe.addConnectionPlugin("muc", { + _connection: null, + rooms: {}, + roomNames: [], + /*Function Initialize the MUC plugin. Sets the correct connection object and extends the namesace. */ - - init: function(conn) { - this._connection = conn; - this._muc_handler = null; - Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC + "#owner"); - Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin"); - Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user"); - return Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig"); - }, - /*Function + init: function(conn) { + this._connection = conn; + this._muc_handler = null; + Strophe.addNamespace("MUC_OWNER", Strophe.NS.MUC + "#owner"); + Strophe.addNamespace("MUC_ADMIN", Strophe.NS.MUC + "#admin"); + Strophe.addNamespace("MUC_USER", Strophe.NS.MUC + "#user"); + return Strophe.addNamespace("MUC_ROOMCONF", Strophe.NS.MUC + "#roomconfig"); + }, + /*Function Join a multi-user chat room Parameters: (String) room - The multi-user chat room to join. @@ -5268,79 +4589,77 @@ Strophe.Websocket.prototype = { (Object) history_attrs - Optional attributes for retrieving history (XML DOM Element) extended_presence - Optional XML for extending presence */ - - join: function(room, nick, msg_handler_cb, pres_handler_cb, roster_cb, password, history_attrs) { - var msg, room_nick, - _this = this; - room_nick = this.test_append_nick(room, nick); - msg = $pres({ - from: this._connection.jid, - to: room_nick - }).c("x", { - xmlns: Strophe.NS.MUC - }); - if (history_attrs != null) { - msg = msg.c("history", history_attrs).up; - } - if (password != null) { - msg.cnode(Strophe.xmlElement("password", [], password)); - } - if (typeof extended_presence !== "undefined" && extended_presence !== null) { - msg.up.cnode(extended_presence); - } - if (this._muc_handler == null) { - this._muc_handler = this._connection.addHandler(function(stanza) { - var from, handler, handlers, id, roomname, x, xmlns, xquery, _i, _len; - from = stanza.getAttribute('from'); - if (!from) { - return true; - } - roomname = from.split("/")[0]; - if (!_this.rooms[roomname]) { - return true; - } - room = _this.rooms[roomname]; - handlers = {}; - if (stanza.nodeName === "message") { - handlers = room._message_handlers; - } else if (stanza.nodeName === "presence") { - xquery = stanza.getElementsByTagName("x"); - if (xquery.length > 0) { - for (_i = 0, _len = xquery.length; _i < _len; _i++) { - x = xquery[_i]; - xmlns = x.getAttribute("xmlns"); - if (xmlns && xmlns.match(Strophe.NS.MUC)) { - handlers = room._presence_handlers; - break; - } - } + join: function(room, nick, msg_handler_cb, pres_handler_cb, roster_cb, password, history_attrs) { + var msg, room_nick, _this = this; + room_nick = this.test_append_nick(room, nick); + msg = $pres({ + from: this._connection.jid, + to: room_nick + }).c("x", { + xmlns: Strophe.NS.MUC + }); + if (history_attrs != null) { + msg = msg.c("history", history_attrs).up; } - } - for (id in handlers) { - handler = handlers[id]; - if (!handler(stanza, room)) { - delete handlers[id]; + if (password != null) { + msg.cnode(Strophe.xmlElement("password", [], password)); } - } - return true; - }); - } - if (!this.rooms.hasOwnProperty(room)) { - this.rooms[room] = new XmppRoom(this, room, nick, password); - this.roomNames.push(room); - } - if (pres_handler_cb) { - this.rooms[room].addHandler('presence', pres_handler_cb); - } - if (msg_handler_cb) { - this.rooms[room].addHandler('message', msg_handler_cb); - } - if (roster_cb) { - this.rooms[room].addHandler('roster', roster_cb); - } - return this._connection.send(msg); - }, - /*Function + if (typeof extended_presence !== "undefined" && extended_presence !== null) { + msg.up.cnode(extended_presence); + } + if (this._muc_handler == null) { + this._muc_handler = this._connection.addHandler(function(stanza) { + var from, handler, handlers, id, roomname, x, xmlns, xquery, _i, _len; + from = stanza.getAttribute("from"); + if (!from) { + return true; + } + roomname = from.split("/")[0]; + if (!_this.rooms[roomname]) { + return true; + } + room = _this.rooms[roomname]; + handlers = {}; + if (stanza.nodeName === "message") { + handlers = room._message_handlers; + } else if (stanza.nodeName === "presence") { + xquery = stanza.getElementsByTagName("x"); + if (xquery.length > 0) { + for (_i = 0, _len = xquery.length; _i < _len; _i++) { + x = xquery[_i]; + xmlns = x.getAttribute("xmlns"); + if (xmlns && xmlns.match(Strophe.NS.MUC)) { + handlers = room._presence_handlers; + break; + } + } + } + } + for (id in handlers) { + handler = handlers[id]; + if (!handler(stanza, room)) { + delete handlers[id]; + } + } + return true; + }); + } + if (!this.rooms.hasOwnProperty(room)) { + this.rooms[room] = new XmppRoom(this, room, nick, password); + this.roomNames.push(room); + } + if (pres_handler_cb) { + this.rooms[room].addHandler("presence", pres_handler_cb); + } + if (msg_handler_cb) { + this.rooms[room].addHandler("message", msg_handler_cb); + } + if (roster_cb) { + this.rooms[room].addHandler("roster", roster_cb); + } + return this._connection.send(msg); + }, + /*Function Leave a multi-user chat room Parameters: (String) room - The multi-user chat room to leave. @@ -5350,36 +4669,35 @@ Strophe.Websocket.prototype = { Returns: iqid - The unique id for the room leave. */ - - leave: function(room, nick, handler_cb, exit_msg) { - var id, presence, presenceid, room_nick; - id = this.roomNames.indexOf(room); - delete this.rooms[room]; - if (id >= 0) { - this.roomNames.splice(id, 1); - if (this.roomNames.length === 0) { - this._connection.deleteHandler(this._muc_handler); - this._muc_handler = null; - } - } - room_nick = this.test_append_nick(room, nick); - presenceid = this._connection.getUniqueId(); - presence = $pres({ - type: "unavailable", - id: presenceid, - from: this._connection.jid, - to: room_nick - }); - if (exit_msg != null) { - presence.c("status", exit_msg); - } - if (handler_cb != null) { - this._connection.addHandler(handler_cb, null, "presence", null, presenceid); - } - this._connection.send(presence); - return presenceid; - }, - /*Function + leave: function(room, nick, handler_cb, exit_msg) { + var id, presence, presenceid, room_nick; + id = this.roomNames.indexOf(room); + delete this.rooms[room]; + if (id >= 0) { + this.roomNames.splice(id, 1); + if (this.roomNames.length === 0) { + this._connection.deleteHandler(this._muc_handler); + this._muc_handler = null; + } + } + room_nick = this.test_append_nick(room, nick); + presenceid = this._connection.getUniqueId(); + presence = $pres({ + type: "unavailable", + id: presenceid, + from: this._connection.jid, + to: room_nick + }); + if (exit_msg != null) { + presence.c("status", exit_msg); + } + if (handler_cb != null) { + this._connection.addHandler(handler_cb, null, "presence", null, presenceid); + } + this._connection.send(presence); + return presenceid; + }, + /*Function Parameters: (String) room - The multi-user chat room name. (String) nick - The nick name used in the chat room. @@ -5390,42 +4708,41 @@ Strophe.Websocket.prototype = { Returns: msgiq - the unique id used to send the message */ - - message: function(room, nick, message, html_message, type) { - var msg, msgid, parent, room_nick; - room_nick = this.test_append_nick(room, nick); - type = type || (nick != null ? "chat" : "groupchat"); - msgid = this._connection.getUniqueId(); - msg = $msg({ - to: room_nick, - from: this._connection.jid, - type: type, - id: msgid - }).c("body", { - xmlns: Strophe.NS.CLIENT - }).t(message); - msg.up(); - if (html_message != null) { - msg.c("html", { - xmlns: Strophe.NS.XHTML_IM - }).c("body", { - xmlns: Strophe.NS.XHTML - }).t(html_message); - if (msg.node.childNodes.length === 0) { - parent = msg.node.parentNode; - msg.up().up(); - msg.node.removeChild(parent); - } else { - msg.up().up(); - } - } - msg.c("x", { - xmlns: "jabber:x:event" - }).c("composing"); - this._connection.send(msg); - return msgid; - }, - /*Function + message: function(room, nick, message, html_message, type) { + var msg, msgid, parent, room_nick; + room_nick = this.test_append_nick(room, nick); + type = type || (nick != null ? "chat" : "groupchat"); + msgid = this._connection.getUniqueId(); + msg = $msg({ + to: room_nick, + from: this._connection.jid, + type: type, + id: msgid + }).c("body", { + xmlns: Strophe.NS.CLIENT + }).t(message); + msg.up(); + if (html_message != null) { + msg.c("html", { + xmlns: Strophe.NS.XHTML_IM + }).c("body", { + xmlns: Strophe.NS.XHTML + }).t(html_message); + if (msg.node.childNodes.length === 0) { + parent = msg.node.parentNode; + msg.up().up(); + msg.node.removeChild(parent); + } else { + msg.up().up(); + } + } + msg.c("x", { + xmlns: "jabber:x:event" + }).c("composing"); + this._connection.send(msg); + return msgid; + }, + /*Function Convenience Function to send a Message to all Occupants Parameters: (String) room - The multi-user chat room name. @@ -5434,11 +4751,10 @@ Strophe.Websocket.prototype = { Returns: msgiq - the unique id used to send the message */ - - groupchat: function(room, message, html_message) { - return this.message(room, null, message, html_message); - }, - /*Function + groupchat: function(room, message, html_message) { + return this.message(room, null, message, html_message); + }, + /*Function Send a mediated invitation. Parameters: (String) room - The multi-user chat room name. @@ -5447,26 +4763,25 @@ Strophe.Websocket.prototype = { Returns: msgiq - the unique id used to send the invitation */ - - invite: function(room, receiver, reason) { - var invitation, msgid; - msgid = this._connection.getUniqueId(); - invitation = $msg({ - from: this._connection.jid, - to: room, - id: msgid - }).c('x', { - xmlns: Strophe.NS.MUC_USER - }).c('invite', { - to: receiver - }); - if (reason != null) { - invitation.c('reason', reason); - } - this._connection.send(invitation); - return msgid; - }, - /*Function + invite: function(room, receiver, reason) { + var invitation, msgid; + msgid = this._connection.getUniqueId(); + invitation = $msg({ + from: this._connection.jid, + to: room, + id: msgid + }).c("x", { + xmlns: Strophe.NS.MUC_USER + }).c("invite", { + to: receiver + }); + if (reason != null) { + invitation.c("reason", reason); + } + this._connection.send(invitation); + return msgid; + }, + /*Function Send a direct invitation. Parameters: (String) room - The multi-user chat room name. @@ -5476,29 +4791,28 @@ Strophe.Websocket.prototype = { Returns: msgiq - the unique id used to send the invitation */ - - directInvite: function(room, receiver, reason, password) { - var attrs, invitation, msgid; - msgid = this._connection.getUniqueId(); - attrs = { - xmlns: 'jabber:x:conference', - jid: room - }; - if (reason != null) { - attrs.reason = reason; - } - if (password != null) { - attrs.password = password; - } - invitation = $msg({ - from: this._connection.jid, - to: receiver, - id: msgid - }).c('x', attrs); - this._connection.send(invitation); - return msgid; - }, - /*Function + directInvite: function(room, receiver, reason, password) { + var attrs, invitation, msgid; + msgid = this._connection.getUniqueId(); + attrs = { + xmlns: "jabber:x:conference", + jid: room + }; + if (reason != null) { + attrs.reason = reason; + } + if (password != null) { + attrs.password = password; + } + invitation = $msg({ + from: this._connection.jid, + to: receiver, + id: msgid + }).c("x", attrs); + this._connection.send(invitation); + return msgid; + }, + /*Function Queries a room for a list of occupants (String) room - The multi-user chat room name. (Function) success_cb - Optional function to handle the info. @@ -5506,20 +4820,19 @@ Strophe.Websocket.prototype = { Returns: id - the unique id used to send the info request */ - - queryOccupants: function(room, success_cb, error_cb) { - var attrs, info; - attrs = { - xmlns: Strophe.NS.DISCO_ITEMS - }; - info = $iq({ - from: this._connection.jid, - to: room, - type: 'get' - }).c('query', attrs); - return this._connection.sendIQ(info, success_cb, error_cb); - }, - /*Function + queryOccupants: function(room, success_cb, error_cb) { + var attrs, info; + attrs = { + xmlns: Strophe.NS.DISCO_ITEMS + }; + info = $iq({ + from: this._connection.jid, + to: room, + type: "get" + }).c("query", attrs); + return this._connection.sendIQ(info, success_cb, error_cb); + }, + /*Function Start a room configuration. Parameters: (String) room - The multi-user chat room name. @@ -5527,41 +4840,39 @@ Strophe.Websocket.prototype = { Returns: id - the unique id used to send the configuration request */ - - configure: function(room, handler_cb, error_cb) { - var config, stanza; - config = $iq({ - to: room, - type: "get" - }).c("query", { - xmlns: Strophe.NS.MUC_OWNER - }); - stanza = config.tree(); - return this._connection.sendIQ(stanza, handler_cb, error_cb); - }, - /*Function + configure: function(room, handler_cb, error_cb) { + var config, stanza; + config = $iq({ + to: room, + type: "get" + }).c("query", { + xmlns: Strophe.NS.MUC_OWNER + }); + stanza = config.tree(); + return this._connection.sendIQ(stanza, handler_cb, error_cb); + }, + /*Function Cancel the room configuration Parameters: (String) room - The multi-user chat room name. Returns: id - the unique id used to cancel the configuration. */ - - cancelConfigure: function(room) { - var config, stanza; - config = $iq({ - to: room, - type: "set" - }).c("query", { - xmlns: Strophe.NS.MUC_OWNER - }).c("x", { - xmlns: "jabber:x:data", - type: "cancel" - }); - stanza = config.tree(); - return this._connection.sendIQ(stanza); - }, - /*Function + cancelConfigure: function(room) { + var config, stanza; + config = $iq({ + to: room, + type: "set" + }).c("query", { + xmlns: Strophe.NS.MUC_OWNER + }).c("x", { + xmlns: "jabber:x:data", + type: "cancel" + }); + stanza = config.tree(); + return this._connection.sendIQ(stanza); + }, + /*Function Save a room configuration. Parameters: (String) room - The multi-user chat room name. @@ -5569,70 +4880,67 @@ Strophe.Websocket.prototype = { Returns: id - the unique id used to save the configuration. */ - - saveConfiguration: function(room, config, success_cb, error_cb) { - var conf, iq, stanza, _i, _len; - iq = $iq({ - to: room, - type: "set" - }).c("query", { - xmlns: Strophe.NS.MUC_OWNER - }); - if (typeof Form !== "undefined" && config instanceof Form) { - config.type = "submit"; - iq.cnode(config.toXML()); - } else { - iq.c("x", { - xmlns: "jabber:x:data", - type: "submit" - }); - for (_i = 0, _len = config.length; _i < _len; _i++) { - conf = config[_i]; - iq.cnode(conf).up(); - } - } - stanza = iq.tree(); - return this._connection.sendIQ(stanza, success_cb, error_cb); - }, - /*Function + saveConfiguration: function(room, config, success_cb, error_cb) { + var conf, iq, stanza, _i, _len; + iq = $iq({ + to: room, + type: "set" + }).c("query", { + xmlns: Strophe.NS.MUC_OWNER + }); + if (typeof Form !== "undefined" && config instanceof Form) { + config.type = "submit"; + iq.cnode(config.toXML()); + } else { + iq.c("x", { + xmlns: "jabber:x:data", + type: "submit" + }); + for (_i = 0, _len = config.length; _i < _len; _i++) { + conf = config[_i]; + iq.cnode(conf).up(); + } + } + stanza = iq.tree(); + return this._connection.sendIQ(stanza, success_cb, error_cb); + }, + /*Function Parameters: (String) room - The multi-user chat room name. Returns: id - the unique id used to create the chat room. */ - - createInstantRoom: function(room, success_cb, error_cb) { - var roomiq; - roomiq = $iq({ - to: room, - type: "set" - }).c("query", { - xmlns: Strophe.NS.MUC_OWNER - }).c("x", { - xmlns: "jabber:x:data", - type: "submit" - }); - return this._connection.sendIQ(roomiq.tree(), success_cb, error_cb); - }, - /*Function + createInstantRoom: function(room, success_cb, error_cb) { + var roomiq; + roomiq = $iq({ + to: room, + type: "set" + }).c("query", { + xmlns: Strophe.NS.MUC_OWNER + }).c("x", { + xmlns: "jabber:x:data", + type: "submit" + }); + return this._connection.sendIQ(roomiq.tree(), success_cb, error_cb); + }, + /*Function Set the topic of the chat room. Parameters: (String) room - The multi-user chat room name. (String) topic - Topic message. */ - - setTopic: function(room, topic) { - var msg; - msg = $msg({ - to: room, - from: this._connection.jid, - type: "groupchat" - }).c("subject", { - xmlns: "jabber:client" - }).t(topic); - return this._connection.send(msg.tree()); - }, - /*Function + setTopic: function(room, topic) { + var msg; + msg = $msg({ + to: room, + from: this._connection.jid, + type: "groupchat" + }).c("subject", { + xmlns: "jabber:client" + }).t(topic); + return this._connection.send(msg.tree()); + }, + /*Function Internal Function that Changes the role or affiliation of a member of a MUC room. This function is used by modifyRole and modifyAffiliation. The modification can only be done by a room moderator. An error will be @@ -5646,21 +4954,20 @@ Strophe.Websocket.prototype = { Returns: iq - the id of the mode change request. */ - - _modifyPrivilege: function(room, item, reason, handler_cb, error_cb) { - var iq; - iq = $iq({ - to: room, - type: "set" - }).c("query", { - xmlns: Strophe.NS.MUC_ADMIN - }).cnode(item.node); - if (reason != null) { - iq.c("reason", reason); - } - return this._connection.sendIQ(iq.tree(), handler_cb, error_cb); - }, - /*Function + _modifyPrivilege: function(room, item, reason, handler_cb, error_cb) { + var iq; + iq = $iq({ + to: room, + type: "set" + }).c("query", { + xmlns: Strophe.NS.MUC_ADMIN + }).cnode(item.node); + if (reason != null) { + iq.c("reason", reason); + } + return this._connection.sendIQ(iq.tree(), handler_cb, error_cb); + }, + /*Function Changes the role of a member of a MUC room. The modification can only be done by a room moderator. An error will be returned if the user doesn't have permission. @@ -5675,31 +4982,30 @@ Strophe.Websocket.prototype = { Returns: iq - the id of the mode change request. */ - - modifyRole: function(room, nick, role, reason, handler_cb, error_cb) { - var item; - item = $build("item", { - nick: nick, - role: role - }); - return this._modifyPrivilege(room, item, reason, handler_cb, error_cb); - }, - kick: function(room, nick, reason, handler_cb, error_cb) { - return this.modifyRole(room, nick, 'none', reason, handler_cb, error_cb); - }, - voice: function(room, nick, reason, handler_cb, error_cb) { - return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb); - }, - mute: function(room, nick, reason, handler_cb, error_cb) { - return this.modifyRole(room, nick, 'visitor', reason, handler_cb, error_cb); - }, - op: function(room, nick, reason, handler_cb, error_cb) { - return this.modifyRole(room, nick, 'moderator', reason, handler_cb, error_cb); - }, - deop: function(room, nick, reason, handler_cb, error_cb) { - return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb); - }, - /*Function + modifyRole: function(room, nick, role, reason, handler_cb, error_cb) { + var item; + item = $build("item", { + nick: nick, + role: role + }); + return this._modifyPrivilege(room, item, reason, handler_cb, error_cb); + }, + kick: function(room, nick, reason, handler_cb, error_cb) { + return this.modifyRole(room, nick, "none", reason, handler_cb, error_cb); + }, + voice: function(room, nick, reason, handler_cb, error_cb) { + return this.modifyRole(room, nick, "participant", reason, handler_cb, error_cb); + }, + mute: function(room, nick, reason, handler_cb, error_cb) { + return this.modifyRole(room, nick, "visitor", reason, handler_cb, error_cb); + }, + op: function(room, nick, reason, handler_cb, error_cb) { + return this.modifyRole(room, nick, "moderator", reason, handler_cb, error_cb); + }, + deop: function(room, nick, reason, handler_cb, error_cb) { + return this.modifyRole(room, nick, "participant", reason, handler_cb, error_cb); + }, + /*Function Changes the affiliation of a member of a MUC room. The modification can only be done by a room moderator. An error will be returned if the user doesn't have permission. @@ -5713,48 +5019,46 @@ Strophe.Websocket.prototype = { Returns: iq - the id of the mode change request. */ - - modifyAffiliation: function(room, jid, affiliation, reason, handler_cb, error_cb) { - var item; - item = $build("item", { - jid: jid, - affiliation: affiliation - }); - return this._modifyPrivilege(room, item, reason, handler_cb, error_cb); - }, - ban: function(room, jid, reason, handler_cb, error_cb) { - return this.modifyAffiliation(room, jid, 'outcast', reason, handler_cb, error_cb); - }, - member: function(room, jid, reason, handler_cb, error_cb) { - return this.modifyAffiliation(room, jid, 'member', reason, handler_cb, error_cb); - }, - revoke: function(room, jid, reason, handler_cb, error_cb) { - return this.modifyAffiliation(room, jid, 'none', reason, handler_cb, error_cb); - }, - owner: function(room, jid, reason, handler_cb, error_cb) { - return this.modifyAffiliation(room, jid, 'owner', reason, handler_cb, error_cb); - }, - admin: function(room, jid, reason, handler_cb, error_cb) { - return this.modifyAffiliation(room, jid, 'admin', reason, handler_cb, error_cb); - }, - /*Function + modifyAffiliation: function(room, jid, affiliation, reason, handler_cb, error_cb) { + var item; + item = $build("item", { + jid: jid, + affiliation: affiliation + }); + return this._modifyPrivilege(room, item, reason, handler_cb, error_cb); + }, + ban: function(room, jid, reason, handler_cb, error_cb) { + return this.modifyAffiliation(room, jid, "outcast", reason, handler_cb, error_cb); + }, + member: function(room, jid, reason, handler_cb, error_cb) { + return this.modifyAffiliation(room, jid, "member", reason, handler_cb, error_cb); + }, + revoke: function(room, jid, reason, handler_cb, error_cb) { + return this.modifyAffiliation(room, jid, "none", reason, handler_cb, error_cb); + }, + owner: function(room, jid, reason, handler_cb, error_cb) { + return this.modifyAffiliation(room, jid, "owner", reason, handler_cb, error_cb); + }, + admin: function(room, jid, reason, handler_cb, error_cb) { + return this.modifyAffiliation(room, jid, "admin", reason, handler_cb, error_cb); + }, + /*Function Change the current users nick name. Parameters: (String) room - The multi-user chat room name. (String) user - The new nick name. */ - - changeNick: function(room, user) { - var presence, room_nick; - room_nick = this.test_append_nick(room, user); - presence = $pres({ - from: this._connection.jid, - to: room_nick, - id: this._connection.getUniqueId() - }); - return this._connection.send(presence.tree()); - }, - /*Function + changeNick: function(room, user) { + var presence, room_nick; + room_nick = this.test_append_nick(room, user); + presence = $pres({ + from: this._connection.jid, + to: room_nick, + id: this._connection.getUniqueId() + }); + return this._connection.send(presence.tree()); + }, + /*Function Change the current users status. Parameters: (String) room - The multi-user chat room name. @@ -5762,169 +5066,140 @@ Strophe.Websocket.prototype = { (String) show - The new show-text. (String) status - The new status-text. */ - - setStatus: function(room, user, show, status) { - var presence, room_nick; - room_nick = this.test_append_nick(room, user); - presence = $pres({ - from: this._connection.jid, - to: room_nick - }); - if (show != null) { - presence.c('show', show).up(); - } - if (status != null) { - presence.c('status', status); - } - return this._connection.send(presence.tree()); - }, - /*Function + setStatus: function(room, user, show, status) { + var presence, room_nick; + room_nick = this.test_append_nick(room, user); + presence = $pres({ + from: this._connection.jid, + to: room_nick + }); + if (show != null) { + presence.c("show", show).up(); + } + if (status != null) { + presence.c("status", status); + } + return this._connection.send(presence.tree()); + }, + /*Function List all chat room available on a server. Parameters: (String) server - name of chat server. (String) handle_cb - Function to call for room list return. (String) error_cb - Function to call on error. */ - - listRooms: function(server, handle_cb, error_cb) { - var iq; - iq = $iq({ - to: server, - from: this._connection.jid, - type: "get" - }).c("query", { - xmlns: Strophe.NS.DISCO_ITEMS - }); - return this._connection.sendIQ(iq, handle_cb, error_cb); - }, - test_append_nick: function(room, nick) { - return room + (nick != null ? "/" + (Strophe.escapeNode(nick)) : ""); - } - }); - - XmppRoom = (function() { - function XmppRoom(client, name, nick, password) { - this.client = client; - this.name = name; - this.nick = nick; - this.password = password; - this._roomRosterHandler = __bind(this._roomRosterHandler, this); - this._addOccupant = __bind(this._addOccupant, this); - this.roster = {}; - this._message_handlers = {}; - this._presence_handlers = {}; - this._roster_handlers = {}; - this._handler_ids = 0; - if (client.muc) { - this.client = client.muc; - } - this.name = Strophe.getBareJidFromJid(name); - this.addHandler('presence', this._roomRosterHandler); - } - - XmppRoom.prototype.join = function(msg_handler_cb, pres_handler_cb, roster_cb) { - return this.client.join(this.name, this.nick, msg_handler_cb, pres_handler_cb, roster_cb, this.password); - }; - - XmppRoom.prototype.leave = function(handler_cb, message) { - this.client.leave(this.name, this.nick, handler_cb, message); - return delete this.client.rooms[this.name]; - }; - - XmppRoom.prototype.message = function(nick, message, html_message, type) { - return this.client.message(this.name, nick, message, html_message, type); - }; - - XmppRoom.prototype.groupchat = function(message, html_message) { - return this.client.groupchat(this.name, message, html_message); - }; - - XmppRoom.prototype.invite = function(receiver, reason) { - return this.client.invite(this.name, receiver, reason); - }; - - XmppRoom.prototype.directInvite = function(receiver, reason) { - return this.client.directInvite(this.name, receiver, reason, this.password); - }; - - XmppRoom.prototype.configure = function(handler_cb) { - return this.client.configure(this.name, handler_cb); - }; - - XmppRoom.prototype.cancelConfigure = function() { - return this.client.cancelConfigure(this.name); - }; - - XmppRoom.prototype.saveConfiguration = function(config) { - return this.client.saveConfiguration(this.name, config); - }; - - XmppRoom.prototype.queryOccupants = function(success_cb, error_cb) { - return this.client.queryOccupants(this.name, success_cb, error_cb); - }; - - XmppRoom.prototype.setTopic = function(topic) { - return this.client.setTopic(this.name, topic); - }; - - XmppRoom.prototype.modifyRole = function(nick, role, reason, success_cb, error_cb) { - return this.client.modifyRole(this.name, nick, role, reason, success_cb, error_cb); - }; - - XmppRoom.prototype.kick = function(nick, reason, handler_cb, error_cb) { - return this.client.kick(this.name, nick, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.voice = function(nick, reason, handler_cb, error_cb) { - return this.client.voice(this.name, nick, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.mute = function(nick, reason, handler_cb, error_cb) { - return this.client.mute(this.name, nick, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.op = function(nick, reason, handler_cb, error_cb) { - return this.client.op(this.name, nick, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.deop = function(nick, reason, handler_cb, error_cb) { - return this.client.deop(this.name, nick, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.modifyAffiliation = function(jid, affiliation, reason, success_cb, error_cb) { - return this.client.modifyAffiliation(this.name, jid, affiliation, reason, success_cb, error_cb); - }; - - XmppRoom.prototype.ban = function(jid, reason, handler_cb, error_cb) { - return this.client.ban(this.name, jid, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.member = function(jid, reason, handler_cb, error_cb) { - return this.client.member(this.name, jid, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.revoke = function(jid, reason, handler_cb, error_cb) { - return this.client.revoke(this.name, jid, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.owner = function(jid, reason, handler_cb, error_cb) { - return this.client.owner(this.name, jid, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.admin = function(jid, reason, handler_cb, error_cb) { - return this.client.admin(this.name, jid, reason, handler_cb, error_cb); - }; - - XmppRoom.prototype.changeNick = function(nick) { - this.nick = nick; - return this.client.changeNick(this.name, nick); - }; - - XmppRoom.prototype.setStatus = function(show, status) { - return this.client.setStatus(this.name, this.nick, show, status); - }; - - /*Function + listRooms: function(server, handle_cb, error_cb) { + var iq; + iq = $iq({ + to: server, + from: this._connection.jid, + type: "get" + }).c("query", { + xmlns: Strophe.NS.DISCO_ITEMS + }); + return this._connection.sendIQ(iq, handle_cb, error_cb); + }, + test_append_nick: function(room, nick) { + return room + (nick != null ? "/" + Strophe.escapeNode(nick) : ""); + } + }); + XmppRoom = function() { + function XmppRoom(client, name, nick, password) { + this.client = client; + this.name = name; + this.nick = nick; + this.password = password; + this._roomRosterHandler = __bind(this._roomRosterHandler, this); + this._addOccupant = __bind(this._addOccupant, this); + this.roster = {}; + this._message_handlers = {}; + this._presence_handlers = {}; + this._roster_handlers = {}; + this._handler_ids = 0; + if (client.muc) { + this.client = client.muc; + } + this.name = Strophe.getBareJidFromJid(name); + this.addHandler("presence", this._roomRosterHandler); + } + XmppRoom.prototype.join = function(msg_handler_cb, pres_handler_cb, roster_cb) { + return this.client.join(this.name, this.nick, msg_handler_cb, pres_handler_cb, roster_cb, this.password); + }; + XmppRoom.prototype.leave = function(handler_cb, message) { + this.client.leave(this.name, this.nick, handler_cb, message); + return delete this.client.rooms[this.name]; + }; + XmppRoom.prototype.message = function(nick, message, html_message, type) { + return this.client.message(this.name, nick, message, html_message, type); + }; + XmppRoom.prototype.groupchat = function(message, html_message) { + return this.client.groupchat(this.name, message, html_message); + }; + XmppRoom.prototype.invite = function(receiver, reason) { + return this.client.invite(this.name, receiver, reason); + }; + XmppRoom.prototype.directInvite = function(receiver, reason) { + return this.client.directInvite(this.name, receiver, reason, this.password); + }; + XmppRoom.prototype.configure = function(handler_cb) { + return this.client.configure(this.name, handler_cb); + }; + XmppRoom.prototype.cancelConfigure = function() { + return this.client.cancelConfigure(this.name); + }; + XmppRoom.prototype.saveConfiguration = function(config) { + return this.client.saveConfiguration(this.name, config); + }; + XmppRoom.prototype.queryOccupants = function(success_cb, error_cb) { + return this.client.queryOccupants(this.name, success_cb, error_cb); + }; + XmppRoom.prototype.setTopic = function(topic) { + return this.client.setTopic(this.name, topic); + }; + XmppRoom.prototype.modifyRole = function(nick, role, reason, success_cb, error_cb) { + return this.client.modifyRole(this.name, nick, role, reason, success_cb, error_cb); + }; + XmppRoom.prototype.kick = function(nick, reason, handler_cb, error_cb) { + return this.client.kick(this.name, nick, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.voice = function(nick, reason, handler_cb, error_cb) { + return this.client.voice(this.name, nick, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.mute = function(nick, reason, handler_cb, error_cb) { + return this.client.mute(this.name, nick, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.op = function(nick, reason, handler_cb, error_cb) { + return this.client.op(this.name, nick, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.deop = function(nick, reason, handler_cb, error_cb) { + return this.client.deop(this.name, nick, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.modifyAffiliation = function(jid, affiliation, reason, success_cb, error_cb) { + return this.client.modifyAffiliation(this.name, jid, affiliation, reason, success_cb, error_cb); + }; + XmppRoom.prototype.ban = function(jid, reason, handler_cb, error_cb) { + return this.client.ban(this.name, jid, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.member = function(jid, reason, handler_cb, error_cb) { + return this.client.member(this.name, jid, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.revoke = function(jid, reason, handler_cb, error_cb) { + return this.client.revoke(this.name, jid, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.owner = function(jid, reason, handler_cb, error_cb) { + return this.client.owner(this.name, jid, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.admin = function(jid, reason, handler_cb, error_cb) { + return this.client.admin(this.name, jid, reason, handler_cb, error_cb); + }; + XmppRoom.prototype.changeNick = function(nick) { + this.nick = nick; + return this.client.changeNick(this.name, nick); + }; + XmppRoom.prototype.setStatus = function(show, status) { + return this.client.setStatus(this.name, this.nick, show, status); + }; + /*Function Adds a handler to the MUC room. Parameters: (String) handler_type - 'message', 'presence' or 'roster'. @@ -5932,29 +5207,29 @@ Strophe.Websocket.prototype = { Returns: id - the id of handler. */ + XmppRoom.prototype.addHandler = function(handler_type, handler) { + var id; + id = this._handler_ids++; + switch (handler_type) { + case "presence": + this._presence_handlers[id] = handler; + break; + case "message": + this._message_handlers[id] = handler; + break; - XmppRoom.prototype.addHandler = function(handler_type, handler) { - var id; - id = this._handler_ids++; - switch (handler_type) { - case 'presence': - this._presence_handlers[id] = handler; - break; - case 'message': - this._message_handlers[id] = handler; - break; - case 'roster': - this._roster_handlers[id] = handler; - break; - default: - this._handler_ids--; - return null; - } - return id; - }; + case "roster": + this._roster_handlers[id] = handler; + break; - /*Function + default: + this._handler_ids--; + return null; + } + return id; + }; + /*Function Removes a handler from the MUC room. This function takes ONLY ids returned by the addHandler function of this room. passing handler ids returned by connection.addHandler @@ -5962,303 +5237,273 @@ Strophe.Websocket.prototype = { Parameters: (number) id - the id of the handler */ - - - XmppRoom.prototype.removeHandler = function(id) { - delete this._presence_handlers[id]; - delete this._message_handlers[id]; - return delete this._roster_handlers[id]; - }; - - /*Function + XmppRoom.prototype.removeHandler = function(id) { + delete this._presence_handlers[id]; + delete this._message_handlers[id]; + return delete this._roster_handlers[id]; + }; + /*Function Creates and adds an Occupant to the Room Roster. Parameters: (Object) data - the data the Occupant is filled with Returns: occ - the created Occupant. */ - - - XmppRoom.prototype._addOccupant = function(data) { - var occ; - occ = new Occupant(data, this); - this.roster[occ.nick] = occ; - return occ; - }; - - /*Function + XmppRoom.prototype._addOccupant = function(data) { + var occ; + occ = new Occupant(data, this); + this.roster[occ.nick] = occ; + return occ; + }; + /*Function The standard handler that managed the Room Roster. Parameters: (Object) pres - the presence stanza containing user information */ + XmppRoom.prototype._roomRosterHandler = function(pres) { + var data, handler, id, newnick, nick, _ref; + data = XmppRoom._parsePresence(pres); + nick = data.nick; + newnick = data.newnick || null; + switch (data.type) { + case "error": + return; + case "unavailable": + if (newnick) { + data.nick = newnick; + if (this.roster[nick] && this.roster[newnick]) { + this.roster[nick].update(this.roster[newnick]); + this.roster[newnick] = this.roster[nick]; + } + if (this.roster[nick] && !this.roster[newnick]) { + this.roster[newnick] = this.roster[nick].update(data); + } + } + delete this.roster[nick]; + break; - XmppRoom.prototype._roomRosterHandler = function(pres) { - var data, handler, id, newnick, nick, _ref; - data = XmppRoom._parsePresence(pres); - nick = data.nick; - newnick = data.newnick || null; - switch (data.type) { - case 'error': - return; - case 'unavailable': - if (newnick) { - data.nick = newnick; - if (this.roster[nick] && this.roster[newnick]) { - this.roster[nick].update(this.roster[newnick]); - this.roster[newnick] = this.roster[nick]; - } - if (this.roster[nick] && !this.roster[newnick]) { - this.roster[newnick] = this.roster[nick].update(data); - } - } - delete this.roster[nick]; - break; - default: - if (this.roster[nick]) { - this.roster[nick].update(data); - } else { - this._addOccupant(data); - } - } - _ref = this._roster_handlers; - for (id in _ref) { - handler = _ref[id]; - if (!handler(this.roster, this)) { - delete this._roster_handlers[id]; - } - } - return true; - }; - - /*Function + default: + if (this.roster[nick]) { + this.roster[nick].update(data); + } else { + this._addOccupant(data); + } + } + _ref = this._roster_handlers; + for (id in _ref) { + handler = _ref[id]; + if (!handler(this.roster, this)) { + delete this._roster_handlers[id]; + } + } + return true; + }; + /*Function Parses a presence stanza Parameters: (Object) data - the data extracted from the presence stanza */ + XmppRoom._parsePresence = function(pres) { + var a, c, c2, data, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; + data = {}; + a = pres.attributes; + data.nick = Strophe.getResourceFromJid(a.from.textContent); + data.type = ((_ref = a.type) != null ? _ref.textContent : void 0) || null; + data.states = []; + _ref1 = pres.childNodes; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + c = _ref1[_i]; + switch (c.nodeName) { + case "status": + data.status = c.textContent || null; + break; - - XmppRoom._parsePresence = function(pres) { - var a, c, c2, data, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; - data = {}; - a = pres.attributes; - data.nick = Strophe.getResourceFromJid(a.from.textContent); - data.type = ((_ref = a.type) != null ? _ref.textContent : void 0) || null; - data.states = []; - _ref1 = pres.childNodes; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - c = _ref1[_i]; - switch (c.nodeName) { - case "status": - data.status = c.textContent || null; - break; - case "show": - data.show = c.textContent || null; - break; - case "x": - a = c.attributes; - if (((_ref2 = a.xmlns) != null ? _ref2.textContent : void 0) === Strophe.NS.MUC_USER) { - _ref3 = c.childNodes; - for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { - c2 = _ref3[_j]; - switch (c2.nodeName) { - case "item": - a = c2.attributes; - data.affiliation = ((_ref4 = a.affiliation) != null ? _ref4.textContent : void 0) || null; - data.role = ((_ref5 = a.role) != null ? _ref5.textContent : void 0) || null; - data.jid = ((_ref6 = a.jid) != null ? _ref6.textContent : void 0) || null; - data.newnick = ((_ref7 = a.nick) != null ? _ref7.textContent : void 0) || null; + case "show": + data.show = c.textContent || null; break; - case "status": - if (c2.attributes.code) { - data.states.push(c2.attributes.code.textContent); + + case "x": + a = c.attributes; + if (((_ref2 = a.xmlns) != null ? _ref2.textContent : void 0) === Strophe.NS.MUC_USER) { + _ref3 = c.childNodes; + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + c2 = _ref3[_j]; + switch (c2.nodeName) { + case "item": + a = c2.attributes; + data.affiliation = ((_ref4 = a.affiliation) != null ? _ref4.textContent : void 0) || null; + data.role = ((_ref5 = a.role) != null ? _ref5.textContent : void 0) || null; + data.jid = ((_ref6 = a.jid) != null ? _ref6.textContent : void 0) || null; + data.newnick = ((_ref7 = a.nick) != null ? _ref7.textContent : void 0) || null; + break; + + case "status": + if (c2.attributes.code) { + data.states.push(c2.attributes.code.textContent); + } + } + } } } - } } - } - } - return data; - }; - - return XmppRoom; - - })(); - - RoomConfig = (function() { - function RoomConfig(info) { - this.parse = __bind(this.parse, this); - if (info != null) { - this.parse(info); - } - } - - RoomConfig.prototype.parse = function(result) { - var attr, attrs, child, field, identity, query, _i, _j, _k, _len, _len1, _len2, _ref; - query = result.getElementsByTagName("query")[0].childNodes; - this.identities = []; - this.features = []; - this.x = []; - for (_i = 0, _len = query.length; _i < _len; _i++) { - child = query[_i]; - attrs = child.attributes; - switch (child.nodeName) { - case "identity": - identity = {}; - for (_j = 0, _len1 = attrs.length; _j < _len1; _j++) { - attr = attrs[_j]; - identity[attr.name] = attr.textContent; - } - this.identities.push(identity); - break; - case "feature": - this.features.push(attrs["var"].textContent); - break; - case "x": - attrs = child.childNodes[0].attributes; - if ((!attrs["var"].textContent === 'FORM_TYPE') || (!attrs.type.textContent === 'hidden')) { - break; - } - _ref = child.childNodes; - for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) { - field = _ref[_k]; - if (!(!field.attributes.type)) { - continue; - } - attrs = field.attributes; - this.x.push({ - "var": attrs["var"].textContent, - label: attrs.label.textContent || "", - value: field.firstChild.textContent || "" - }); + return data; + }; + return XmppRoom; + }(); + RoomConfig = function() { + function RoomConfig(info) { + this.parse = __bind(this.parse, this); + if (info != null) { + this.parse(info); } } - } - return { - "identities": this.identities, - "features": this.features, - "x": this.x - }; - }; - - return RoomConfig; - - })(); - - Occupant = (function() { - function Occupant(data, room) { - this.room = room; - this.update = __bind(this.update, this); - this.admin = __bind(this.admin, this); - this.owner = __bind(this.owner, this); - this.revoke = __bind(this.revoke, this); - this.member = __bind(this.member, this); - this.ban = __bind(this.ban, this); - this.modifyAffiliation = __bind(this.modifyAffiliation, this); - this.deop = __bind(this.deop, this); - this.op = __bind(this.op, this); - this.mute = __bind(this.mute, this); - this.voice = __bind(this.voice, this); - this.kick = __bind(this.kick, this); - this.modifyRole = __bind(this.modifyRole, this); - this.update(data); - } - - Occupant.prototype.modifyRole = function(role, reason, success_cb, error_cb) { - return this.room.modifyRole(this.nick, role, reason, success_cb, error_cb); - }; - - Occupant.prototype.kick = function(reason, handler_cb, error_cb) { - return this.room.kick(this.nick, reason, handler_cb, error_cb); - }; - - Occupant.prototype.voice = function(reason, handler_cb, error_cb) { - return this.room.voice(this.nick, reason, handler_cb, error_cb); - }; - - Occupant.prototype.mute = function(reason, handler_cb, error_cb) { - return this.room.mute(this.nick, reason, handler_cb, error_cb); - }; - - Occupant.prototype.op = function(reason, handler_cb, error_cb) { - return this.room.op(this.nick, reason, handler_cb, error_cb); - }; - - Occupant.prototype.deop = function(reason, handler_cb, error_cb) { - return this.room.deop(this.nick, reason, handler_cb, error_cb); - }; - - Occupant.prototype.modifyAffiliation = function(affiliation, reason, success_cb, error_cb) { - return this.room.modifyAffiliation(this.jid, affiliation, reason, success_cb, error_cb); - }; - - Occupant.prototype.ban = function(reason, handler_cb, error_cb) { - return this.room.ban(this.jid, reason, handler_cb, error_cb); - }; - - Occupant.prototype.member = function(reason, handler_cb, error_cb) { - return this.room.member(this.jid, reason, handler_cb, error_cb); - }; - - Occupant.prototype.revoke = function(reason, handler_cb, error_cb) { - return this.room.revoke(this.jid, reason, handler_cb, error_cb); - }; - - Occupant.prototype.owner = function(reason, handler_cb, error_cb) { - return this.room.owner(this.jid, reason, handler_cb, error_cb); - }; - - Occupant.prototype.admin = function(reason, handler_cb, error_cb) { - return this.room.admin(this.jid, reason, handler_cb, error_cb); - }; - - Occupant.prototype.update = function(data) { - this.nick = data.nick || null; - this.affiliation = data.affiliation || null; - this.role = data.role || null; - this.jid = data.jid || null; - this.status = data.status || null; - this.show = data.show || null; - return this; - }; - - return Occupant; + RoomConfig.prototype.parse = function(result) { + var attr, attrs, child, field, identity, query, _i, _j, _k, _len, _len1, _len2, _ref; + query = result.getElementsByTagName("query")[0].childNodes; + this.identities = []; + this.features = []; + this.x = []; + for (_i = 0, _len = query.length; _i < _len; _i++) { + child = query[_i]; + attrs = child.attributes; + switch (child.nodeName) { + case "identity": + identity = {}; + for (_j = 0, _len1 = attrs.length; _j < _len1; _j++) { + attr = attrs[_j]; + identity[attr.name] = attr.textContent; + } + this.identities.push(identity); + break; - })(); + case "feature": + this.features.push(attrs["var"].textContent); + break; + case "x": + attrs = child.childNodes[0].attributes; + if (!attrs["var"].textContent === "FORM_TYPE" || !attrs.type.textContent === "hidden") { + break; + } + _ref = child.childNodes; + for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) { + field = _ref[_k]; + if (!!field.attributes.type) { + continue; + } + attrs = field.attributes; + this.x.push({ + "var": attrs["var"].textContent, + label: attrs.label.textContent || "", + value: field.firstChild.textContent || "" + }); + } + } + } + return { + identities: this.identities, + features: this.features, + x: this.x + }; + }; + return RoomConfig; + }(); + Occupant = function() { + function Occupant(data, room) { + this.room = room; + this.update = __bind(this.update, this); + this.admin = __bind(this.admin, this); + this.owner = __bind(this.owner, this); + this.revoke = __bind(this.revoke, this); + this.member = __bind(this.member, this); + this.ban = __bind(this.ban, this); + this.modifyAffiliation = __bind(this.modifyAffiliation, this); + this.deop = __bind(this.deop, this); + this.op = __bind(this.op, this); + this.mute = __bind(this.mute, this); + this.voice = __bind(this.voice, this); + this.kick = __bind(this.kick, this); + this.modifyRole = __bind(this.modifyRole, this); + this.update(data); + } + Occupant.prototype.modifyRole = function(role, reason, success_cb, error_cb) { + return this.room.modifyRole(this.nick, role, reason, success_cb, error_cb); + }; + Occupant.prototype.kick = function(reason, handler_cb, error_cb) { + return this.room.kick(this.nick, reason, handler_cb, error_cb); + }; + Occupant.prototype.voice = function(reason, handler_cb, error_cb) { + return this.room.voice(this.nick, reason, handler_cb, error_cb); + }; + Occupant.prototype.mute = function(reason, handler_cb, error_cb) { + return this.room.mute(this.nick, reason, handler_cb, error_cb); + }; + Occupant.prototype.op = function(reason, handler_cb, error_cb) { + return this.room.op(this.nick, reason, handler_cb, error_cb); + }; + Occupant.prototype.deop = function(reason, handler_cb, error_cb) { + return this.room.deop(this.nick, reason, handler_cb, error_cb); + }; + Occupant.prototype.modifyAffiliation = function(affiliation, reason, success_cb, error_cb) { + return this.room.modifyAffiliation(this.jid, affiliation, reason, success_cb, error_cb); + }; + Occupant.prototype.ban = function(reason, handler_cb, error_cb) { + return this.room.ban(this.jid, reason, handler_cb, error_cb); + }; + Occupant.prototype.member = function(reason, handler_cb, error_cb) { + return this.room.member(this.jid, reason, handler_cb, error_cb); + }; + Occupant.prototype.revoke = function(reason, handler_cb, error_cb) { + return this.room.revoke(this.jid, reason, handler_cb, error_cb); + }; + Occupant.prototype.owner = function(reason, handler_cb, error_cb) { + return this.room.owner(this.jid, reason, handler_cb, error_cb); + }; + Occupant.prototype.admin = function(reason, handler_cb, error_cb) { + return this.room.admin(this.jid, reason, handler_cb, error_cb); + }; + Occupant.prototype.update = function(data) { + this.nick = data.nick || null; + this.affiliation = data.affiliation || null; + this.role = data.role || null; + this.jid = data.jid || null; + this.status = data.status || null; + this.show = data.show || null; + return this; + }; + return Occupant; + }(); }).call(this); /* Copyright 2010, François de Metz */ - /** * Disco Strophe Plugin * Implement http://xmpp.org/extensions/xep-0030.html * TODO: manage node hierarchies, and node on info request */ -Strophe.addConnectionPlugin('disco', -{ +Strophe.addConnectionPlugin("disco", { _connection: null, - _identities : [], - _features : [], - _items : [], + _identities: [], + _features: [], + _items: [], /** Function: init * Plugin init * * Parameters: * (Strophe.Connection) conn - Strophe connection */ - init: function(conn) - { - this._connection = conn; + init: function(conn) { + this._connection = conn; this._identities = []; - this._features = []; - this._items = []; + this._features = []; + this._items = []; // disco info - conn.addHandler(this._onDiscoInfo.bind(this), Strophe.NS.DISCO_INFO, 'iq', 'get', null, null); + conn.addHandler(this._onDiscoInfo.bind(this), Strophe.NS.DISCO_INFO, "iq", "get", null, null); // disco items - conn.addHandler(this._onDiscoItems.bind(this), Strophe.NS.DISCO_ITEMS, 'iq', 'get', null, null); + conn.addHandler(this._onDiscoItems.bind(this), Strophe.NS.DISCO_ITEMS, "iq", "get", null, null); }, /** Function: addIdentity * See http://xmpp.org/registrar/disco-categories.html @@ -6271,19 +5516,18 @@ Strophe.addConnectionPlugin('disco', * Returns: * Boolean */ - addIdentity: function(category, type, name, lang) - { - for (var i=0; i */ - - Strophe.addConnectionPlugin('caps', { - /** Constant: HASH +Strophe.addConnectionPlugin("caps", { + /** Constant: HASH * Hash used * * Currently only sha-1 is supported. */ - HASH: 'sha-1', - /** Variable: node + HASH: "sha-1", + /** Variable: node * Client which is being used. * * Can be overwritten as soon as Strophe has been initialized. */ - node: 'http://strophe.im/strophejs/', - /** PrivateVariable: _ver + node: "http://strophe.im/strophejs/", + /** PrivateVariable: _ver * Own generated version string */ - _ver: '', - /** PrivateVariable: _connection + _ver: "", + /** PrivateVariable: _connection * Strophe connection */ - _connection: null, - /** PrivateVariable: _knownCapabilities + _connection: null, + /** PrivateVariable: _knownCapabilities * A hashtable containing version-strings and their capabilities, serialized * as string. * * TODO: Maybe those caps shouldn't be serialized. */ - _knownCapabilities: {}, - /** PrivateVariable: _jidVerIndex + _knownCapabilities: {}, + /** PrivateVariable: _jidVerIndex * A hashtable containing jids and their versions for better lookup of capabilities. */ - _jidVerIndex: {}, - - /** Function: init + _jidVerIndex: {}, + /** Function: init * Initialize plugin: * - Add caps namespace * - Add caps feature to disco plugin @@ -6517,63 +5756,51 @@ Strophe.addConnectionPlugin('disco', * Parameters: * (Strophe.Connection) conn - Strophe connection */ - init: function(conn) { - this._connection = conn; - - Strophe.addNamespace('CAPS', 'http://jabber.org/protocol/caps'); - - if (!this._connection.disco) { - throw "Caps plugin requires the disco plugin to be installed."; - } - - this._connection.disco.addFeature(Strophe.NS.CAPS); - this._connection.addHandler(this._delegateCapabilities.bind(this), Strophe.NS.CAPS); - }, - - /** Function: generateCapsAttrs + init: function(conn) { + this._connection = conn; + Strophe.addNamespace("CAPS", "http://jabber.org/protocol/caps"); + if (!this._connection.disco) { + throw "Caps plugin requires the disco plugin to be installed."; + } + this._connection.disco.addFeature(Strophe.NS.CAPS); + this._connection.addHandler(this._delegateCapabilities.bind(this), Strophe.NS.CAPS); + }, + /** Function: generateCapsAttrs * Returns the attributes for generating the "c"-stanza containing the own version * * Returns: * (Object) - attributes */ - generateCapsAttrs: function() { - return { - 'xmlns': Strophe.NS.CAPS, - 'hash': this.HASH, - 'node': this.node, - 'ver': this.generateVer() - }; - }, - - /** Function: generateVer + generateCapsAttrs: function() { + return { + xmlns: Strophe.NS.CAPS, + hash: this.HASH, + node: this.node, + ver: this.generateVer() + }; + }, + /** Function: generateVer * Returns the base64 encoded version string (encoded itself with sha1) * * Returns: * (String) - version */ - generateVer: function() { - if (this._ver !== "") { - return this._ver; - } - - var ver = "", - identities = this._connection.disco._identities.sort(this._sortIdentities), - identitiesLen = identities.length, - features = this._connection.disco._features.sort(), - featuresLen = features.length; - for(var i = 0; i < identitiesLen; i++) { - var curIdent = identities[i]; - ver += curIdent.category + "/" + curIdent.type + "/" + curIdent.lang + "/" + curIdent.name + "<"; - } - for(var i = 0; i < featuresLen; i++) { - ver += features[i] + '<'; - } - - this._ver = b64_sha1(ver); - return this._ver; - }, - - /** Function: getCapabilitiesByJid + generateVer: function() { + if (this._ver !== "") { + return this._ver; + } + var ver = "", identities = this._connection.disco._identities.sort(this._sortIdentities), identitiesLen = identities.length, features = this._connection.disco._features.sort(), featuresLen = features.length; + for (var i = 0; i < identitiesLen; i++) { + var curIdent = identities[i]; + ver += curIdent.category + "/" + curIdent.type + "/" + curIdent.lang + "/" + curIdent.name + "<"; + } + for (var i = 0; i < featuresLen; i++) { + ver += features[i] + "<"; + } + this._ver = b64_sha1(ver); + return this._ver; + }, + /** Function: getCapabilitiesByJid * Returns serialized capabilities of a jid (if available). * Otherwise null. * @@ -6583,14 +5810,13 @@ Strophe.addConnectionPlugin('disco', * Returns: * (String|null) - capabilities, serialized; or null when not available. */ - getCapabilitiesByJid: function(jid) { - if (this._jidVerIndex[jid]) { - return this._knownCapabilities[this._jidVerIndex[jid]]; - } - return null; - }, - - /** PrivateFunction: _delegateCapabilities + getCapabilitiesByJid: function(jid) { + if (this._jidVerIndex[jid]) { + return this._knownCapabilities[this._jidVerIndex[jid]]; + } + return null; + }, + /** PrivateFunction: _delegateCapabilities * Checks if the version has already been saved. * If yes: do nothing. * If no: Request capabilities @@ -6601,23 +5827,19 @@ Strophe.addConnectionPlugin('disco', * Returns: * (Boolean) */ - _delegateCapabilities: function(stanza) { - var from = stanza.getAttribute('from'), - c = stanza.querySelector('c'), - ver = c.getAttribute('ver'), - node = c.getAttribute('node'); - if (!this._knownCapabilities[ver]) { - return this._requestCapabilities(from, node, ver); - } else { - this._jidVerIndex[from] = ver; - } - if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) { - this._jidVerIndex[from] = ver; - } - return true; - }, - - /** PrivateFunction: _requestCapabilities + _delegateCapabilities: function(stanza) { + var from = stanza.getAttribute("from"), c = stanza.querySelector("c"), ver = c.getAttribute("ver"), node = c.getAttribute("node"); + if (!this._knownCapabilities[ver]) { + return this._requestCapabilities(from, node, ver); + } else { + this._jidVerIndex[from] = ver; + } + if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) { + this._jidVerIndex[from] = ver; + } + return true; + }, + /** PrivateFunction: _requestCapabilities * Requests capabilities from the one which sent the caps-info stanza. * This is done using disco info. * @@ -6631,15 +5853,14 @@ Strophe.addConnectionPlugin('disco', * Returns: * (Boolean) - true */ - _requestCapabilities: function(to, node, ver) { - if (to !== this._connection.jid) { - var id = this._connection.disco.info(to, node + '#' + ver); - this._connection.addHandler(this._handleDiscoInfoReply.bind(this), Strophe.NS.DISCO_INFO, 'iq', 'result', id, to); - } - return true; - }, - - /** PrivateFunction: _handleDiscoInfoReply + _requestCapabilities: function(to, node, ver) { + if (to !== this._connection.jid) { + var id = this._connection.disco.info(to, node + "#" + ver); + this._connection.addHandler(this._handleDiscoInfoReply.bind(this), Strophe.NS.DISCO_INFO, "iq", "result", id, to); + } + return true; + }, + /** PrivateFunction: _handleDiscoInfoReply * Parses the disco info reply and adds the version & it's capabilities to the _knownCapabilities variable. * Additionally, it adds the jid & the version to the _jidVerIndex variable for a better lookup. * @@ -6649,27 +5870,25 @@ Strophe.addConnectionPlugin('disco', * Returns: * (Boolean) - false, to automatically remove the handler. */ - _handleDiscoInfoReply: function(stanza) { - var query = stanza.querySelector('query'), - node = query.getAttribute('node').split('#'), - ver = node[1], - from = stanza.getAttribute('from'); - if (!this._knownCapabilities[ver]) { - var childNodes = query.childNodes, - childNodesLen = childNodes.length; - this._knownCapabilities[ver] = []; - for(var i = 0; i < childNodesLen; i++) { - var node = childNodes[i]; - this._knownCapabilities[ver].push({name: node.nodeName, attributes: node.attributes}); - } - this._jidVerIndex[from] = ver; - } else if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) { - this._jidVerIndex[from] = ver; - } - return false; - }, - - /** PrivateFunction: _sortIdentities + _handleDiscoInfoReply: function(stanza) { + var query = stanza.querySelector("query"), node = query.getAttribute("node").split("#"), ver = node[1], from = stanza.getAttribute("from"); + if (!this._knownCapabilities[ver]) { + var childNodes = query.childNodes, childNodesLen = childNodes.length; + this._knownCapabilities[ver] = []; + for (var i = 0; i < childNodesLen; i++) { + var node = childNodes[i]; + this._knownCapabilities[ver].push({ + name: node.nodeName, + attributes: node.attributes + }); + } + this._jidVerIndex[from] = ver; + } else if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) { + this._jidVerIndex[from] = ver; + } + return false; + }, + /** PrivateFunction: _sortIdentities * Sorts two identities according the sorting requirements in XEP-0115. * * Parameters: @@ -6679,353 +5898,337 @@ Strophe.addConnectionPlugin('disco', * Returns: * (Integer) - 1, 0 or -1; according to which one's greater. */ - _sortIdentities: function(a, b) { - if (a.category > b.category) { - return 1; - } - if (a.category < b.category) { - return -1; - } - if (a.type > b.type) { - return 1; - } - if (a.type < b.type) { - return -1; - } - if (a.lang > b.lang) { - return 1; - } - if (a.lang < b.lang) { - return -1; - } - return 0; - } - }); + _sortIdentities: function(a, b) { + if (a.category > b.category) { + return 1; + } + if (a.category < b.category) { + return -1; + } + if (a.type > b.type) { + return 1; + } + if (a.type < b.type) { + return -1; + } + if (a.lang > b.lang) { + return 1; + } + if (a.lang < b.lang) { + return -1; + } + return 0; + } +}); /* mustache.js — Logic-less templates in JavaScript See http://mustache.github.com/ for more info. */ - var Mustache = function() { - var Renderer = function() {}; - - Renderer.prototype = { - otag: "{{", - ctag: "}}", - pragmas: {}, - buffer: [], - pragmas_implemented: { - "IMPLICIT-ITERATOR": true - }, - context: {}, - - render: function(template, context, partials, in_recursion) { - // reset buffer & set context - if(!in_recursion) { - this.context = context; - this.buffer = []; // TODO: make this non-lazy - } - - // fail fast - if(!this.includes("", template)) { - if(in_recursion) { - return template; - } else { - this.send(template); - return; - } - } - - template = this.render_pragmas(template); - var html = this.render_section(template, context, partials); - if(in_recursion) { - return this.render_tags(html, context, partials, in_recursion); - } - - this.render_tags(html, context, partials, in_recursion); - }, - - /* + var Renderer = function() {}; + Renderer.prototype = { + otag: "{{", + ctag: "}}", + pragmas: {}, + buffer: [], + pragmas_implemented: { + "IMPLICIT-ITERATOR": true + }, + context: {}, + render: function(template, context, partials, in_recursion) { + // reset buffer & set context + if (!in_recursion) { + this.context = context; + this.buffer = []; + } + // fail fast + if (!this.includes("", template)) { + if (in_recursion) { + return template; + } else { + this.send(template); + return; + } + } + template = this.render_pragmas(template); + var html = this.render_section(template, context, partials); + if (in_recursion) { + return this.render_tags(html, context, partials, in_recursion); + } + this.render_tags(html, context, partials, in_recursion); + }, + /* Sends parsed lines */ - send: function(line) { - if(line !== "") { - this.buffer.push(line); - } - }, - - /* + send: function(line) { + if (line !== "") { + this.buffer.push(line); + } + }, + /* Looks for %PRAGMAS */ - render_pragmas: function(template) { - // no pragmas - if(!this.includes("%", template)) { - return template; - } - - var that = this; - var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + - this.ctag, "g"); - return template.replace(regex, function(match, pragma, options) { - if(!that.pragmas_implemented[pragma]) { - throw({message: - "This implementation of mustache doesn't understand the '" + - pragma + "' pragma"}); - } - that.pragmas[pragma] = {}; - if(options) { - var opts = options.split("="); - that.pragmas[pragma][opts[0]] = opts[1]; - } - return ""; - // ignore unknown pragmas silently - }); - }, - - /* + render_pragmas: function(template) { + // no pragmas + if (!this.includes("%", template)) { + return template; + } + var that = this; + var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + this.ctag, "g"); + return template.replace(regex, function(match, pragma, options) { + if (!that.pragmas_implemented[pragma]) { + throw { + message: "This implementation of mustache doesn't understand the '" + pragma + "' pragma" + }; + } + that.pragmas[pragma] = {}; + if (options) { + var opts = options.split("="); + that.pragmas[pragma][opts[0]] = opts[1]; + } + return ""; + }); + }, + /* Tries to find a partial in the curent scope and render it */ - render_partial: function(name, context, partials) { - name = this.trim(name); - if(!partials || partials[name] === undefined) { - throw({message: "unknown_partial '" + name + "'"}); - } - if(typeof(context[name]) != "object") { - return this.render(partials[name], context, partials, true); - } - return this.render(partials[name], context[name], partials, true); - }, - - /* + render_partial: function(name, context, partials) { + name = this.trim(name); + if (!partials || partials[name] === undefined) { + throw { + message: "unknown_partial '" + name + "'" + }; + } + if (typeof context[name] != "object") { + return this.render(partials[name], context, partials, true); + } + return this.render(partials[name], context[name], partials, true); + }, + /* Renders inverted (^) and normal (#) sections */ - render_section: function(template, context, partials) { - if(!this.includes("#", template) && !this.includes("^", template)) { - return template; - } - - var that = this; - // CSW - Added "+?" so it finds the tighest bound, not the widest - var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag + - "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag + - "\\s*", "mg"); - - // for each {{#foo}}{{/foo}} section do... - return template.replace(regex, function(match, type, name, content) { - var value = that.find(name, context); - if(type == "^") { // inverted section - if(!value || that.is_array(value) && value.length === 0) { - // false or empty list, render it - return that.render(content, context, partials, true); - } else { - return ""; - } - } else if(type == "#") { // normal section - if(that.is_array(value)) { // Enumerable, Let's loop! - return that.map(value, function(row) { - return that.render(content, that.create_context(row), - partials, true); - }).join(""); - } else if(that.is_object(value)) { // Object, Use it as subcontext! - return that.render(content, that.create_context(value), - partials, true); - } else if(typeof value === "function") { - // higher order section - return value.call(context, content, function(text) { - return that.render(text, context, partials, true); + render_section: function(template, context, partials) { + if (!this.includes("#", template) && !this.includes("^", template)) { + return template; + } + var that = this; + // CSW - Added "+?" so it finds the tighest bound, not the widest + var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag + "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag + "\\s*", "mg"); + // for each {{#foo}}{{/foo}} section do... + return template.replace(regex, function(match, type, name, content) { + var value = that.find(name, context); + if (type == "^") { + // inverted section + if (!value || that.is_array(value) && value.length === 0) { + // false or empty list, render it + return that.render(content, context, partials, true); + } else { + return ""; + } + } else if (type == "#") { + // normal section + if (that.is_array(value)) { + // Enumerable, Let's loop! + return that.map(value, function(row) { + return that.render(content, that.create_context(row), partials, true); + }).join(""); + } else if (that.is_object(value)) { + // Object, Use it as subcontext! + return that.render(content, that.create_context(value), partials, true); + } else if (typeof value === "function") { + // higher order section + return value.call(context, content, function(text) { + return that.render(text, context, partials, true); + }); + } else if (value) { + // boolean section + return that.render(content, context, partials, true); + } else { + return ""; + } + } }); - } else if(value) { // boolean section - return that.render(content, context, partials, true); - } else { - return ""; - } - } - }); - }, - - /* + }, + /* Replace {{foo}} and friends with values from our view */ - render_tags: function(template, context, partials, in_recursion) { - // tit for tat - var that = this; - - var new_regex = function() { - return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + - that.ctag + "+", "g"); - }; - - var regex = new_regex(); - var tag_replace_callback = function(match, operator, name) { - switch(operator) { - case "!": // ignore comments - return ""; - case "=": // set new delimiters, rebuild the replace regexp - that.set_delimiters(name); - regex = new_regex(); - return ""; - case ">": // render partial - return that.render_partial(name, context, partials); - case "{": // the triple mustache is unescaped - return that.find(name, context); - default: // escape the value - return that.escape(that.find(name, context)); - } - }; - var lines = template.split("\n"); - for(var i = 0; i < lines.length; i++) { - lines[i] = lines[i].replace(regex, tag_replace_callback, this); - if(!in_recursion) { - this.send(lines[i]); - } - } - - if(in_recursion) { - return lines.join("\n"); - } - }, - - set_delimiters: function(delimiters) { - var dels = delimiters.split(" "); - this.otag = this.escape_regex(dels[0]); - this.ctag = this.escape_regex(dels[1]); - }, - - escape_regex: function(text) { - // thank you Simon Willison - if(!arguments.callee.sRE) { - var specials = [ - '/', '.', '*', '+', '?', '|', - '(', ')', '[', ']', '{', '}', '\\' - ]; - arguments.callee.sRE = new RegExp( - '(\\' + specials.join('|\\') + ')', 'g' - ); - } - return text.replace(arguments.callee.sRE, '\\$1'); - }, - - /* + render_tags: function(template, context, partials, in_recursion) { + // tit for tat + var that = this; + var new_regex = function() { + return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + that.ctag + "+", "g"); + }; + var regex = new_regex(); + var tag_replace_callback = function(match, operator, name) { + switch (operator) { + case "!": + // ignore comments + return ""; + + case "=": + // set new delimiters, rebuild the replace regexp + that.set_delimiters(name); + regex = new_regex(); + return ""; + + case ">": + // render partial + return that.render_partial(name, context, partials); + + case "{": + // the triple mustache is unescaped + return that.find(name, context); + + default: + // escape the value + return that.escape(that.find(name, context)); + } + }; + var lines = template.split("\n"); + for (var i = 0; i < lines.length; i++) { + lines[i] = lines[i].replace(regex, tag_replace_callback, this); + if (!in_recursion) { + this.send(lines[i]); + } + } + if (in_recursion) { + return lines.join("\n"); + } + }, + set_delimiters: function(delimiters) { + var dels = delimiters.split(" "); + this.otag = this.escape_regex(dels[0]); + this.ctag = this.escape_regex(dels[1]); + }, + escape_regex: function(text) { + // thank you Simon Willison + if (!arguments.callee.sRE) { + var specials = [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\" ]; + arguments.callee.sRE = new RegExp("(\\" + specials.join("|\\") + ")", "g"); + } + return text.replace(arguments.callee.sRE, "\\$1"); + }, + /* find `name` in current `context`. That is find me a value from the view object */ - find: function(name, context) { - name = this.trim(name); - - // Checks whether a value is thruthy or false or 0 - function is_kinda_truthy(bool) { - return bool === false || bool === 0 || bool; - } - - var value; - if(is_kinda_truthy(context[name])) { - value = context[name]; - } else if(is_kinda_truthy(this.context[name])) { - value = this.context[name]; - } - - if(typeof value === "function") { - return value.apply(context); - } - if(value !== undefined) { - return value; - } - // silently ignore unkown variables - return ""; - }, - - // Utility methods - - /* includes tag */ - includes: function(needle, haystack) { - return haystack.indexOf(this.otag + needle) != -1; - }, - - /* + find: function(name, context) { + name = this.trim(name); + // Checks whether a value is thruthy or false or 0 + function is_kinda_truthy(bool) { + return bool === false || bool === 0 || bool; + } + var value; + if (is_kinda_truthy(context[name])) { + value = context[name]; + } else if (is_kinda_truthy(this.context[name])) { + value = this.context[name]; + } + if (typeof value === "function") { + return value.apply(context); + } + if (value !== undefined) { + return value; + } + // silently ignore unkown variables + return ""; + }, + // Utility methods + /* includes tag */ + includes: function(needle, haystack) { + return haystack.indexOf(this.otag + needle) != -1; + }, + /* Does away with nasty characters */ - escape: function(s) { - s = String(s === null ? "" : s); - return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) { - switch(s) { - case "&": return "&"; - case "\\": return "\\\\"; - case '"': return '"'; - case "'": return '''; - case "<": return "<"; - case ">": return ">"; - default: return s; - } - }); - }, + escape: function(s) { + s = String(s === null ? "" : s); + return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) { + switch (s) { + case "&": + return "&"; - // by @langalex, support for arrays of strings - create_context: function(_context) { - if(this.is_object(_context)) { - return _context; - } else { - var iterator = "."; - if(this.pragmas["IMPLICIT-ITERATOR"]) { - iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; - } - var ctx = {}; - ctx[iterator] = _context; - return ctx; - } - }, + case "\\": + return "\\\\"; - is_object: function(a) { - return a && typeof a == "object"; - }, + case '"': + return """; - is_array: function(a) { - return Object.prototype.toString.call(a) === '[object Array]'; - }, + case "'": + return "'"; - /* + case "<": + return "<"; + + case ">": + return ">"; + + default: + return s; + } + }); + }, + // by @langalex, support for arrays of strings + create_context: function(_context) { + if (this.is_object(_context)) { + return _context; + } else { + var iterator = "."; + if (this.pragmas["IMPLICIT-ITERATOR"]) { + iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; + } + var ctx = {}; + ctx[iterator] = _context; + return ctx; + } + }, + is_object: function(a) { + return a && typeof a == "object"; + }, + is_array: function(a) { + return Object.prototype.toString.call(a) === "[object Array]"; + }, + /* Gets rid of leading and trailing whitespace */ - trim: function(s) { - return s.replace(/^\s*|\s*$/g, ""); - }, - - /* + trim: function(s) { + return s.replace(/^\s*|\s*$/g, ""); + }, + /* Why, why, why? Because IE. Cry, cry cry. */ - map: function(array, fn) { - if (typeof array.map == "function") { - return array.map(fn); - } else { - var r = []; - var l = array.length; - for(var i = 0; i < l; i++) { - r.push(fn(array[i])); + map: function(array, fn) { + if (typeof array.map == "function") { + return array.map(fn); + } else { + var r = []; + var l = array.length; + for (var i = 0; i < l; i++) { + r.push(fn(array[i])); + } + return r; + } } - return r; - } - } - }; - - return({ - name: "mustache.js", - version: "0.3.1-dev", - - /* + }; + return { + name: "mustache.js", + version: "0.3.1-dev", + /* Turns a template and view into HTML */ - to_html: function(template, view, partials, send_fun) { - var renderer = new Renderer(); - if(send_fun) { - renderer.send = send_fun; - } - renderer.render(template, view, partials); - if(!send_fun) { - return renderer.buffer.join("\n"); - } - } - }); + to_html: function(template, view, partials, send_fun) { + var renderer = new Renderer(); + if (send_fun) { + renderer.send = send_fun; + } + renderer.render(template, view, partials); + if (!send_fun) { + return renderer.buffer.join("\n"); + } + } + }; }(); /*! @@ -7039,36 +6242,31 @@ var Mustache = function() { * Version: 1.1.1 (Sun, 05 Jan 2014 05:26:50 GMT) */ (function($) { - /** + /** * i18n provides a mechanism for translating strings using a jscript dictionary. * */ - - var __slice = Array.prototype.slice; - - /* + var __slice = Array.prototype.slice; + /* * i18n property list */ - var i18n = { - - dict: null, - - /** + var i18n = { + dict: null, + /** * load() * * Load translations. * * @param property_list i18n_dict : The dictionary to use for translation. */ - load: function(i18n_dict) { - if (this.dict !== null) { - $.extend(this.dict, i18n_dict); - } else { - this.dict = i18n_dict; - } - }, - - /** + load: function(i18n_dict) { + if (this.dict !== null) { + $.extend(this.dict, i18n_dict); + } else { + this.dict = i18n_dict; + } + }, + /** * _() * * Looks the given string up in the dictionary and returns the translation if @@ -7079,18 +6277,17 @@ var Mustache = function() { * * @return string : Translated word. */ - _: function (str) { - dict = this.dict; - if (dict && dict.hasOwnProperty(str)) { - str = dict[str]; - } - args = __slice.call(arguments); - args[0] = str; - // Substitute any params. - return this.printf.apply(this, args); - }, - - /* + _: function(str) { + dict = this.dict; + if (dict && dict.hasOwnProperty(str)) { + str = dict[str]; + } + args = __slice.call(arguments); + args[0] = str; + // Substitute any params. + return this.printf.apply(this, args); + }, + /* * printf() * * Substitutes %s with parameters given in list. %%s is used to escape %s. @@ -7100,20 +6297,18 @@ var Mustache = function() { * * @return string result : Substituted string */ - printf: function(str, args) { - if (arguments.length < 2) return str; - args = $.isArray(args) ? args : __slice.call(arguments, 1); - return str.replace(/([^%]|^)%(?:(\d+)\$)?s/g, function(p0, p, position) { - if (position) { - return p + args[parseInt(position)-1]; + printf: function(str, args) { + if (arguments.length < 2) return str; + args = $.isArray(args) ? args : __slice.call(arguments, 1); + return str.replace(/([^%]|^)%(?:(\d+)\$)?s/g, function(p0, p, position) { + if (position) { + return p + args[parseInt(position) - 1]; + } + return p + args.shift(); + }).replace(/%%s/g, "%s"); } - return p + args.shift(); - }).replace(/%%s/g, '%s'); - } - - }; - - /* + }; + /* * _t() * * Allows you to translate a jQuery selector. @@ -7125,11 +6320,10 @@ var Mustache = function() { * * @return element : Chained and translated element(s). */ - $.fn._t = function(str, params) { - return $(this).html(i18n._.apply(i18n, arguments)); - }; - - $.i18n = i18n; + $.fn._t = function(str, params) { + return $(this).html(i18n._.apply(i18n, arguments)); + }; + $.i18n = i18n; })(jQuery); /* @@ -7147,115 +6341,89 @@ var Mustache = function() { * * @link http://blog.stevenlevithan.com/archives/date-time-format */ - -var dateFormat = function () { - var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, - timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, - timezoneClip = /[^-+\dA-Z]/g, - pad = function (val, len) { - val = String(val); - len = len || 2; - while (val.length < len) val = "0" + val; - return val; - }; - - // Regexes and supporting functions are cached through closure - return function (date, mask, utc) { - var dF = dateFormat; - - // You can't provide utc if you skip other args (use the "UTC:" mask prefix) - if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { - mask = date; - date = undefined; - } - - // Passing date through Date applies Date.parse, if necessary - date = date ? new Date(date) : new Date; - if (isNaN(date)) throw SyntaxError("invalid date"); - - mask = String(dF.masks[mask] || mask || dF.masks["default"]); - - // Allow setting the utc argument via the mask - if (mask.slice(0, 4) == "UTC:") { - mask = mask.slice(4); - utc = true; - } - - var _ = utc ? "getUTC" : "get", - d = date[_ + "Date"](), - D = date[_ + "Day"](), - m = date[_ + "Month"](), - y = date[_ + "FullYear"](), - H = date[_ + "Hours"](), - M = date[_ + "Minutes"](), - s = date[_ + "Seconds"](), - L = date[_ + "Milliseconds"](), - o = utc ? 0 : date.getTimezoneOffset(), - flags = { - d: d, - dd: pad(d), - ddd: dF.i18n.dayNames[D], - dddd: dF.i18n.dayNames[D + 7], - m: m + 1, - mm: pad(m + 1), - mmm: dF.i18n.monthNames[m], - mmmm: dF.i18n.monthNames[m + 12], - yy: String(y).slice(2), - yyyy: y, - h: H % 12 || 12, - hh: pad(H % 12 || 12), - H: H, - HH: pad(H), - M: M, - MM: pad(M), - s: s, - ss: pad(s), - l: pad(L, 3), - L: pad(L > 99 ? Math.round(L / 10) : L), - t: H < 12 ? "a" : "p", - tt: H < 12 ? "am" : "pm", - T: H < 12 ? "A" : "P", - TT: H < 12 ? "AM" : "PM", - Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), - o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), - S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] - }; - - return mask.replace(token, function ($0) { - return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); - }); - }; +var dateFormat = function() { + var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g, pad = function(val, len) { + val = String(val); + len = len || 2; + while (val.length < len) val = "0" + val; + return val; + }; + // Regexes and supporting functions are cached through closure + return function(date, mask, utc) { + var dF = dateFormat; + // You can't provide utc if you skip other args (use the "UTC:" mask prefix) + if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { + mask = date; + date = undefined; + } + // Passing date through Date applies Date.parse, if necessary + date = date ? new Date(date) : new Date(); + if (isNaN(date)) throw SyntaxError("invalid date"); + mask = String(dF.masks[mask] || mask || dF.masks["default"]); + // Allow setting the utc argument via the mask + if (mask.slice(0, 4) == "UTC:") { + mask = mask.slice(4); + utc = true; + } + var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = date[_ + "Day"](), m = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), M = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = { + d: d, + dd: pad(d), + ddd: dF.i18n.dayNames[D], + dddd: dF.i18n.dayNames[D + 7], + m: m + 1, + mm: pad(m + 1), + mmm: dF.i18n.monthNames[m], + mmmm: dF.i18n.monthNames[m + 12], + yy: String(y).slice(2), + yyyy: y, + h: H % 12 || 12, + hh: pad(H % 12 || 12), + H: H, + HH: pad(H), + M: M, + MM: pad(M), + s: s, + ss: pad(s), + l: pad(L, 3), + L: pad(L > 99 ? Math.round(L / 10) : L), + t: H < 12 ? "a" : "p", + tt: H < 12 ? "am" : "pm", + T: H < 12 ? "A" : "P", + TT: H < 12 ? "AM" : "PM", + Z: utc ? "UTC" : (String(date).match(timezone) || [ "" ]).pop().replace(timezoneClip, ""), + o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + S: [ "th", "st", "nd", "rd" ][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] + }; + return mask.replace(token, function($0) { + return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); + }); + }; }(); // Some common format strings dateFormat.masks = { - "default": "ddd mmm dd yyyy HH:MM:ss", - shortDate: "m/d/yy", - mediumDate: "mmm d, yyyy", - longDate: "mmmm d, yyyy", - fullDate: "dddd, mmmm d, yyyy", - shortTime: "h:MM TT", - mediumTime: "h:MM:ss TT", - longTime: "h:MM:ss TT Z", - isoDate: "yyyy-mm-dd", - isoTime: "HH:MM:ss", - isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", - isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" + "default": "ddd mmm dd yyyy HH:MM:ss", + shortDate: "m/d/yy", + mediumDate: "mmm d, yyyy", + longDate: "mmmm d, yyyy", + fullDate: "dddd, mmmm d, yyyy", + shortTime: "h:MM TT", + mediumTime: "h:MM:ss TT", + longTime: "h:MM:ss TT Z", + isoDate: "yyyy-mm-dd", + isoTime: "HH:MM:ss", + isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", + isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" }; // Internationalization strings dateFormat.i18n = { - dayNames: [ - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" - ] + dayNames: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], + monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] }; // For convenience... -Date.prototype.format = function (mask, utc) { - return dateFormat(this, mask, utc); -}; \ No newline at end of file +Date.prototype.format = function(mask, utc) { + return dateFormat(this, mask, utc); +}; +//# sourceMappingURL=libs.bundle.map \ No newline at end of file diff --git a/libs/libs.bundle.map b/libs/libs.bundle.map new file mode 100644 index 00000000..9a86569c --- /dev/null +++ b/libs/libs.bundle.map @@ -0,0 +1 @@ +{"version":3,"file":"libs.bundle.js","sources":["strophejs/strophe.js","strophejs-plugins/muc/strophe.muc.js","strophejs-plugins/disco/strophe.disco.js","strophejs-plugins/caps/strophe.caps.jsonly.js","mustache.js/mustache.js","jquery-i18n/jquery.i18n.js","dateformat/dateFormat.js"],"names":["Base64","keyStr","obj","encode","input","output","chr1","chr2","chr3","enc1","enc2","enc3","enc4","i","charCodeAt","isNaN","charAt","length","decode","replace","indexOf","String","fromCharCode","hexcase","b64pad","chrsz","hex_sha1","s","binb2hex","core_sha1","str2binb","b64_sha1","binb2b64","str_sha1","binb2str","hex_hmac_sha1","key","data","core_hmac_sha1","b64_hmac_sha1","str_hmac_sha1","sha1_vm_test","x","len","w","Array","a","b","c","d","e","j","t","olda","oldb","oldc","oldd","olde","rol","safe_add","sha1_ft","sha1_kt","bkey","ipad","opad","hash","concat","y","lsw","msw","num","cnt","str","bin","mask","binarray","hex_tab","tab","triplet","MD5","bit_rol","str2binl","binl2str","binl2hex","binl2b64","md5_cmn","q","md5_ff","md5_gg","md5_hh","md5_ii","core_md5","core_hmac_md5","hexdigest","b64digest","hmac_hexdigest","hmac_b64digest","hmac_hash","test","Function","prototype","bind","func","this","_slice","slice","_concat","_args","call","arguments","apply","elt","from","Number","Math","ceil","floor","callback","Strophe","$build","name","attrs","Builder","$msg","$iq","$pres","VERSION","NS","HTTPBIND","BOSH","CLIENT","AUTH","ROSTER","PROFILE","DISCO_INFO","DISCO_ITEMS","MUC","SASL","STREAM","BIND","SESSION","STANZAS","XHTML_IM","XHTML","tags","attributes","blockquote","br","cite","em","img","li","ol","p","span","strong","ul","body","css","validTag","tag","validAttribute","attribute","validCSS","style","Status","ERROR","CONNECTING","CONNFAIL","AUTHENTICATING","AUTHFAIL","CONNECTED","DISCONNECTED","DISCONNECTING","ATTACHED","LogLevel","DEBUG","INFO","WARN","FATAL","ElementType","NORMAL","TEXT","CDATA","FRAGMENT","TIMEOUT","SECONDARY_TIMEOUT","addNamespace","value","forEachChild","elem","elemName","childNode","childNodes","nodeType","isTagEqual","el","tagName","toLowerCase","_xmlGenerator","_makeGenerator","doc","document","implementation","createDocument","undefined","documentMode","_getIEXmlDom","appendChild","createElement","xmlGenerator","docStrings","ActiveXObject","xmlElement","node","k","xmlTextNode","setAttribute","hasOwnProperty","xmlescape","text","createTextNode","xmlHtmlNode","html","window","DOMParser","parser","parseFromString","async","loadXML","getText","nodeValue","copyElement","nodeName","createHtml","cssAttrs","attr","cssName","cssValue","children","child","getAttribute","cssText","split","push","join","createDocumentFragment","escapeNode","unescapeNode","getNodeFromJid","jid","getDomainFromJid","bare","getBareJidFromJid","parts","splice","getResourceFromJid","log","level","msg","debug","info","warn","error","fatal","serialize","result","tree","_requestId","_connectionPlugins","addConnectionPlugin","ptype","xmlns","nodeTree","toString","up","parentNode","moreattrs","cnode","impNode","xmlGen","importNode","newElem","h","fragment","innerHTML","xhtml","Handler","handler","ns","type","id","options","matchBare","user","isMatch","nsMatch","that","run","sourceURL","line","message","fileName","console","trace","lineNumber","stack","TimedHandler","period","lastCalled","Date","getTime","reset","Connection","service","proto","protocol","_proto","Websocket","Bosh","domain","features","_sasl_data","do_session","do_bind","timedHandlers","handlers","removeTimeds","removeHandlers","addTimeds","addHandlers","_authentication","_idleTimeout","_disconnectTimeout","do_authentication","authenticated","disconnecting","connected","errors","paused","_data","_uniqueId","_sasl_success_handler","_sasl_failure_handler","_sasl_challenge_handler","maxRetries","setTimeout","_onIdle","F","init","_reset","_requests","pause","resume","getUniqueId","suffix","connect","pass","wait","hold","route","authzid","authcid","servtype","connect_callback","_changeConnectStatus","_connect","attach","sid","rid","wind","_attach","xmlInput","xmlOutput","rawInput","rawOutput","send","_queueData","_send","flush","clearTimeout","sendIQ","errback","timeout","timeoutHandler","addHandler","stanza","deleteTimedHandler","iqtype","addTimedHandler","deleteHandler","element","_sendRestart","thand","handRef","hand","disconnect","reason","pres","_addSysTimedHandler","_onDisconnectTimeout","_disconnect","status","condition","plugin","statusChanged","err","_doDisconnect","_dataRecv","req","raw","_reqToData","strip","pop","_emptyQueue","typ","cond","conflict","getElementsByTagName","newList","mechanisms","_connect_cb","_callback","bodyWrap","conncheck","sasl_scram_sha1","sasl_plain","sasl_digest_md5","sasl_anonymous","legacy_auth","hasFeatures","matched","mech","auth_str","hashed_auth_str","found_authentication","_no_auth_received","authenticate","higher","priority","swap","mechanism_found","_addSysHandler","_sasl_success_cb","_sasl_failure_cb","_sasl_challenge_cb","_sasl_mechanism","onStart","request_auth_exchange","mechanism","isClientFirst","response","onChallenge","_auth1_cb","to","challenge","iq","_auth2_cb","serverSignature","success","attribMatch","matches","match","onSuccess","_sasl_auth1_cb","_sasl_bind_cb","resource","jidNode","_sasl_session_cb","onFailure","since","now","time_elapsed","SASLMechanism","connection","_connection","Error","SASLAnonymous","SASLPlain","SASLSHA1","test_cnonce","cnonce","random","nonce","salt","iter","Hi","U","U_old","clientKey","serverKey","clientSignature","responseText","authMessage","substr","SASLMD5","_quote","realm","host","qop","digest_uri","A1","A2","Request","sends","xmlData","origFunc","date","NaN","abort","dead","age","timeDead","xhr","_newXHR","getResponse","responseXML","documentElement","XMLHttpRequest","overrideMimeType","onreadystatechange","_conn","_buildBody","xml:lang","content","ver","xmpp:version","xmlns:xmpp","_onRequestStateChange","_throttledRequestHandler","parseInt","_sendTerminate","_hitError","reqStatus","xmpp:restart","_processRequest","readyState","reqIs0","reqIs1","_removeRequest","_restartRequest","self","primaryTimeout","secondaryTimeout","requestCompletedWithServerError","open","sync","e2","sendFunc","customHeaders","headers","header","setRequestHeader","backoff","min","pow","abs","new_service","location","pathname","_buildStream","xmlns:stream","version","_check_streamerror","connectstatus","textContent","errorString","_closeSocket","socket","WebSocket","onopen","_onOpen","onerror","_onError","onclose","_onClose","onmessage","_connect_cb_wrapper","_handleStreamStart","ns_stream","namespaceURI","streamStart","string","_streamWrap","_onMessage","CLOSED","close","event","rawStanza","_removeClosingTag","search","firstChild","start","startString","Occupant","RoomConfig","XmppRoom","__bind","fn","me","rooms","roomNames","conn","_muc_handler","room","nick","msg_handler_cb","pres_handler_cb","roster_cb","password","history_attrs","room_nick","_this","test_append_nick","extended_presence","roomname","xquery","_i","_len","_message_handlers","_presence_handlers","leave","handler_cb","exit_msg","presence","presenceid","html_message","msgid","parent","removeChild","groupchat","invite","receiver","invitation","MUC_USER","directInvite","queryOccupants","success_cb","error_cb","configure","config","MUC_OWNER","cancelConfigure","saveConfiguration","conf","Form","toXML","createInstantRoom","roomiq","setTopic","topic","_modifyPrivilege","item","MUC_ADMIN","modifyRole","role","kick","voice","mute","op","deop","modifyAffiliation","affiliation","ban","member","revoke","owner","admin","changeNick","setStatus","show","listRooms","server","handle_cb","client","_roomRosterHandler","_addOccupant","roster","_roster_handlers","_handler_ids","muc","handler_type","removeHandler","occ","newnick","_ref","_parsePresence","update","c2","_j","_len1","_ref1","_ref2","_ref3","_ref4","_ref5","_ref6","_ref7","states","code","parse","field","identity","query","_k","_len2","identities","var","label","_identities","_features","_items","_onDiscoInfo","_onDiscoItems","addIdentity","category","lang","addFeature","var_name","removeFeature","addItem","call_back","items","_buildIQResult","query_attrs","iqresult","HASH","_ver","_knownCapabilities","_jidVerIndex","disco","CAPS","_delegateCapabilities","generateCapsAttrs","generateVer","sort","_sortIdentities","identitiesLen","featuresLen","curIdent","getCapabilitiesByJid","querySelector","_requestCapabilities","_handleDiscoInfoReply","childNodesLen","Mustache","Renderer","otag","ctag","pragmas","buffer","pragmas_implemented","IMPLICIT-ITERATOR","context","render","template","partials","in_recursion","includes","render_pragmas","render_section","render_tags","regex","RegExp","pragma","opts","render_partial","trim","find","is_array","map","row","create_context","is_object","new_regex","tag_replace_callback","operator","set_delimiters","escape","lines","delimiters","dels","escape_regex","callee","sRE","specials","is_kinda_truthy","bool","needle","haystack","_context","iterator","ctx","Object","array","r","l","to_html","view","send_fun","renderer","$","__slice","i18n","dict","load","i18n_dict","extend","_","args","printf","isArray","p0","position","shift","_t","params","jQuery","dateFormat","token","timezone","timezoneClip","pad","val","utc","dF","SyntaxError","masks","D","m","H","M","L","o","getTimezoneOffset","flags","dd","ddd","dayNames","dddd","mm","mmm","monthNames","mmmm","yy","yyyy","hh","HH","MM","ss","round","tt","T","TT","Z","S","$0","default","shortDate","mediumDate","longDate","fullDate","shortTime","mediumTime","longTime","isoDate","isoTime","isoDateTime","isoUtcDateTime","format"],"mappings":"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"} \ No newline at end of file diff --git a/libs/libs.min.js b/libs/libs.min.js index 4b4cc495..299bf7f4 100644 --- a/libs/libs.min.js +++ b/libs/libs.min.js @@ -1,3 +1,3 @@ -function hex_sha1(a){return binb2hex(core_sha1(str2binb(a),a.length*chrsz))}function b64_sha1(a){return binb2b64(core_sha1(str2binb(a),a.length*chrsz))}function str_sha1(a){return binb2str(core_sha1(str2binb(a),a.length*chrsz))}function hex_hmac_sha1(a,b){return binb2hex(core_hmac_sha1(a,b))}function b64_hmac_sha1(a,b){return binb2b64(core_hmac_sha1(a,b))}function str_hmac_sha1(a,b){return binb2str(core_hmac_sha1(a,b))}function sha1_vm_test(){return"a9993e364706816aba3e25717850c26c9cd0d89d"==hex_sha1("abc")}function core_sha1(a,b){a[b>>5]|=128<<24-b%32,a[(b+64>>9<<4)+15]=b;var c,d,e,f,g,h,i,j,k=new Array(80),l=1732584193,m=-271733879,n=-1732584194,o=271733878,p=-1009589776;for(c=0;cd;d++)k[d]=16>d?a[c+d]:rol(k[d-3]^k[d-8]^k[d-14]^k[d-16],1),e=safe_add(safe_add(rol(l,5),sha1_ft(d,m,n,o)),safe_add(safe_add(p,k[d]),sha1_kt(d))),p=o,o=n,n=rol(m,30),m=l,l=e;l=safe_add(l,f),m=safe_add(m,g),n=safe_add(n,h),o=safe_add(o,i),p=safe_add(p,j)}return[l,m,n,o,p]}function sha1_ft(a,b,c,d){return 20>a?b&c|~b&d:40>a?b^c^d:60>a?b&c|b&d|c&d:b^c^d}function sha1_kt(a){return 20>a?1518500249:40>a?1859775393:60>a?-1894007588:-899497514}function core_hmac_sha1(a,b){var c=str2binb(a);c.length>16&&(c=core_sha1(c,a.length*chrsz));for(var d=new Array(16),e=new Array(16),f=0;16>f;f++)d[f]=909522486^c[f],e[f]=1549556828^c[f];var g=core_sha1(d.concat(str2binb(b)),512+b.length*chrsz);return core_sha1(e.concat(g),672)}function safe_add(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}function rol(a,b){return a<>>32-b}function str2binb(a){for(var b=[],c=(1<>5]|=(a.charCodeAt(d/chrsz)&c)<<32-chrsz-d%32;return b}function binb2str(a){for(var b="",c=(1<>5]>>>32-chrsz-d%32&c);return b}function binb2hex(a){for(var b=hexcase?"0123456789ABCDEF":"0123456789abcdef",c="",d=0;d<4*a.length;d++)c+=b.charAt(a[d>>2]>>8*(3-d%4)+4&15)+b.charAt(a[d>>2]>>8*(3-d%4)&15);return c}function binb2b64(a){for(var b,c,d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",e="",f=0;f<4*a.length;f+=3)for(b=(a[f>>2]>>8*(3-f%4)&255)<<16|(a[f+1>>2]>>8*(3-(f+1)%4)&255)<<8|a[f+2>>2]>>8*(3-(f+2)%4)&255,c=0;4>c;c++)e+=8*f+6*c>32*a.length?b64pad:d.charAt(b>>6*(3-c)&63);return e}var Base64=function(){var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",b={encode:function(b){var c,d,e,f,g,h,i,j="",k=0;do c=b.charCodeAt(k++),d=b.charCodeAt(k++),e=b.charCodeAt(k++),f=c>>2,g=(3&c)<<4|d>>4,h=(15&d)<<2|e>>6,i=63&e,isNaN(d)?h=i=64:isNaN(e)&&(i=64),j=j+a.charAt(f)+a.charAt(g)+a.charAt(h)+a.charAt(i);while(k>4,d=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(c),64!=h&&(j+=String.fromCharCode(d)),64!=i&&(j+=String.fromCharCode(e));while(k>16)+(b>>16)+(c>>16);return d<<16|65535&c},e=function(a,b){return a<>>32-b},f=function(a){for(var b=[],d=(1<>5]|=(a.charCodeAt(e/c)&d)<>5]>>>e%32&d);return b},h=function(b){for(var c=a?"0123456789ABCDEF":"0123456789abcdef",d="",e=0;e<4*b.length;e++)d+=c.charAt(b[e>>2]>>e%4*8+4&15)+c.charAt(b[e>>2]>>e%4*8&15);return d},i=function(a){for(var c,d,e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f="",g=0;g<4*a.length;g+=3)for(c=(a[g>>2]>>8*(g%4)&255)<<16|(a[g+1>>2]>>8*((g+1)%4)&255)<<8|a[g+2>>2]>>8*((g+2)%4)&255,d=0;4>d;d++)f+=8*g+6*d>32*a.length?b:e.charAt(c>>6*(3-d)&63);return f},j=function(a,b,c,f,g,h){return d(e(d(d(b,a),d(f,h)),g),c)},k=function(a,b,c,d,e,f,g){return j(b&c|~b&d,a,b,e,f,g)},l=function(a,b,c,d,e,f,g){return j(b&d|c&~d,a,b,e,f,g)},m=function(a,b,c,d,e,f,g){return j(b^c^d,a,b,e,f,g)},n=function(a,b,c,d,e,f,g){return j(c^(b|~d),a,b,e,f,g)},o=function(a,b){a[b>>5]|=128<>>9<<4)+14]=b;for(var c,e,f,g,h=1732584193,i=-271733879,j=-1732584194,o=271733878,p=0;p16&&(d=o(d,a.length*c));for(var e=new Array(16),g=new Array(16),h=0;16>h;h++)e[h]=909522486^d[h],g[h]=1549556828^d[h];var i=o(e.concat(f(b)),512+b.length*c);return o(g.concat(i),640)},q={hexdigest:function(a){return h(o(f(a),a.length*c))},b64digest:function(a){return i(o(f(a),a.length*c))},hash:function(a){return g(o(f(a),a.length*c))},hmac_hexdigest:function(a,b){return h(p(a,b))},hmac_b64digest:function(a,b){return i(p(a,b))},hmac_hash:function(a,b){return g(p(a,b))},test:function(){return"900150983cd24fb0d6963f7d28e17f72"===MD5.hexdigest("abc")}};return q}();Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice,d=Array.prototype.concat,e=c.call(arguments,1);return function(){return b.apply(a?a:this,d.call(e,c.call(arguments,0)))}}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=this.length,c=Number(arguments[1])||0;for(c=0>c?Math.ceil(c):Math.floor(c),0>c&&(c+=b);b>c;c++)if(c in this&&this[c]===a)return c;return-1}),function(a){function b(a,b){return new f.Builder(a,b)}function c(a){return new f.Builder("message",a)}function d(a){return new f.Builder("iq",a)}function e(a){return new f.Builder("presence",a)}var f;f={VERSION:"a1f13b2",NS:{HTTPBIND:"http://jabber.org/protocol/httpbind",BOSH:"urn:xmpp:xbosh",CLIENT:"jabber:client",AUTH:"jabber:iq:auth",ROSTER:"jabber:iq:roster",PROFILE:"jabber:iq:profile",DISCO_INFO:"http://jabber.org/protocol/disco#info",DISCO_ITEMS:"http://jabber.org/protocol/disco#items",MUC:"http://jabber.org/protocol/muc",SASL:"urn:ietf:params:xml:ns:xmpp-sasl",STREAM:"http://etherx.jabber.org/streams",BIND:"urn:ietf:params:xml:ns:xmpp-bind",SESSION:"urn:ietf:params:xml:ns:xmpp-session",VERSION:"jabber:iq:version",STANZAS:"urn:ietf:params:xml:ns:xmpp-stanzas",XHTML_IM:"http://jabber.org/protocol/xhtml-im",XHTML:"http://www.w3.org/1999/xhtml"},XHTML:{tags:["a","blockquote","br","cite","em","img","li","ol","p","span","strong","ul","body"],attributes:{a:["href"],blockquote:["style"],br:[],cite:["style"],em:[],img:["src","alt","style","height","width"],li:["style"],ol:["style"],p:["style"],span:["style"],strong:[],ul:["style"],body:[]},css:["background-color","color","font-family","font-size","font-style","font-weight","margin-left","margin-right","text-align","text-decoration"],validTag:function(a){for(var b=0;b0)for(var c=0;c/g,">"),a=a.replace(/'/g,"'"),a=a.replace(/"/g,""")},xmlTextNode:function(a){return f.xmlGenerator().createTextNode(a)},xmlHtmlNode:function(a){return window.DOMParser?(parser=new DOMParser,node=parser.parseFromString(a,"text/xml")):(node=new ActiveXObject("Microsoft.XMLDOM"),node.async="false",node.loadXML(a)),node},getText:function(a){if(!a)return null;var b="";0===a.childNodes.length&&a.nodeType==f.ElementType.TEXT&&(b+=a.nodeValue);for(var c=0;c0&&(h=i.join("; "),c.setAttribute(g,h))}else c.setAttribute(g,h);for(b=0;b/g,"\\3e").replace(/@/g,"\\40")},unescapeNode:function(a){return a.replace(/\\20/g," ").replace(/\\22/g,'"').replace(/\\26/g,"&").replace(/\\27/g,"'").replace(/\\2f/g,"/").replace(/\\3a/g,":").replace(/\\3c/g,"<").replace(/\\3e/g,">").replace(/\\40/g,"@").replace(/\\5c/g,"\\")},getNodeFromJid:function(a){return a.indexOf("@")<0?null:a.split("@")[0]},getDomainFromJid:function(a){var b=f.getBareJidFromJid(a);if(b.indexOf("@")<0)return b;var c=b.split("@");return c.splice(0,1),c.join("@")},getResourceFromJid:function(a){var b=a.split("/");return b.length<2?null:(b.splice(0,1),b.join("/"))},getBareJidFromJid:function(a){return a?a.split("/")[0]:null},log:function(){},debug:function(a){this.log(this.LogLevel.DEBUG,a)},info:function(a){this.log(this.LogLevel.INFO,a)},warn:function(a){this.log(this.LogLevel.WARN,a)},error:function(a){this.log(this.LogLevel.ERROR,a)},fatal:function(a){this.log(this.LogLevel.FATAL,a)},serialize:function(a){var b;if(!a)return null;"function"==typeof a.tree&&(a=a.tree());var c,d,e=a.nodeName;for(a.getAttribute("_realname")&&(e=a.getAttribute("_realname")),b="<"+e,c=0;c/g,">").replace(/0){for(b+=">",c=0;c"}b+=""}else b+="/>";return b},_requestId:0,_connectionPlugins:{},addConnectionPlugin:function(a,b){f._connectionPlugins[a]=b}},f.Builder=function(a,b){("presence"==a||"message"==a||"iq"==a)&&(b&&!b.xmlns?b.xmlns=f.NS.CLIENT:b||(b={xmlns:f.NS.CLIENT})),this.nodeTree=f.xmlElement(a,b),this.node=this.nodeTree},f.Builder.prototype={tree:function(){return this.nodeTree},toString:function(){return f.serialize(this.nodeTree)},up:function(){return this.node=this.node.parentNode,this},attrs:function(a){for(var b in a)a.hasOwnProperty(b)&&this.node.setAttribute(b,a[b]);return this},c:function(a,b,c){var d=f.xmlElement(a,b,c);return this.node.appendChild(d),c||(this.node=d),this},cnode:function(a){var b,c=f.xmlGenerator();try{b=void 0!==c.importNode}catch(d){b=!1}var e=b?c.importNode(a,!0):f.copyElement(a);return this.node.appendChild(e),this.node=e,this},t:function(a){var b=f.xmlTextNode(a);return this.node.appendChild(b),this},h:function(a){var b=document.createElement("body");b.innerHTML=a;for(var c=f.createHtml(b);c.childNodes.length>0;)this.node.appendChild(c.childNodes[0]);return this}},f.Handler=function(a,b,c,d,e,g,h){this.handler=a,this.ns=b,this.name=c,this.type=d,this.id=e,this.options=h||{matchBare:!1},this.options.matchBare||(this.options.matchBare=!1),this.from=this.options.matchBare?g?f.getBareJidFromJid(g):null:g,this.user=!0},f.Handler.prototype={isMatch:function(a){var b,c=null;if(c=this.options.matchBare?f.getBareJidFromJid(a.getAttribute("from")):a.getAttribute("from"),b=!1,this.ns){var d=this;f.forEachChild(a,null,function(a){a.getAttribute("xmlns")==d.ns&&(b=!0)}),b=b||a.getAttribute("xmlns")==this.ns}else b=!0;return!b||this.name&&!f.isTagEqual(a,this.name)||this.type&&a.getAttribute("type")!=this.type||this.id&&a.getAttribute("id")!=this.id||this.from&&c!=this.from?!1:!0},run:function(a){var b=null;try{b=this.handler(a)}catch(c){throw c.sourceURL?f.fatal("error: "+this.handler+" "+c.sourceURL+":"+c.line+" - "+c.name+": "+c.message):c.fileName?("undefined"!=typeof console&&(console.trace(),console.error(this.handler," - error - ",c,c.message)),f.fatal("error: "+this.handler+" "+c.fileName+":"+c.lineNumber+" - "+c.name+": "+c.message)):f.fatal("error: "+c.message+"\n"+c.stack),c}return b},toString:function(){return"{Handler: "+this.handler+"("+this.name+","+this.id+","+this.ns+")}"}},f.TimedHandler=function(a,b){this.period=a,this.handler=b,this.lastCalled=(new Date).getTime(),this.user=!0},f.TimedHandler.prototype={run:function(){return this.lastCalled=(new Date).getTime(),this.handler()},reset:function(){this.lastCalled=(new Date).getTime()},toString:function(){return"{TimedHandler: "+this.handler+"("+this.period+")}"}},f.Connection=function(a,b){this.service=a,this.options=b||{};var c=this.options.protocol||"";this._proto=0===a.indexOf("ws:")||0===a.indexOf("wss:")||0===c.indexOf("ws")?new f.Websocket(this):new f.Bosh(this),this.jid="",this.domain=null,this.features=null,this._sasl_data={},this.do_session=!1,this.do_bind=!1,this.timedHandlers=[],this.handlers=[],this.removeTimeds=[],this.removeHandlers=[],this.addTimeds=[],this.addHandlers=[],this._authentication={},this._idleTimeout=null,this._disconnectTimeout=null,this.do_authentication=!0,this.authenticated=!1,this.disconnecting=!1,this.connected=!1,this.errors=0,this.paused=!1,this._data=[],this._uniqueId=0,this._sasl_success_handler=null,this._sasl_failure_handler=null,this._sasl_challenge_handler=null,this.maxRetries=5,this._idleTimeout=setTimeout(this._onIdle.bind(this),100);for(var d in f._connectionPlugins)if(f._connectionPlugins.hasOwnProperty(d)){var e=f._connectionPlugins[d],g=function(){};g.prototype=e,this[d]=new g,this[d].init(this)}},f.Connection.prototype={reset:function(){this._proto._reset(),this.do_session=!1,this.do_bind=!1,this.timedHandlers=[],this.handlers=[],this.removeTimeds=[],this.removeHandlers=[],this.addTimeds=[],this.addHandlers=[],this._authentication={},this.authenticated=!1,this.disconnecting=!1,this.connected=!1,this.errors=0,this._requests=[],this._uniqueId=0},pause:function(){this.paused=!0},resume:function(){this.paused=!1},getUniqueId:function(a){return"string"==typeof a||"number"==typeof a?++this._uniqueId+":"+a:++this._uniqueId+""},connect:function(a,b,c,d,e,g){this.jid=a,this.authzid=f.getBareJidFromJid(this.jid),this.authcid=f.getNodeFromJid(this.jid),this.pass=b,this.servtype="xmpp",this.connect_callback=c,this.disconnecting=!1,this.connected=!1,this.authenticated=!1,this.errors=0,this.domain=this.domain||f.getDomainFromJid(this.jid),this._changeConnectStatus(f.Status.CONNECTING,null),this._proto._connect(d,e,g)},attach:function(a,b,c,d,e,f,g){this._proto._attach(a,b,c,d,e,f,g)},xmlInput:function(){},xmlOutput:function(){},rawInput:function(){},rawOutput:function(){},send:function(a){if(null!==a){if("function"==typeof a.sort)for(var b=0;b0;)e=this.removeHandlers.pop(),d=this.handlers.indexOf(e),d>=0&&this.handlers.splice(d,1);for(;this.addHandlers.length>0;)this.handlers.push(this.addHandlers.pop());if(this.disconnecting&&this._proto._emptyQueue())return this._doDisconnect(),void 0;var g,h,i=c.getAttribute("type");if(null!==i&&"terminate"==i){if(this.disconnecting)return;return g=c.getAttribute("condition"),h=c.getElementsByTagName("conflict"),null!==g?("remote-stream-error"==g&&h.length>0&&(g="conflict"),this._changeConnectStatus(f.Status.CONNFAIL,g)):this._changeConnectStatus(f.Status.CONNFAIL,"unknown"),this.disconnect("unknown stream-error"),void 0}var j=this;f.forEachChild(c,null,function(a){var b,c;for(c=j.handlers,j.handlers=[],b=0;b0;g||(g=d.getElementsByTagName("features").length>0);var h,i,j=d.getElementsByTagName("mechanism"),k=[],l=!1;if(!g)return this._proto._no_auth_received(b),void 0;if(j.length>0)for(h=0;h0,(l=this._authentication.legacy_auth||k.length>0)?(this.do_authentication!==!1&&this.authenticate(k),void 0):(this._proto._no_auth_received(b),void 0)}}},authenticate:function(a){var c;for(c=0;ca[e].prototype.priority&&(e=g);if(e!=c){var h=a[c];a[c]=a[e],a[e]=h}}var i=!1;for(c=0;c0&&(b="conflict"),this._changeConnectStatus(f.Status.AUTHFAIL,b),!1}var e,g=a.getElementsByTagName("bind");return g.length>0?(e=g[0].getElementsByTagName("jid"),e.length>0&&(this.jid=f.getText(e[0]),this.do_session?(this._addSysHandler(this._sasl_session_cb.bind(this),null,null,null,"_session_auth_2"),this.send(d({type:"set",id:"_session_auth_2"}).c("session",{xmlns:f.NS.SESSION}).tree())):(this.authenticated=!0,this._changeConnectStatus(f.Status.CONNECTED,null))),void 0):(f.info("SASL binding failed."),this._changeConnectStatus(f.Status.AUTHFAIL,null),!1)},_sasl_session_cb:function(a){if("result"==a.getAttribute("type"))this.authenticated=!0,this._changeConnectStatus(f.Status.CONNECTED,null);else if("error"==a.getAttribute("type"))return f.info("Session creation failed."),this._changeConnectStatus(f.Status.AUTHFAIL,null),!1;return!1},_sasl_failure_cb:function(){return this._sasl_success_handler&&(this.deleteHandler(this._sasl_success_handler),this._sasl_success_handler=null),this._sasl_challenge_handler&&(this.deleteHandler(this._sasl_challenge_handler),this._sasl_challenge_handler=null),this._sasl_mechanism&&this._sasl_mechanism.onFailure(),this._changeConnectStatus(f.Status.AUTHFAIL,null),!1},_auth2_cb:function(a){return"result"==a.getAttribute("type")?(this.authenticated=!0,this._changeConnectStatus(f.Status.CONNECTED,null)):"error"==a.getAttribute("type")&&(this._changeConnectStatus(f.Status.AUTHFAIL,null),this.disconnect("authentication failed")),!1},_addSysTimedHandler:function(a,b){var c=new f.TimedHandler(a,b);return c.user=!1,this.addTimeds.push(c),c},_addSysHandler:function(a,b,c,d,e){var g=new f.Handler(a,b,c,d,e);return g.user=!1,this.addHandlers.push(g),g},_onDisconnectTimeout:function(){return f.info("_onDisconnectTimeout was called"),this._proto._onDisconnectTimeout(),this._doDisconnect(),!1},_onIdle:function(){for(var a,b,c,d;this.addTimeds.length>0;)this.timedHandlers.push(this.addTimeds.pop());for(;this.removeTimeds.length>0;)b=this.removeTimeds.pop(),a=this.timedHandlers.indexOf(b),a>=0&&this.timedHandlers.splice(a,1);var e=(new Date).getTime();for(d=[],a=0;a=c-e?b.run()&&d.push(b):d.push(b));this.timedHandlers=d;clearTimeout(this._idleTimeout),this._proto._onIdle(),this.connected&&(this._idleTimeout=setTimeout(this._onIdle.bind(this),100))}},a&&a(f,b,c,d,e),f.SASLMechanism=function(a,b,c){this.name=a,this.isClientFirst=b,this.priority=c},f.SASLMechanism.prototype={_sasl_data:{},test:function(){return!0},onStart:function(a){this._connection=a},onChallenge:function(){throw new Error("You should implement challenge handling!")},onFailure:function(){this._connection=null},onSuccess:function(){this._connection=null}},f.SASLAnonymous=function(){},f.SASLAnonymous.prototype=new f.SASLMechanism("ANONYMOUS",!1,10),f.SASLAnonymous.test=function(a){return null===a.authcid},f.Connection.prototype.mechanisms[f.SASLAnonymous.prototype.name]=f.SASLAnonymous,f.SASLPlain=function(){},f.SASLPlain.prototype=new f.SASLMechanism("PLAIN",!0,20),f.SASLPlain.test=function(a){return null!==a.authcid},f.SASLPlain.prototype.onChallenge=function(a){var b=a.authzid;return b+="\x00",b+=a.authcid,b+="\x00",b+=a.pass},f.Connection.prototype.mechanisms[f.SASLPlain.prototype.name]=f.SASLPlain,f.SASLSHA1=function(){},f.SASLSHA1.prototype=new f.SASLMechanism("SCRAM-SHA-1",!0,40),f.SASLSHA1.test=function(a){return null!==a.authcid -},f.SASLSHA1.prototype.onChallenge=function(a,b,c){var d=c||MD5.hexdigest(1234567890*Math.random()),e="n="+a.authcid;return e+=",r=",e+=d,this._sasl_data.cnonce=d,this._sasl_data["client-first-message-bare"]=e,e="n,,"+e,this.onChallenge=function(a,b){for(var c,d,e,f,g,h,j,l,m,n="c=biws,",o=this._sasl_data["client-first-message-bare"]+","+b+",",p=this._sasl_data.cnonce,q=/([a-z]+)=([^,]+)(,|$)/;b.match(q);)switch(matches=b.match(q),b=b.replace(matches[0],""),matches[1]){case"r":c=matches[2];break;case"s":d=matches[2];break;case"i":e=matches[2]}if(c.substr(0,p.length)!==p)return this._sasl_data={},a._sasl_failure_cb();for(n+="r="+c,o+=n,d=Base64.decode(d),d+="\x00\x00\x00",f=h=core_hmac_sha1(a.pass,d),i=1;e>i;i++){for(g=core_hmac_sha1(a.pass,binb2str(h)),k=0;5>k;k++)f[k]^=g[k];h=g}for(f=binb2str(f),j=core_hmac_sha1(f,"Client Key"),l=str_hmac_sha1(f,"Server Key"),m=core_hmac_sha1(str_sha1(binb2str(j)),o),a._sasl_data["server-signature"]=b64_hmac_sha1(l,o),k=0;5>k;k++)j[k]^=m[k];return n+=",p="+Base64.encode(binb2str(j))}.bind(this),e},f.Connection.prototype.mechanisms[f.SASLSHA1.prototype.name]=f.SASLSHA1,f.SASLMD5=function(){},f.SASLMD5.prototype=new f.SASLMechanism("DIGEST-MD5",!1,30),f.SASLMD5.test=function(a){return null!==a.authcid},f.SASLMD5.prototype._quote=function(a){return'"'+a.replace(/\\/g,"\\\\").replace(/"/g,'\\"')+'"'},f.SASLMD5.prototype.onChallenge=function(a,b,c){for(var d,e=/([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/,f=c||MD5.hexdigest(""+1234567890*Math.random()),g="",h=null,i="",j="";b.match(e);)switch(d=b.match(e),b=b.replace(d[0],""),d[2]=d[2].replace(/^"(.+)"$/,"$1"),d[1]){case"realm":g=d[2];break;case"nonce":i=d[2];break;case"qop":j=d[2];break;case"host":h=d[2]}var k=a.servtype+"/"+a.domain;null!==h&&(k=k+"/"+h);var l=MD5.hash(a.authcid+":"+g+":"+this._connection.pass)+":"+i+":"+f,m="AUTHENTICATE:"+k,n="";return n+="charset=utf-8,",n+="username="+this._quote(a.authcid)+",",n+="realm="+this._quote(g)+",",n+="nonce="+this._quote(i)+",",n+="nc=00000001,",n+="cnonce="+this._quote(f)+",",n+="digest-uri="+this._quote(k)+",",n+="response="+MD5.hexdigest(MD5.hexdigest(l)+":"+i+":00000001:"+f+":auth:"+MD5.hexdigest(m))+",",n+="qop=auth",this.onChallenge=function(){return""}.bind(this),n},f.Connection.prototype.mechanisms[f.SASLMD5.prototype.name]=f.SASLMD5}(function(){window.Strophe=arguments[0],window.$build=arguments[1],window.$msg=arguments[2],window.$iq=arguments[3],window.$pres=arguments[4]}),Strophe.Request=function(a,b,c,d){this.id=++Strophe._requestId,this.xmlData=a,this.data=Strophe.serialize(a),this.origFunc=b,this.func=b,this.rid=c,this.date=0/0,this.sends=d||0,this.abort=!1,this.dead=null,this.age=function(){if(!this.date)return 0;var a=new Date;return(a-this.date)/1e3},this.timeDead=function(){if(!this.dead)return 0;var a=new Date;return(a-this.dead)/1e3},this.xhr=this._newXHR()},Strophe.Request.prototype={getResponse:function(){var a=null;if(this.xhr.responseXML&&this.xhr.responseXML.documentElement){if(a=this.xhr.responseXML.documentElement,"parsererror"==a.tagName)throw Strophe.error("invalid response received"),Strophe.error("responseText: "+this.xhr.responseText),Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML)),"parsererror"}else this.xhr.responseText&&(Strophe.error("invalid response received"),Strophe.error("responseText: "+this.xhr.responseText),Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML)));return a},_newXHR:function(){var a=null;return window.XMLHttpRequest?(a=new XMLHttpRequest,a.overrideMimeType&&a.overrideMimeType("text/xml")):window.ActiveXObject&&(a=new ActiveXObject("Microsoft.XMLHTTP")),a.onreadystatechange=this.func.bind(null,this),a}},Strophe.Bosh=function(a){this._conn=a,this.rid=Math.floor(4294967295*Math.random()),this.sid=null,this.hold=1,this.wait=60,this.window=5,this._requests=[]},Strophe.Bosh.prototype={strip:null,_buildBody:function(){var a=$build("body",{rid:this.rid++,xmlns:Strophe.NS.HTTPBIND});return null!==this.sid&&a.attrs({sid:this.sid}),a},_reset:function(){this.rid=Math.floor(4294967295*Math.random()),this.sid=null},_connect:function(a,b,c){this.wait=a||this.wait,this.hold=b||this.hold;var d=this._buildBody().attrs({to:this._conn.domain,"xml:lang":"en",wait:this.wait,hold:this.hold,content:"text/xml; charset=utf-8",ver:"1.6","xmpp:version":"1.0","xmlns:xmpp":Strophe.NS.BOSH});c&&d.attrs({route:c});var e=this._conn._connect_cb;this._requests.push(new Strophe.Request(d.tree(),this._onRequestStateChange.bind(this,e.bind(this._conn)),d.tree().getAttribute("rid"))),this._throttledRequestHandler()},_attach:function(a,b,c,d,e,f,g){this._conn.jid=a,this.sid=b,this.rid=c,this._conn.connect_callback=d,this._conn.domain=Strophe.getDomainFromJid(this._conn.jid),this._conn.authenticated=!0,this._conn.connected=!0,this.wait=e||this.wait,this.hold=f||this.hold,this.window=g||this.window,this._conn._changeConnectStatus(Strophe.Status.ATTACHED,null)},_connect_cb:function(a){var b,c,d=a.getAttribute("type");if(null!==d&&"terminate"==d)return Strophe.error("BOSH-Connection failed: "+b),b=a.getAttribute("condition"),c=a.getElementsByTagName("conflict"),null!==b?("remote-stream-error"==b&&c.length>0&&(b="conflict"),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,b)):this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"unknown"),this._conn._doDisconnect(),Strophe.Status.CONNFAIL;this.sid||(this.sid=a.getAttribute("sid"));var e=a.getAttribute("requests");e&&(this.window=parseInt(e,10));var f=a.getAttribute("hold");f&&(this.hold=parseInt(f,10));var g=a.getAttribute("wait");g&&(this.wait=parseInt(g,10))},_disconnect:function(a){this._sendTerminate(a)},_doDisconnect:function(){this.sid=null,this.rid=Math.floor(4294967295*Math.random())},_emptyQueue:function(){return 0===this._requests.length},_hitError:function(a){this.errors++,Strophe.warn("request errored, status: "+a+", number of errors: "+this.errors),this.errors>4&&this._onDisconnectTimeout()},_no_auth_received:function(a){a=a?a.bind(this._conn):this._conn._connect_cb.bind(this._conn);var b=this._buildBody();this._requests.push(new Strophe.Request(b.tree(),this._onRequestStateChange.bind(this,a.bind(this._conn)),b.tree().getAttribute("rid"))),this._throttledRequestHandler()},_onDisconnectTimeout:function(){for(var a;this._requests.length>0;)a=this._requests.pop(),a.abort=!0,a.xhr.abort(),a.xhr.onreadystatechange=function(){}},_onIdle:function(){var a=this._conn._data;if(this._conn.authenticated&&0===this._requests.length&&0===a.length&&!this._conn.disconnecting&&(Strophe.info("no requests during idle cycle, sending blank request"),a.push(null)),this._requests.length<2&&a.length>0&&!this._conn.paused){for(body=this._buildBody(),i=0;i0&&(time_elapsed=this._requests[0].age(),null!==this._requests[0].dead&&this._requests[0].timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait)&&this._throttledRequestHandler(),time_elapsed>Math.floor(Strophe.TIMEOUT*this.wait)&&(Strophe.warn("Request "+this._requests[0].id+" timed out, over "+Math.floor(Strophe.TIMEOUT*this.wait)+" seconds since last activity"),this._throttledRequestHandler()))},_onRequestStateChange:function(a,b){if(Strophe.debug("request id "+b.id+"."+b.sends+" state changed to "+b.xhr.readyState),b.abort)return b.abort=!1,void 0;var c;if(4==b.xhr.readyState){c=0;try{c=b.xhr.status}catch(d){}if("undefined"==typeof c&&(c=0),this.disconnecting&&c>=400)return this._hitError(c),void 0;var e=this._requests[0]==b,f=this._requests[1]==b;(c>0&&500>c||b.sends>5)&&(this._removeRequest(b),Strophe.debug("request id "+b.id+" should now be removed")),200==c?((f||e&&this._requests.length>0&&this._requests[0].age()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait))&&this._restartRequest(0),Strophe.debug("request id "+b.id+"."+b.sends+" got 200"),a(b),this.errors=0):(Strophe.error("request id "+b.id+"."+b.sends+" error "+c+" happened"),(0===c||c>=400&&600>c||c>=12e3)&&(this._hitError(c),c>=400&&500>c&&(this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING,null),this._conn._doDisconnect()))),c>0&&500>c||b.sends>5||this._throttledRequestHandler()}},_processRequest:function(a){var b=this,c=this._requests[a],d=-1;try{4==c.xhr.readyState&&(d=c.xhr.status)}catch(e){Strophe.error("caught an error in _requests["+a+"], reqStatus: "+d)}if("undefined"==typeof d&&(d=-1),c.sends>this.maxRetries)return this._onDisconnectTimeout(),void 0;var f=c.age(),g=!isNaN(f)&&f>Math.floor(Strophe.TIMEOUT*this.wait),h=null!==c.dead&&c.timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait),i=4==c.xhr.readyState&&(1>d||d>=500);if((g||h||i)&&(h&&Strophe.error("Request "+this._requests[a].id+" timed out (secondary), restarting"),c.abort=!0,c.xhr.abort(),c.xhr.onreadystatechange=function(){},this._requests[a]=new Strophe.Request(c.xmlData,c.origFunc,c.rid,c.sends),c=this._requests[a]),0===c.xhr.readyState){Strophe.debug("request id "+c.id+"."+c.sends+" posting");try{c.xhr.open("POST",this._conn.service,this._conn.options.sync?!1:!0)}catch(j){return Strophe.error("XHR open failed."),this._conn.connected||this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"bad-service"),this._conn.disconnect(),void 0}var k=function(){if(c.date=new Date,b._conn.options.customHeaders){var a=b._conn.options.customHeaders;for(var d in a)a.hasOwnProperty(d)&&c.xhr.setRequestHeader(d,a[d])}c.xhr.send(c.data)};if(c.sends>1){var l=1e3*Math.min(Math.floor(Strophe.TIMEOUT*this.wait),Math.pow(c.sends,3));setTimeout(k,l)}else k();c.sends++,this._conn.xmlOutput!==Strophe.Connection.prototype.xmlOutput&&(c.xmlData.nodeName===this.strip&&c.xmlData.childNodes.length?this._conn.xmlOutput(c.xmlData.childNodes[0]):this._conn.xmlOutput(c.xmlData)),this._conn.rawOutput!==Strophe.Connection.prototype.rawOutput&&this._conn.rawOutput(c.data)}else Strophe.debug("_processRequest: "+(0===a?"first":"second")+" request has readyState of "+c.xhr.readyState)},_removeRequest:function(a){Strophe.debug("removing request");var b;for(b=this._requests.length-1;b>=0;b--)a==this._requests[b]&&this._requests.splice(b,1);a.xhr.onreadystatechange=function(){},this._throttledRequestHandler()},_restartRequest:function(a){var b=this._requests[a];null===b.dead&&(b.dead=new Date),this._processRequest(a)},_reqToData:function(a){try{return a.getResponse()}catch(b){if("parsererror"!=b)throw b;this._conn.disconnect("strophe-parsererror")}},_sendTerminate:function(a){Strophe.info("_sendTerminate was called");var b=this._buildBody().attrs({type:"terminate"});a&&b.cnode(a.tree());var c=new Strophe.Request(b.tree(),this._onRequestStateChange.bind(this,this._conn._dataRecv.bind(this._conn)),b.tree().getAttribute("rid"));this._requests.push(c),this._throttledRequestHandler()},_send:function(){clearTimeout(this._conn._idleTimeout),this._throttledRequestHandler(),this._conn._idleTimeout=setTimeout(this._conn._onIdle.bind(this._conn),100)},_sendRestart:function(){this._throttledRequestHandler(),clearTimeout(this._conn._idleTimeout)},_throttledRequestHandler:function(){this._requests?Strophe.debug("_throttledRequestHandler called with "+this._requests.length+" requests"):Strophe.debug("_throttledRequestHandler called with undefined requests"),this._requests&&0!==this._requests.length&&(this._requests.length>0&&this._processRequest(0),this._requests.length>1&&Math.abs(this._requests[0].rid-this._requests[1].rid)\s*)*/,"");if(""===b)return;b=a.data.replace(//,"");var c=(new DOMParser).parseFromString(b,"text/xml").documentElement;this._conn.xmlInput(c),this._conn.rawInput(a.data),this._handleStreamStart(c)&&(this._connect_cb(c),this.streamStart=a.data.replace(/^$/,""))}else{if(""===a.data)return this._conn.rawInput(a.data),this._conn.xmlInput(document.createElement("stream:stream")),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,error),this._conn._doDisconnect(),void 0;var d=this._streamWrap(a.data),e=(new DOMParser).parseFromString(d,"text/xml").documentElement;this.socket.onmessage=this._onMessage.bind(this),this._conn._connect_cb(e,null,a.data)}},_disconnect:function(a){if(this.socket.readyState!==WebSocket.CLOSED){a&&this._conn.send(a);var b="";this._conn.xmlOutput(document.createElement("stream:stream")),this._conn.rawOutput(b);try{this.socket.send(b)}catch(c){Strophe.info("Couldn't send closing stream tag.")}}this._conn._doDisconnect()},_doDisconnect:function(){Strophe.info("WebSockets _doDisconnect was called"),this._closeSocket()},_streamWrap:function(a){return this.streamStart+a+""},_closeSocket:function(){if(this.socket)try{this.socket.close()}catch(a){}this.socket=null},_emptyQueue:function(){return!0},_onClose:function(){this._conn.connected&&!this._conn.disconnecting?(Strophe.error("Websocket closed unexcectedly"),this._conn._doDisconnect()):Strophe.info("Websocket closed")},_no_auth_received:function(a){Strophe.error("Server did not send any auth methods"),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"Server did not send any auth methods"),a&&(a=a.bind(this._conn),a()),this._conn._doDisconnect()},_onDisconnectTimeout:function(){},_onError:function(a){Strophe.error("Websocket error "+a),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"The WebSocket connection could not be established was disconnected."),this._disconnect()},_onIdle:function(){var a=this._conn._data;if(a.length>0&&!this._conn.paused){for(i=0;i"===a.data){var c="";return this._conn.rawInput(c),this._conn.xmlInput(document.createElement("stream:stream")),this._conn.disconnecting||this._conn._doDisconnect(),void 0}if(0===a.data.search("/,""),b=(new DOMParser).parseFromString(data,"text/xml").documentElement,!this._handleStreamStart(b))return}else data=this._streamWrap(a.data),b=(new DOMParser).parseFromString(data,"text/xml").documentElement;if(!this._check_streamerror(b,Strophe.Status.ERROR))return this._conn.disconnecting&&"presence"===b.firstChild.nodeName&&"unavailable"===b.firstChild.getAttribute("type")?(this._conn.xmlInput(b),this._conn.rawInput(Strophe.serialize(b)),void 0):(this._conn._dataRecv(b,a.data),void 0)},_onOpen:function(){Strophe.info("Websocket open");var a=this._buildStream();this._conn.xmlOutput(a.tree());var b=this._removeClosingTag(a);this._conn.rawOutput(b),this.socket.send(b)},_removeClosingTag:function(a){var b=Strophe.serialize(a);return b=b.replace(/<(stream:stream .*[^\/])\/>$/,"<$1>")},_reqToData:function(a){return a},_send:function(){this._conn.flush()},_sendRestart:function(){clearTimeout(this._conn._idleTimeout),this._conn._onIdle.bind(this._conn)()}},function(){var a,b,c,d=function(a,b){return function(){return a.apply(b,arguments)}};Strophe.addConnectionPlugin("muc",{_connection:null,rooms:{},roomNames:[],init:function(a){return this._connection=a,this._muc_handler=null,Strophe.addNamespace("MUC_OWNER",Strophe.NS.MUC+"#owner"),Strophe.addNamespace("MUC_ADMIN",Strophe.NS.MUC+"#admin"),Strophe.addNamespace("MUC_USER",Strophe.NS.MUC+"#user"),Strophe.addNamespace("MUC_ROOMCONF",Strophe.NS.MUC+"#roomconfig")},join:function(a,b,d,e,f,g,h){var i,j,k=this;return j=this.test_append_nick(a,b),i=$pres({from:this._connection.jid,to:j}).c("x",{xmlns:Strophe.NS.MUC}),null!=h&&(i=i.c("history",h).up),null!=g&&i.cnode(Strophe.xmlElement("password",[],g)),"undefined"!=typeof extended_presence&&null!==extended_presence&&i.up.cnode(extended_presence),null==this._muc_handler&&(this._muc_handler=this._connection.addHandler(function(b){var c,d,e,f,g,h,i,j,l,m;if(c=b.getAttribute("from"),!c)return!0;if(g=c.split("/")[0],!k.rooms[g])return!0;if(a=k.rooms[g],e={},"message"===b.nodeName)e=a._message_handlers;else if("presence"===b.nodeName&&(j=b.getElementsByTagName("x"),j.length>0))for(l=0,m=j.length;m>l;l++)if(h=j[l],i=h.getAttribute("xmlns"),i&&i.match(Strophe.NS.MUC)){e=a._presence_handlers;break}for(f in e)d=e[f],d(b,a)||delete e[f];return!0})),this.rooms.hasOwnProperty(a)||(this.rooms[a]=new c(this,a,b,g),this.roomNames.push(a)),e&&this.rooms[a].addHandler("presence",e),d&&this.rooms[a].addHandler("message",d),f&&this.rooms[a].addHandler("roster",f),this._connection.send(i)},leave:function(a,b,c,d){var e,f,g,h;return e=this.roomNames.indexOf(a),delete this.rooms[a],e>=0&&(this.roomNames.splice(e,1),0===this.roomNames.length&&(this._connection.deleteHandler(this._muc_handler),this._muc_handler=null)),h=this.test_append_nick(a,b),g=this._connection.getUniqueId(),f=$pres({type:"unavailable",id:g,from:this._connection.jid,to:h}),null!=d&&f.c("status",d),null!=c&&this._connection.addHandler(c,null,"presence",null,g),this._connection.send(f),g},message:function(a,b,c,d,e){var f,g,h,i;return i=this.test_append_nick(a,b),e=e||(null!=b?"chat":"groupchat"),g=this._connection.getUniqueId(),f=$msg({to:i,from:this._connection.jid,type:e,id:g}).c("body",{xmlns:Strophe.NS.CLIENT}).t(c),f.up(),null!=d&&(f.c("html",{xmlns:Strophe.NS.XHTML_IM}).c("body",{xmlns:Strophe.NS.XHTML}).t(d),0===f.node.childNodes.length?(h=f.node.parentNode,f.up().up(),f.node.removeChild(h)):f.up().up()),f.c("x",{xmlns:"jabber:x:event"}).c("composing"),this._connection.send(f),g},groupchat:function(a,b,c){return this.message(a,null,b,c)},invite:function(a,b,c){var d,e;return e=this._connection.getUniqueId(),d=$msg({from:this._connection.jid,to:a,id:e}).c("x",{xmlns:Strophe.NS.MUC_USER}).c("invite",{to:b}),null!=c&&d.c("reason",c),this._connection.send(d),e},directInvite:function(a,b,c,d){var e,f,g;return g=this._connection.getUniqueId(),e={xmlns:"jabber:x:conference",jid:a},null!=c&&(e.reason=c),null!=d&&(e.password=d),f=$msg({from:this._connection.jid,to:b,id:g}).c("x",e),this._connection.send(f),g},queryOccupants:function(a,b,c){var d,e;return d={xmlns:Strophe.NS.DISCO_ITEMS},e=$iq({from:this._connection.jid,to:a,type:"get"}).c("query",d),this._connection.sendIQ(e,b,c)},configure:function(a,b,c){var d,e;return d=$iq({to:a,type:"get"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}),e=d.tree(),this._connection.sendIQ(e,b,c)},cancelConfigure:function(a){var b,c;return b=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}).c("x",{xmlns:"jabber:x:data",type:"cancel"}),c=b.tree(),this._connection.sendIQ(c)},saveConfiguration:function(a,b,c,d){var e,f,g,h,i;if(f=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}),"undefined"!=typeof Form&&b instanceof Form)b.type="submit",f.cnode(b.toXML());else for(f.c("x",{xmlns:"jabber:x:data",type:"submit"}),h=0,i=b.length;i>h;h++)e=b[h],f.cnode(e).up();return g=f.tree(),this._connection.sendIQ(g,c,d)},createInstantRoom:function(a,b,c){var d;return d=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}).c("x",{xmlns:"jabber:x:data",type:"submit"}),this._connection.sendIQ(d.tree(),b,c)},setTopic:function(a,b){var c;return c=$msg({to:a,from:this._connection.jid,type:"groupchat"}).c("subject",{xmlns:"jabber:client"}).t(b),this._connection.send(c.tree())},_modifyPrivilege:function(a,b,c,d,e){var f;return f=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_ADMIN}).cnode(b.node),null!=c&&f.c("reason",c),this._connection.sendIQ(f.tree(),d,e)},modifyRole:function(a,b,c,d,e,f){var g;return g=$build("item",{nick:b,role:c}),this._modifyPrivilege(a,g,d,e,f)},kick:function(a,b,c,d,e){return this.modifyRole(a,b,"none",c,d,e)},voice:function(a,b,c,d,e){return this.modifyRole(a,b,"participant",c,d,e)},mute:function(a,b,c,d,e){return this.modifyRole(a,b,"visitor",c,d,e)},op:function(a,b,c,d,e){return this.modifyRole(a,b,"moderator",c,d,e)},deop:function(a,b,c,d,e){return this.modifyRole(a,b,"participant",c,d,e)},modifyAffiliation:function(a,b,c,d,e,f){var g;return g=$build("item",{jid:b,affiliation:c}),this._modifyPrivilege(a,g,d,e,f)},ban:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"outcast",c,d,e)},member:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"member",c,d,e)},revoke:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"none",c,d,e)},owner:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"owner",c,d,e)},admin:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"admin",c,d,e)},changeNick:function(a,b){var c,d;return d=this.test_append_nick(a,b),c=$pres({from:this._connection.jid,to:d,id:this._connection.getUniqueId()}),this._connection.send(c.tree())},setStatus:function(a,b,c,d){var e,f;return f=this.test_append_nick(a,b),e=$pres({from:this._connection.jid,to:f}),null!=c&&e.c("show",c).up(),null!=d&&e.c("status",d),this._connection.send(e.tree())},listRooms:function(a,b,c){var d;return d=$iq({to:a,from:this._connection.jid,type:"get"}).c("query",{xmlns:Strophe.NS.DISCO_ITEMS}),this._connection.sendIQ(d,b,c)},test_append_nick:function(a,b){return a+(null!=b?"/"+Strophe.escapeNode(b):"")}}),c=function(){function b(a,b,c,e){this.client=a,this.name=b,this.nick=c,this.password=e,this._roomRosterHandler=d(this._roomRosterHandler,this),this._addOccupant=d(this._addOccupant,this),this.roster={},this._message_handlers={},this._presence_handlers={},this._roster_handlers={},this._handler_ids=0,a.muc&&(this.client=a.muc),this.name=Strophe.getBareJidFromJid(b),this.addHandler("presence",this._roomRosterHandler)}return b.prototype.join=function(a,b,c){return this.client.join(this.name,this.nick,a,b,c,this.password)},b.prototype.leave=function(a,b){return this.client.leave(this.name,this.nick,a,b),delete this.client.rooms[this.name]},b.prototype.message=function(a,b,c,d){return this.client.message(this.name,a,b,c,d)},b.prototype.groupchat=function(a,b){return this.client.groupchat(this.name,a,b)},b.prototype.invite=function(a,b){return this.client.invite(this.name,a,b)},b.prototype.directInvite=function(a,b){return this.client.directInvite(this.name,a,b,this.password)},b.prototype.configure=function(a){return this.client.configure(this.name,a)},b.prototype.cancelConfigure=function(){return this.client.cancelConfigure(this.name)},b.prototype.saveConfiguration=function(a){return this.client.saveConfiguration(this.name,a)},b.prototype.queryOccupants=function(a,b){return this.client.queryOccupants(this.name,a,b)},b.prototype.setTopic=function(a){return this.client.setTopic(this.name,a)},b.prototype.modifyRole=function(a,b,c,d,e){return this.client.modifyRole(this.name,a,b,c,d,e)},b.prototype.kick=function(a,b,c,d){return this.client.kick(this.name,a,b,c,d)},b.prototype.voice=function(a,b,c,d){return this.client.voice(this.name,a,b,c,d)},b.prototype.mute=function(a,b,c,d){return this.client.mute(this.name,a,b,c,d)},b.prototype.op=function(a,b,c,d){return this.client.op(this.name,a,b,c,d)},b.prototype.deop=function(a,b,c,d){return this.client.deop(this.name,a,b,c,d)},b.prototype.modifyAffiliation=function(a,b,c,d,e){return this.client.modifyAffiliation(this.name,a,b,c,d,e)},b.prototype.ban=function(a,b,c,d){return this.client.ban(this.name,a,b,c,d)},b.prototype.member=function(a,b,c,d){return this.client.member(this.name,a,b,c,d)},b.prototype.revoke=function(a,b,c,d){return this.client.revoke(this.name,a,b,c,d)},b.prototype.owner=function(a,b,c,d){return this.client.owner(this.name,a,b,c,d)},b.prototype.admin=function(a,b,c,d){return this.client.admin(this.name,a,b,c,d)},b.prototype.changeNick=function(a){return this.nick=a,this.client.changeNick(this.name,a)},b.prototype.setStatus=function(a,b){return this.client.setStatus(this.name,this.nick,a,b)},b.prototype.addHandler=function(a,b){var c;switch(c=this._handler_ids++,a){case"presence":this._presence_handlers[c]=b;break;case"message":this._message_handlers[c]=b;break;case"roster":this._roster_handlers[c]=b;break;default:return this._handler_ids--,null}return c},b.prototype.removeHandler=function(a){return delete this._presence_handlers[a],delete this._message_handlers[a],delete this._roster_handlers[a]},b.prototype._addOccupant=function(b){var c;return c=new a(b,this),this.roster[c.nick]=c,c},b.prototype._roomRosterHandler=function(a){var c,d,e,f,g,h;switch(c=b._parsePresence(a),g=c.nick,f=c.newnick||null,c.type){case"error":return;case"unavailable":f&&(c.nick=f,this.roster[g]&&this.roster[f]&&(this.roster[g].update(this.roster[f]),this.roster[f]=this.roster[g]),this.roster[g]&&!this.roster[f]&&(this.roster[f]=this.roster[g].update(c))),delete this.roster[g];break;default:this.roster[g]?this.roster[g].update(c):this._addOccupant(c)}h=this._roster_handlers;for(e in h)d=h[e],d(this.roster,this)||delete this._roster_handlers[e];return!0},b._parsePresence=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q;for(e={},b=a.attributes,e.nick=Strophe.getResourceFromJid(b.from.textContent),e.type=(null!=(j=b.type)?j.textContent:void 0)||null,e.states=[],k=a.childNodes,f=0,h=k.length;h>f;f++)switch(c=k[f],c.nodeName){case"status":e.status=c.textContent||null;break;case"show":e.show=c.textContent||null;break;case"x":if(b=c.attributes,(null!=(l=b.xmlns)?l.textContent:void 0)===Strophe.NS.MUC_USER)for(m=c.childNodes,g=0,i=m.length;i>g;g++)switch(d=m[g],d.nodeName){case"item":b=d.attributes,e.affiliation=(null!=(n=b.affiliation)?n.textContent:void 0)||null,e.role=(null!=(o=b.role)?o.textContent:void 0)||null,e.jid=(null!=(p=b.jid)?p.textContent:void 0)||null,e.newnick=(null!=(q=b.nick)?q.textContent:void 0)||null;break;case"status":d.attributes.code&&e.states.push(d.attributes.code.textContent)}}return e},b}(),b=function(){function a(a){this.parse=d(this.parse,this),null!=a&&this.parse(a)}return a.prototype.parse=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n;for(g=a.getElementsByTagName("query")[0].childNodes,this.identities=[],this.features=[],this.x=[],h=0,k=g.length;k>h;h++)switch(d=g[h],c=d.attributes,d.nodeName){case"identity":for(f={},i=0,l=c.length;l>i;i++)b=c[i],f[b.name]=b.textContent;this.identities.push(f);break;case"feature":this.features.push(c["var"].textContent);break;case"x":if(c=d.childNodes[0].attributes,"FORM_TYPE"===!c["var"].textContent||"hidden"===!c.type.textContent)break;for(n=d.childNodes,j=0,m=n.length;m>j;j++)e=n[j],e.attributes.type||(c=e.attributes,this.x.push({"var":c["var"].textContent,label:c.label.textContent||"",value:e.firstChild.textContent||""}))}return{identities:this.identities,features:this.features,x:this.x}},a}(),a=function(){function a(a,b){this.room=b,this.update=d(this.update,this),this.admin=d(this.admin,this),this.owner=d(this.owner,this),this.revoke=d(this.revoke,this),this.member=d(this.member,this),this.ban=d(this.ban,this),this.modifyAffiliation=d(this.modifyAffiliation,this),this.deop=d(this.deop,this),this.op=d(this.op,this),this.mute=d(this.mute,this),this.voice=d(this.voice,this),this.kick=d(this.kick,this),this.modifyRole=d(this.modifyRole,this),this.update(a)}return a.prototype.modifyRole=function(a,b,c,d){return this.room.modifyRole(this.nick,a,b,c,d)},a.prototype.kick=function(a,b,c){return this.room.kick(this.nick,a,b,c)},a.prototype.voice=function(a,b,c){return this.room.voice(this.nick,a,b,c)},a.prototype.mute=function(a,b,c){return this.room.mute(this.nick,a,b,c)},a.prototype.op=function(a,b,c){return this.room.op(this.nick,a,b,c)},a.prototype.deop=function(a,b,c){return this.room.deop(this.nick,a,b,c)},a.prototype.modifyAffiliation=function(a,b,c,d){return this.room.modifyAffiliation(this.jid,a,b,c,d)},a.prototype.ban=function(a,b,c){return this.room.ban(this.jid,a,b,c)},a.prototype.member=function(a,b,c){return this.room.member(this.jid,a,b,c)},a.prototype.revoke=function(a,b,c){return this.room.revoke(this.jid,a,b,c)},a.prototype.owner=function(a,b,c){return this.room.owner(this.jid,a,b,c)},a.prototype.admin=function(a,b,c){return this.room.admin(this.jid,a,b,c)},a.prototype.update=function(a){return this.nick=a.nick||null,this.affiliation=a.affiliation||null,this.role=a.role||null,this.jid=a.jid||null,this.status=a.status||null,this.show=a.show||null,this},a}()}.call(this),Strophe.addConnectionPlugin("disco",{_connection:null,_identities:[],_features:[],_items:[],init:function(a){this._connection=a,this._identities=[],this._features=[],this._items=[],a.addHandler(this._onDiscoInfo.bind(this),Strophe.NS.DISCO_INFO,"iq","get",null,null),a.addHandler(this._onDiscoItems.bind(this),Strophe.NS.DISCO_ITEMS,"iq","get",null,null)},addIdentity:function(a,b,c,d){for(var e=0;ef;f++){var g=b[f];a+=g.category+"/"+g.type+"/"+g.lang+"/"+g.name+"<"}for(var f=0;e>f;f++)a+=d[f]+"<";return this._ver=b64_sha1(a),this._ver},getCapabilitiesByJid:function(a){return this._jidVerIndex[a]?this._knownCapabilities[this._jidVerIndex[a]]:null},_delegateCapabilities:function(a){var b=a.getAttribute("from"),c=a.querySelector("c"),d=c.getAttribute("ver"),e=c.getAttribute("node");return this._knownCapabilities[d]?(this._jidVerIndex[b]=d,this._jidVerIndex[b]&&!this._jidVerIndex[b]===d||(this._jidVerIndex[b]=d),!0):this._requestCapabilities(b,e,d)},_requestCapabilities:function(a,b,c){if(a!==this._connection.jid){var d=this._connection.disco.info(a,b+"#"+c);this._connection.addHandler(this._handleDiscoInfoReply.bind(this),Strophe.NS.DISCO_INFO,"iq","result",d,a)}return!0},_handleDiscoInfoReply:function(a){var b=a.querySelector("query"),c=b.getAttribute("node").split("#"),d=c[1],e=a.getAttribute("from");if(this._knownCapabilities[d])this._jidVerIndex[e]&&!this._jidVerIndex[e]===d||(this._jidVerIndex[e]=d);else{var f=b.childNodes,g=f.length;this._knownCapabilities[d]=[];for(var h=0;g>h;h++){var c=f[h];this._knownCapabilities[d].push({name:c.nodeName,attributes:c.attributes})}this._jidVerIndex[e]=d}return!1},_sortIdentities:function(a,b){return a.category>b.category?1:a.categoryb.type?1:a.typeb.lang?1:a.lang|\\{|%)?([^\\/#\\^]+?)\\1?"+e.ctag+"+","g")},g=f(),h=function(a,d,h){switch(d){case"!":return"";case"=":return e.set_delimiters(h),g=f(),"";case">":return e.render_partial(h,b,c);case"{":return e.find(h,b);default:return e.escape(e.find(h,b))}},i=a.split("\n"),j=0;j\\]/g,function(a){switch(a){case"&":return"&";case"\\":return"\\\\";case'"':return""";case"'":return"'";case"<":return"<";case">":return">";default:return a}})},create_context:function(a){if(this.is_object(a))return a;var b=".";this.pragmas["IMPLICIT-ITERATOR"]&&(b=this.pragmas["IMPLICIT-ITERATOR"].iterator);var c={};return c[b]=a,c},is_object:function(a){return a&&"object"==typeof a},is_array:function(a){return"[object Array]"===Object.prototype.toString.call(a)},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},map:function(a,b){if("function"==typeof a.map)return a.map(b);for(var c=[],d=a.length,e=0;d>e;e++)c.push(b(a[e]));return c}},{name:"mustache.js",version:"0.3.1-dev",to_html:function(b,c,d,e){var f=new a;return e&&(f.send=e),f.render(b,c,d),e?void 0:f.buffer.join("\n")}}}();!function(a){var b=Array.prototype.slice,c={dict:null,load:function(b){null!==this.dict?a.extend(this.dict,b):this.dict=b},_:function(a){return dict=this.dict,dict&&dict.hasOwnProperty(a)&&(a=dict[a]),args=b.call(arguments),args[0]=a,this.printf.apply(this,args)},printf:function(c,d){return arguments.length<2?c:(d=a.isArray(d)?d:b.call(arguments,1),c.replace(/([^%]|^)%(?:(\d+)\$)?s/g,function(a,b,c){return c?b+d[parseInt(c)-1]:b+d.shift()}).replace(/%%s/g,"%s"))}};a.fn._t=function(){return a(this).html(c._.apply(c,arguments))},a.i18n=c}(jQuery);var dateFormat=function(){var a=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,b=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,c=/[^-+\dA-Z]/g,d=function(a,b){for(a=String(a),b=b||2;a.length99?Math.round(q/10):q),t:12>n?"a":"p",tt:12>n?"am":"pm",T:12>n?"A":"P",TT:12>n?"AM":"PM",Z:g?"UTC":(String(e).match(b)||[""]).pop().replace(c,""),o:(r>0?"-":"+")+d(100*Math.floor(Math.abs(r)/60)+Math.abs(r)%60,4),S:["th","st","nd","rd"][j%10>3?0:(j%100-j%10!=10)*j%10]};return f.replace(a,function(a){return a in s?s[a]:a.slice(1,a.length-1)})}}();dateFormat.masks={"default":"ddd mmm dd yyyy HH:MM:ss",shortDate:"m/d/yy",mediumDate:"mmm d, yyyy",longDate:"mmmm d, yyyy",fullDate:"dddd, mmmm d, yyyy",shortTime:"h:MM TT",mediumTime:"h:MM:ss TT",longTime:"h:MM:ss TT Z",isoDate:"yyyy-mm-dd",isoTime:"HH:MM:ss",isoDateTime:"yyyy-mm-dd'T'HH:MM:ss",isoUtcDateTime:"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"},dateFormat.i18n={dayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"]},Date.prototype.format=function(a,b){return dateFormat(this,a,b)}; \ No newline at end of file +function hex_sha1(a){return binb2hex(core_sha1(str2binb(a),a.length*chrsz))}function b64_sha1(a){return binb2b64(core_sha1(str2binb(a),a.length*chrsz))}function str_sha1(a){return binb2str(core_sha1(str2binb(a),a.length*chrsz))}function hex_hmac_sha1(a,b){return binb2hex(core_hmac_sha1(a,b))}function b64_hmac_sha1(a,b){return binb2b64(core_hmac_sha1(a,b))}function str_hmac_sha1(a,b){return binb2str(core_hmac_sha1(a,b))}function sha1_vm_test(){return"a9993e364706816aba3e25717850c26c9cd0d89d"==hex_sha1("abc")}function core_sha1(a,b){a[b>>5]|=128<<24-b%32,a[(b+64>>9<<4)+15]=b;var c,d,e,f,g,h,i,j,k=new Array(80),l=1732584193,m=-271733879,n=-1732584194,o=271733878,p=-1009589776;for(c=0;cd;d++)k[d]=16>d?a[c+d]:rol(k[d-3]^k[d-8]^k[d-14]^k[d-16],1),e=safe_add(safe_add(rol(l,5),sha1_ft(d,m,n,o)),safe_add(safe_add(p,k[d]),sha1_kt(d))),p=o,o=n,n=rol(m,30),m=l,l=e;l=safe_add(l,f),m=safe_add(m,g),n=safe_add(n,h),o=safe_add(o,i),p=safe_add(p,j)}return[l,m,n,o,p]}function sha1_ft(a,b,c,d){return 20>a?b&c|~b&d:40>a?b^c^d:60>a?b&c|b&d|c&d:b^c^d}function sha1_kt(a){return 20>a?1518500249:40>a?1859775393:60>a?-1894007588:-899497514}function core_hmac_sha1(a,b){var c=str2binb(a);c.length>16&&(c=core_sha1(c,a.length*chrsz));for(var d=new Array(16),e=new Array(16),f=0;16>f;f++)d[f]=909522486^c[f],e[f]=1549556828^c[f];var g=core_sha1(d.concat(str2binb(b)),512+b.length*chrsz);return core_sha1(e.concat(g),672)}function safe_add(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}function rol(a,b){return a<>>32-b}function str2binb(a){for(var b=[],c=(1<>5]|=(a.charCodeAt(d/chrsz)&c)<<32-chrsz-d%32;return b}function binb2str(a){for(var b="",c=(1<>5]>>>32-chrsz-d%32&c);return b}function binb2hex(a){for(var b=hexcase?"0123456789ABCDEF":"0123456789abcdef",c="",d=0;d<4*a.length;d++)c+=b.charAt(a[d>>2]>>8*(3-d%4)+4&15)+b.charAt(a[d>>2]>>8*(3-d%4)&15);return c}function binb2b64(a){for(var b,c,d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",e="",f=0;f<4*a.length;f+=3)for(b=(a[f>>2]>>8*(3-f%4)&255)<<16|(a[f+1>>2]>>8*(3-(f+1)%4)&255)<<8|a[f+2>>2]>>8*(3-(f+2)%4)&255,c=0;4>c;c++)e+=8*f+6*c>32*a.length?b64pad:d.charAt(b>>6*(3-c)&63);return e}var Base64=function(){var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",b={encode:function(b){var c,d,e,f,g,h,i,j="",k=0;do c=b.charCodeAt(k++),d=b.charCodeAt(k++),e=b.charCodeAt(k++),f=c>>2,g=(3&c)<<4|d>>4,h=(15&d)<<2|e>>6,i=63&e,isNaN(d)?h=i=64:isNaN(e)&&(i=64),j=j+a.charAt(f)+a.charAt(g)+a.charAt(h)+a.charAt(i);while(k>4,d=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(c),64!=h&&(j+=String.fromCharCode(d)),64!=i&&(j+=String.fromCharCode(e));while(k>16)+(b>>16)+(c>>16);return d<<16|65535&c},e=function(a,b){return a<>>32-b},f=function(a){for(var b=[],d=(1<>5]|=(a.charCodeAt(e/c)&d)<>5]>>>e%32&d);return b},h=function(b){for(var c=a?"0123456789ABCDEF":"0123456789abcdef",d="",e=0;e<4*b.length;e++)d+=c.charAt(b[e>>2]>>e%4*8+4&15)+c.charAt(b[e>>2]>>e%4*8&15);return d},i=function(a){for(var c,d,e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f="",g=0;g<4*a.length;g+=3)for(c=(a[g>>2]>>8*(g%4)&255)<<16|(a[g+1>>2]>>8*((g+1)%4)&255)<<8|a[g+2>>2]>>8*((g+2)%4)&255,d=0;4>d;d++)f+=8*g+6*d>32*a.length?b:e.charAt(c>>6*(3-d)&63);return f},j=function(a,b,c,f,g,h){return d(e(d(d(b,a),d(f,h)),g),c)},k=function(a,b,c,d,e,f,g){return j(b&c|~b&d,a,b,e,f,g)},l=function(a,b,c,d,e,f,g){return j(b&d|c&~d,a,b,e,f,g)},m=function(a,b,c,d,e,f,g){return j(b^c^d,a,b,e,f,g)},n=function(a,b,c,d,e,f,g){return j(c^(b|~d),a,b,e,f,g)},o=function(a,b){a[b>>5]|=128<>>9<<4)+14]=b;for(var c,e,f,g,h=1732584193,i=-271733879,j=-1732584194,o=271733878,p=0;p16&&(d=o(d,a.length*c));for(var e=new Array(16),g=new Array(16),h=0;16>h;h++)e[h]=909522486^d[h],g[h]=1549556828^d[h];var i=o(e.concat(f(b)),512+b.length*c);return o(g.concat(i),640)},q={hexdigest:function(a){return h(o(f(a),a.length*c))},b64digest:function(a){return i(o(f(a),a.length*c))},hash:function(a){return g(o(f(a),a.length*c))},hmac_hexdigest:function(a,b){return h(p(a,b))},hmac_b64digest:function(a,b){return i(p(a,b))},hmac_hash:function(a,b){return g(p(a,b))},test:function(){return"900150983cd24fb0d6963f7d28e17f72"===MD5.hexdigest("abc")}};return q}();Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice,d=Array.prototype.concat,e=c.call(arguments,1);return function(){return b.apply(a?a:this,d.call(e,c.call(arguments,0)))}}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=this.length,c=Number(arguments[1])||0;for(c=0>c?Math.ceil(c):Math.floor(c),0>c&&(c+=b);b>c;c++)if(c in this&&this[c]===a)return c;return-1}),function(a){function b(a,b){return new f.Builder(a,b)}function c(a){return new f.Builder("message",a)}function d(a){return new f.Builder("iq",a)}function e(a){return new f.Builder("presence",a)}var f;f={VERSION:"a1f13b2",NS:{HTTPBIND:"http://jabber.org/protocol/httpbind",BOSH:"urn:xmpp:xbosh",CLIENT:"jabber:client",AUTH:"jabber:iq:auth",ROSTER:"jabber:iq:roster",PROFILE:"jabber:iq:profile",DISCO_INFO:"http://jabber.org/protocol/disco#info",DISCO_ITEMS:"http://jabber.org/protocol/disco#items",MUC:"http://jabber.org/protocol/muc",SASL:"urn:ietf:params:xml:ns:xmpp-sasl",STREAM:"http://etherx.jabber.org/streams",BIND:"urn:ietf:params:xml:ns:xmpp-bind",SESSION:"urn:ietf:params:xml:ns:xmpp-session",VERSION:"jabber:iq:version",STANZAS:"urn:ietf:params:xml:ns:xmpp-stanzas",XHTML_IM:"http://jabber.org/protocol/xhtml-im",XHTML:"http://www.w3.org/1999/xhtml"},XHTML:{tags:["a","blockquote","br","cite","em","img","li","ol","p","span","strong","ul","body"],attributes:{a:["href"],blockquote:["style"],br:[],cite:["style"],em:[],img:["src","alt","style","height","width"],li:["style"],ol:["style"],p:["style"],span:["style"],strong:[],ul:["style"],body:[]},css:["background-color","color","font-family","font-size","font-style","font-weight","margin-left","margin-right","text-align","text-decoration"],validTag:function(a){for(var b=0;b0)for(var c=0;c/g,">"),a=a.replace(/'/g,"'"),a=a.replace(/"/g,""")},xmlTextNode:function(a){return f.xmlGenerator().createTextNode(a)},xmlHtmlNode:function(a){return window.DOMParser?(parser=new DOMParser,node=parser.parseFromString(a,"text/xml")):(node=new ActiveXObject("Microsoft.XMLDOM"),node.async="false",node.loadXML(a)),node},getText:function(a){if(!a)return null;var b="";0===a.childNodes.length&&a.nodeType==f.ElementType.TEXT&&(b+=a.nodeValue);for(var c=0;c0&&(h=i.join("; "),c.setAttribute(g,h))}else c.setAttribute(g,h);for(b=0;b/g,"\\3e").replace(/@/g,"\\40")},unescapeNode:function(a){return a.replace(/\\20/g," ").replace(/\\22/g,'"').replace(/\\26/g,"&").replace(/\\27/g,"'").replace(/\\2f/g,"/").replace(/\\3a/g,":").replace(/\\3c/g,"<").replace(/\\3e/g,">").replace(/\\40/g,"@").replace(/\\5c/g,"\\")},getNodeFromJid:function(a){return a.indexOf("@")<0?null:a.split("@")[0]},getDomainFromJid:function(a){var b=f.getBareJidFromJid(a);if(b.indexOf("@")<0)return b;var c=b.split("@");return c.splice(0,1),c.join("@")},getResourceFromJid:function(a){var b=a.split("/");return b.length<2?null:(b.splice(0,1),b.join("/"))},getBareJidFromJid:function(a){return a?a.split("/")[0]:null},log:function(){},debug:function(a){this.log(this.LogLevel.DEBUG,a)},info:function(a){this.log(this.LogLevel.INFO,a)},warn:function(a){this.log(this.LogLevel.WARN,a)},error:function(a){this.log(this.LogLevel.ERROR,a)},fatal:function(a){this.log(this.LogLevel.FATAL,a)},serialize:function(a){var b;if(!a)return null;"function"==typeof a.tree&&(a=a.tree());var c,d,e=a.nodeName;for(a.getAttribute("_realname")&&(e=a.getAttribute("_realname")),b="<"+e,c=0;c/g,">").replace(/0){for(b+=">",c=0;c"}b+=""}else b+="/>";return b},_requestId:0,_connectionPlugins:{},addConnectionPlugin:function(a,b){f._connectionPlugins[a]=b}},f.Builder=function(a,b){("presence"==a||"message"==a||"iq"==a)&&(b&&!b.xmlns?b.xmlns=f.NS.CLIENT:b||(b={xmlns:f.NS.CLIENT})),this.nodeTree=f.xmlElement(a,b),this.node=this.nodeTree},f.Builder.prototype={tree:function(){return this.nodeTree},toString:function(){return f.serialize(this.nodeTree)},up:function(){return this.node=this.node.parentNode,this},attrs:function(a){for(var b in a)a.hasOwnProperty(b)&&this.node.setAttribute(b,a[b]);return this},c:function(a,b,c){var d=f.xmlElement(a,b,c);return this.node.appendChild(d),c||(this.node=d),this},cnode:function(a){var b,c=f.xmlGenerator();try{b=void 0!==c.importNode}catch(d){b=!1}var e=b?c.importNode(a,!0):f.copyElement(a);return this.node.appendChild(e),this.node=e,this},t:function(a){var b=f.xmlTextNode(a);return this.node.appendChild(b),this},h:function(a){var b=document.createElement("body");b.innerHTML=a;for(var c=f.createHtml(b);c.childNodes.length>0;)this.node.appendChild(c.childNodes[0]);return this}},f.Handler=function(a,b,c,d,e,g,h){this.handler=a,this.ns=b,this.name=c,this.type=d,this.id=e,this.options=h||{matchBare:!1},this.options.matchBare||(this.options.matchBare=!1),this.from=this.options.matchBare?g?f.getBareJidFromJid(g):null:g,this.user=!0},f.Handler.prototype={isMatch:function(a){var b,c=null;if(c=this.options.matchBare?f.getBareJidFromJid(a.getAttribute("from")):a.getAttribute("from"),b=!1,this.ns){var d=this;f.forEachChild(a,null,function(a){a.getAttribute("xmlns")==d.ns&&(b=!0)}),b=b||a.getAttribute("xmlns")==this.ns}else b=!0;return!b||this.name&&!f.isTagEqual(a,this.name)||this.type&&a.getAttribute("type")!=this.type||this.id&&a.getAttribute("id")!=this.id||this.from&&c!=this.from?!1:!0},run:function(a){var b=null;try{b=this.handler(a)}catch(c){throw c.sourceURL?f.fatal("error: "+this.handler+" "+c.sourceURL+":"+c.line+" - "+c.name+": "+c.message):c.fileName?("undefined"!=typeof console&&(console.trace(),console.error(this.handler," - error - ",c,c.message)),f.fatal("error: "+this.handler+" "+c.fileName+":"+c.lineNumber+" - "+c.name+": "+c.message)):f.fatal("error: "+c.message+"\n"+c.stack),c}return b},toString:function(){return"{Handler: "+this.handler+"("+this.name+","+this.id+","+this.ns+")}"}},f.TimedHandler=function(a,b){this.period=a,this.handler=b,this.lastCalled=(new Date).getTime(),this.user=!0},f.TimedHandler.prototype={run:function(){return this.lastCalled=(new Date).getTime(),this.handler()},reset:function(){this.lastCalled=(new Date).getTime()},toString:function(){return"{TimedHandler: "+this.handler+"("+this.period+")}"}},f.Connection=function(a,b){this.service=a,this.options=b||{};var c=this.options.protocol||"";this._proto=0===a.indexOf("ws:")||0===a.indexOf("wss:")||0===c.indexOf("ws")?new f.Websocket(this):new f.Bosh(this),this.jid="",this.domain=null,this.features=null,this._sasl_data={},this.do_session=!1,this.do_bind=!1,this.timedHandlers=[],this.handlers=[],this.removeTimeds=[],this.removeHandlers=[],this.addTimeds=[],this.addHandlers=[],this._authentication={},this._idleTimeout=null,this._disconnectTimeout=null,this.do_authentication=!0,this.authenticated=!1,this.disconnecting=!1,this.connected=!1,this.errors=0,this.paused=!1,this._data=[],this._uniqueId=0,this._sasl_success_handler=null,this._sasl_failure_handler=null,this._sasl_challenge_handler=null,this.maxRetries=5,this._idleTimeout=setTimeout(this._onIdle.bind(this),100);for(var d in f._connectionPlugins)if(f._connectionPlugins.hasOwnProperty(d)){var e=f._connectionPlugins[d],g=function(){};g.prototype=e,this[d]=new g,this[d].init(this)}},f.Connection.prototype={reset:function(){this._proto._reset(),this.do_session=!1,this.do_bind=!1,this.timedHandlers=[],this.handlers=[],this.removeTimeds=[],this.removeHandlers=[],this.addTimeds=[],this.addHandlers=[],this._authentication={},this.authenticated=!1,this.disconnecting=!1,this.connected=!1,this.errors=0,this._requests=[],this._uniqueId=0},pause:function(){this.paused=!0},resume:function(){this.paused=!1},getUniqueId:function(a){return"string"==typeof a||"number"==typeof a?++this._uniqueId+":"+a:++this._uniqueId+""},connect:function(a,b,c,d,e,g){this.jid=a,this.authzid=f.getBareJidFromJid(this.jid),this.authcid=f.getNodeFromJid(this.jid),this.pass=b,this.servtype="xmpp",this.connect_callback=c,this.disconnecting=!1,this.connected=!1,this.authenticated=!1,this.errors=0,this.domain=this.domain||f.getDomainFromJid(this.jid),this._changeConnectStatus(f.Status.CONNECTING,null),this._proto._connect(d,e,g)},attach:function(a,b,c,d,e,f,g){this._proto._attach(a,b,c,d,e,f,g)},xmlInput:function(){},xmlOutput:function(){},rawInput:function(){},rawOutput:function(){},send:function(a){if(null!==a){if("function"==typeof a.sort)for(var b=0;b0;)e=this.removeHandlers.pop(),d=this.handlers.indexOf(e),d>=0&&this.handlers.splice(d,1);for(;this.addHandlers.length>0;)this.handlers.push(this.addHandlers.pop());if(this.disconnecting&&this._proto._emptyQueue())return void this._doDisconnect();var g,h,i=c.getAttribute("type");if(null!==i&&"terminate"==i){if(this.disconnecting)return;return g=c.getAttribute("condition"),h=c.getElementsByTagName("conflict"),null!==g?("remote-stream-error"==g&&h.length>0&&(g="conflict"),this._changeConnectStatus(f.Status.CONNFAIL,g)):this._changeConnectStatus(f.Status.CONNFAIL,"unknown"),void this.disconnect("unknown stream-error")}var j=this;f.forEachChild(c,null,function(a){var b,c;for(c=j.handlers,j.handlers=[],b=0;b0;g||(g=d.getElementsByTagName("features").length>0);var h,i,j=d.getElementsByTagName("mechanism"),k=[],l=!1;if(!g)return void this._proto._no_auth_received(b);if(j.length>0)for(h=0;h0,(l=this._authentication.legacy_auth||k.length>0)?void(this.do_authentication!==!1&&this.authenticate(k)):void this._proto._no_auth_received(b)}}},authenticate:function(a){var c;for(c=0;ca[e].prototype.priority&&(e=g);if(e!=c){var h=a[c];a[c]=a[e],a[e]=h}}var i=!1;for(c=0;c0&&(b="conflict"),this._changeConnectStatus(f.Status.AUTHFAIL,b),!1}var e,g=a.getElementsByTagName("bind");return g.length>0?(e=g[0].getElementsByTagName("jid"),void(e.length>0&&(this.jid=f.getText(e[0]),this.do_session?(this._addSysHandler(this._sasl_session_cb.bind(this),null,null,null,"_session_auth_2"),this.send(d({type:"set",id:"_session_auth_2"}).c("session",{xmlns:f.NS.SESSION}).tree())):(this.authenticated=!0,this._changeConnectStatus(f.Status.CONNECTED,null))))):(f.info("SASL binding failed."),this._changeConnectStatus(f.Status.AUTHFAIL,null),!1)},_sasl_session_cb:function(a){if("result"==a.getAttribute("type"))this.authenticated=!0,this._changeConnectStatus(f.Status.CONNECTED,null);else if("error"==a.getAttribute("type"))return f.info("Session creation failed."),this._changeConnectStatus(f.Status.AUTHFAIL,null),!1;return!1},_sasl_failure_cb:function(){return this._sasl_success_handler&&(this.deleteHandler(this._sasl_success_handler),this._sasl_success_handler=null),this._sasl_challenge_handler&&(this.deleteHandler(this._sasl_challenge_handler),this._sasl_challenge_handler=null),this._sasl_mechanism&&this._sasl_mechanism.onFailure(),this._changeConnectStatus(f.Status.AUTHFAIL,null),!1},_auth2_cb:function(a){return"result"==a.getAttribute("type")?(this.authenticated=!0,this._changeConnectStatus(f.Status.CONNECTED,null)):"error"==a.getAttribute("type")&&(this._changeConnectStatus(f.Status.AUTHFAIL,null),this.disconnect("authentication failed")),!1},_addSysTimedHandler:function(a,b){var c=new f.TimedHandler(a,b);return c.user=!1,this.addTimeds.push(c),c},_addSysHandler:function(a,b,c,d,e){var g=new f.Handler(a,b,c,d,e);return g.user=!1,this.addHandlers.push(g),g},_onDisconnectTimeout:function(){return f.info("_onDisconnectTimeout was called"),this._proto._onDisconnectTimeout(),this._doDisconnect(),!1},_onIdle:function(){for(var a,b,c,d;this.addTimeds.length>0;)this.timedHandlers.push(this.addTimeds.pop());for(;this.removeTimeds.length>0;)b=this.removeTimeds.pop(),a=this.timedHandlers.indexOf(b),a>=0&&this.timedHandlers.splice(a,1);var e=(new Date).getTime();for(d=[],a=0;a=c-e?b.run()&&d.push(b):d.push(b));this.timedHandlers=d;clearTimeout(this._idleTimeout),this._proto._onIdle(),this.connected&&(this._idleTimeout=setTimeout(this._onIdle.bind(this),100))}},a&&a(f,b,c,d,e),f.SASLMechanism=function(a,b,c){this.name=a,this.isClientFirst=b,this.priority=c},f.SASLMechanism.prototype={_sasl_data:{},test:function(){return!0},onStart:function(a){this._connection=a},onChallenge:function(){throw new Error("You should implement challenge handling!")},onFailure:function(){this._connection=null},onSuccess:function(){this._connection=null}},f.SASLAnonymous=function(){},f.SASLAnonymous.prototype=new f.SASLMechanism("ANONYMOUS",!1,10),f.SASLAnonymous.test=function(a){return null===a.authcid},f.Connection.prototype.mechanisms[f.SASLAnonymous.prototype.name]=f.SASLAnonymous,f.SASLPlain=function(){},f.SASLPlain.prototype=new f.SASLMechanism("PLAIN",!0,20),f.SASLPlain.test=function(a){return null!==a.authcid},f.SASLPlain.prototype.onChallenge=function(a){var b=a.authzid;return b+="\x00",b+=a.authcid,b+="\x00",b+=a.pass},f.Connection.prototype.mechanisms[f.SASLPlain.prototype.name]=f.SASLPlain,f.SASLSHA1=function(){},f.SASLSHA1.prototype=new f.SASLMechanism("SCRAM-SHA-1",!0,40),f.SASLSHA1.test=function(a){return null!==a.authcid},f.SASLSHA1.prototype.onChallenge=function(a,b,c){var d=c||MD5.hexdigest(1234567890*Math.random()),e="n="+a.authcid; +return e+=",r=",e+=d,this._sasl_data.cnonce=d,this._sasl_data["client-first-message-bare"]=e,e="n,,"+e,this.onChallenge=function(a,b){for(var c,d,e,f,g,h,j,l,m,n="c=biws,",o=this._sasl_data["client-first-message-bare"]+","+b+",",p=this._sasl_data.cnonce,q=/([a-z]+)=([^,]+)(,|$)/;b.match(q);)switch(matches=b.match(q),b=b.replace(matches[0],""),matches[1]){case"r":c=matches[2];break;case"s":d=matches[2];break;case"i":e=matches[2]}if(c.substr(0,p.length)!==p)return this._sasl_data={},a._sasl_failure_cb();for(n+="r="+c,o+=n,d=Base64.decode(d),d+="\x00\x00\x00",f=h=core_hmac_sha1(a.pass,d),i=1;e>i;i++){for(g=core_hmac_sha1(a.pass,binb2str(h)),k=0;5>k;k++)f[k]^=g[k];h=g}for(f=binb2str(f),j=core_hmac_sha1(f,"Client Key"),l=str_hmac_sha1(f,"Server Key"),m=core_hmac_sha1(str_sha1(binb2str(j)),o),a._sasl_data["server-signature"]=b64_hmac_sha1(l,o),k=0;5>k;k++)j[k]^=m[k];return n+=",p="+Base64.encode(binb2str(j))}.bind(this),e},f.Connection.prototype.mechanisms[f.SASLSHA1.prototype.name]=f.SASLSHA1,f.SASLMD5=function(){},f.SASLMD5.prototype=new f.SASLMechanism("DIGEST-MD5",!1,30),f.SASLMD5.test=function(a){return null!==a.authcid},f.SASLMD5.prototype._quote=function(a){return'"'+a.replace(/\\/g,"\\\\").replace(/"/g,'\\"')+'"'},f.SASLMD5.prototype.onChallenge=function(a,b,c){for(var d,e=/([a-z]+)=("[^"]+"|[^,"]+)(?:,|$)/,f=c||MD5.hexdigest(""+1234567890*Math.random()),g="",h=null,i="",j="";b.match(e);)switch(d=b.match(e),b=b.replace(d[0],""),d[2]=d[2].replace(/^"(.+)"$/,"$1"),d[1]){case"realm":g=d[2];break;case"nonce":i=d[2];break;case"qop":j=d[2];break;case"host":h=d[2]}var k=a.servtype+"/"+a.domain;null!==h&&(k=k+"/"+h);var l=MD5.hash(a.authcid+":"+g+":"+this._connection.pass)+":"+i+":"+f,m="AUTHENTICATE:"+k,n="";return n+="charset=utf-8,",n+="username="+this._quote(a.authcid)+",",n+="realm="+this._quote(g)+",",n+="nonce="+this._quote(i)+",",n+="nc=00000001,",n+="cnonce="+this._quote(f)+",",n+="digest-uri="+this._quote(k)+",",n+="response="+MD5.hexdigest(MD5.hexdigest(l)+":"+i+":00000001:"+f+":auth:"+MD5.hexdigest(m))+",",n+="qop=auth",this.onChallenge=function(){return""}.bind(this),n},f.Connection.prototype.mechanisms[f.SASLMD5.prototype.name]=f.SASLMD5}(function(){window.Strophe=arguments[0],window.$build=arguments[1],window.$msg=arguments[2],window.$iq=arguments[3],window.$pres=arguments[4]}),Strophe.Request=function(a,b,c,d){this.id=++Strophe._requestId,this.xmlData=a,this.data=Strophe.serialize(a),this.origFunc=b,this.func=b,this.rid=c,this.date=0/0,this.sends=d||0,this.abort=!1,this.dead=null,this.age=function(){if(!this.date)return 0;var a=new Date;return(a-this.date)/1e3},this.timeDead=function(){if(!this.dead)return 0;var a=new Date;return(a-this.dead)/1e3},this.xhr=this._newXHR()},Strophe.Request.prototype={getResponse:function(){var a=null;if(this.xhr.responseXML&&this.xhr.responseXML.documentElement){if(a=this.xhr.responseXML.documentElement,"parsererror"==a.tagName)throw Strophe.error("invalid response received"),Strophe.error("responseText: "+this.xhr.responseText),Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML)),"parsererror"}else this.xhr.responseText&&(Strophe.error("invalid response received"),Strophe.error("responseText: "+this.xhr.responseText),Strophe.error("responseXML: "+Strophe.serialize(this.xhr.responseXML)));return a},_newXHR:function(){var a=null;return window.XMLHttpRequest?(a=new XMLHttpRequest,a.overrideMimeType&&a.overrideMimeType("text/xml")):window.ActiveXObject&&(a=new ActiveXObject("Microsoft.XMLHTTP")),a.onreadystatechange=this.func.bind(null,this),a}},Strophe.Bosh=function(a){this._conn=a,this.rid=Math.floor(4294967295*Math.random()),this.sid=null,this.hold=1,this.wait=60,this.window=5,this._requests=[]},Strophe.Bosh.prototype={strip:null,_buildBody:function(){var a=$build("body",{rid:this.rid++,xmlns:Strophe.NS.HTTPBIND});return null!==this.sid&&a.attrs({sid:this.sid}),a},_reset:function(){this.rid=Math.floor(4294967295*Math.random()),this.sid=null},_connect:function(a,b,c){this.wait=a||this.wait,this.hold=b||this.hold;var d=this._buildBody().attrs({to:this._conn.domain,"xml:lang":"en",wait:this.wait,hold:this.hold,content:"text/xml; charset=utf-8",ver:"1.6","xmpp:version":"1.0","xmlns:xmpp":Strophe.NS.BOSH});c&&d.attrs({route:c});var e=this._conn._connect_cb;this._requests.push(new Strophe.Request(d.tree(),this._onRequestStateChange.bind(this,e.bind(this._conn)),d.tree().getAttribute("rid"))),this._throttledRequestHandler()},_attach:function(a,b,c,d,e,f,g){this._conn.jid=a,this.sid=b,this.rid=c,this._conn.connect_callback=d,this._conn.domain=Strophe.getDomainFromJid(this._conn.jid),this._conn.authenticated=!0,this._conn.connected=!0,this.wait=e||this.wait,this.hold=f||this.hold,this.window=g||this.window,this._conn._changeConnectStatus(Strophe.Status.ATTACHED,null)},_connect_cb:function(a){var b,c,d=a.getAttribute("type");if(null!==d&&"terminate"==d)return Strophe.error("BOSH-Connection failed: "+b),b=a.getAttribute("condition"),c=a.getElementsByTagName("conflict"),null!==b?("remote-stream-error"==b&&c.length>0&&(b="conflict"),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,b)):this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"unknown"),this._conn._doDisconnect(),Strophe.Status.CONNFAIL;this.sid||(this.sid=a.getAttribute("sid"));var e=a.getAttribute("requests");e&&(this.window=parseInt(e,10));var f=a.getAttribute("hold");f&&(this.hold=parseInt(f,10));var g=a.getAttribute("wait");g&&(this.wait=parseInt(g,10))},_disconnect:function(a){this._sendTerminate(a)},_doDisconnect:function(){this.sid=null,this.rid=Math.floor(4294967295*Math.random())},_emptyQueue:function(){return 0===this._requests.length},_hitError:function(a){this.errors++,Strophe.warn("request errored, status: "+a+", number of errors: "+this.errors),this.errors>4&&this._onDisconnectTimeout()},_no_auth_received:function(a){a=a?a.bind(this._conn):this._conn._connect_cb.bind(this._conn);var b=this._buildBody();this._requests.push(new Strophe.Request(b.tree(),this._onRequestStateChange.bind(this,a.bind(this._conn)),b.tree().getAttribute("rid"))),this._throttledRequestHandler()},_onDisconnectTimeout:function(){for(var a;this._requests.length>0;)a=this._requests.pop(),a.abort=!0,a.xhr.abort(),a.xhr.onreadystatechange=function(){}},_onIdle:function(){var a=this._conn._data;if(this._conn.authenticated&&0===this._requests.length&&0===a.length&&!this._conn.disconnecting&&(Strophe.info("no requests during idle cycle, sending blank request"),a.push(null)),this._requests.length<2&&a.length>0&&!this._conn.paused){for(body=this._buildBody(),i=0;i0&&(time_elapsed=this._requests[0].age(),null!==this._requests[0].dead&&this._requests[0].timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait)&&this._throttledRequestHandler(),time_elapsed>Math.floor(Strophe.TIMEOUT*this.wait)&&(Strophe.warn("Request "+this._requests[0].id+" timed out, over "+Math.floor(Strophe.TIMEOUT*this.wait)+" seconds since last activity"),this._throttledRequestHandler()))},_onRequestStateChange:function(a,b){if(Strophe.debug("request id "+b.id+"."+b.sends+" state changed to "+b.xhr.readyState),b.abort)return void(b.abort=!1);var c;if(4==b.xhr.readyState){c=0;try{c=b.xhr.status}catch(d){}if("undefined"==typeof c&&(c=0),this.disconnecting&&c>=400)return void this._hitError(c);var e=this._requests[0]==b,f=this._requests[1]==b;(c>0&&500>c||b.sends>5)&&(this._removeRequest(b),Strophe.debug("request id "+b.id+" should now be removed")),200==c?((f||e&&this._requests.length>0&&this._requests[0].age()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait))&&this._restartRequest(0),Strophe.debug("request id "+b.id+"."+b.sends+" got 200"),a(b),this.errors=0):(Strophe.error("request id "+b.id+"."+b.sends+" error "+c+" happened"),(0===c||c>=400&&600>c||c>=12e3)&&(this._hitError(c),c>=400&&500>c&&(this._conn._changeConnectStatus(Strophe.Status.DISCONNECTING,null),this._conn._doDisconnect()))),c>0&&500>c||b.sends>5||this._throttledRequestHandler()}},_processRequest:function(a){var b=this,c=this._requests[a],d=-1;try{4==c.xhr.readyState&&(d=c.xhr.status)}catch(e){Strophe.error("caught an error in _requests["+a+"], reqStatus: "+d)}if("undefined"==typeof d&&(d=-1),c.sends>this.maxRetries)return void this._onDisconnectTimeout();var f=c.age(),g=!isNaN(f)&&f>Math.floor(Strophe.TIMEOUT*this.wait),h=null!==c.dead&&c.timeDead()>Math.floor(Strophe.SECONDARY_TIMEOUT*this.wait),i=4==c.xhr.readyState&&(1>d||d>=500);if((g||h||i)&&(h&&Strophe.error("Request "+this._requests[a].id+" timed out (secondary), restarting"),c.abort=!0,c.xhr.abort(),c.xhr.onreadystatechange=function(){},this._requests[a]=new Strophe.Request(c.xmlData,c.origFunc,c.rid,c.sends),c=this._requests[a]),0===c.xhr.readyState){Strophe.debug("request id "+c.id+"."+c.sends+" posting");try{c.xhr.open("POST",this._conn.service,this._conn.options.sync?!1:!0)}catch(j){return Strophe.error("XHR open failed."),this._conn.connected||this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"bad-service"),void this._conn.disconnect()}var k=function(){if(c.date=new Date,b._conn.options.customHeaders){var a=b._conn.options.customHeaders;for(var d in a)a.hasOwnProperty(d)&&c.xhr.setRequestHeader(d,a[d])}c.xhr.send(c.data)};if(c.sends>1){var l=1e3*Math.min(Math.floor(Strophe.TIMEOUT*this.wait),Math.pow(c.sends,3));setTimeout(k,l)}else k();c.sends++,this._conn.xmlOutput!==Strophe.Connection.prototype.xmlOutput&&this._conn.xmlOutput(c.xmlData.nodeName===this.strip&&c.xmlData.childNodes.length?c.xmlData.childNodes[0]:c.xmlData),this._conn.rawOutput!==Strophe.Connection.prototype.rawOutput&&this._conn.rawOutput(c.data)}else Strophe.debug("_processRequest: "+(0===a?"first":"second")+" request has readyState of "+c.xhr.readyState)},_removeRequest:function(a){Strophe.debug("removing request");var b;for(b=this._requests.length-1;b>=0;b--)a==this._requests[b]&&this._requests.splice(b,1);a.xhr.onreadystatechange=function(){},this._throttledRequestHandler()},_restartRequest:function(a){var b=this._requests[a];null===b.dead&&(b.dead=new Date),this._processRequest(a)},_reqToData:function(a){try{return a.getResponse()}catch(b){if("parsererror"!=b)throw b;this._conn.disconnect("strophe-parsererror")}},_sendTerminate:function(a){Strophe.info("_sendTerminate was called");var b=this._buildBody().attrs({type:"terminate"});a&&b.cnode(a.tree());var c=new Strophe.Request(b.tree(),this._onRequestStateChange.bind(this,this._conn._dataRecv.bind(this._conn)),b.tree().getAttribute("rid"));this._requests.push(c),this._throttledRequestHandler()},_send:function(){clearTimeout(this._conn._idleTimeout),this._throttledRequestHandler(),this._conn._idleTimeout=setTimeout(this._conn._onIdle.bind(this._conn),100)},_sendRestart:function(){this._throttledRequestHandler(),clearTimeout(this._conn._idleTimeout)},_throttledRequestHandler:function(){Strophe.debug(this._requests?"_throttledRequestHandler called with "+this._requests.length+" requests":"_throttledRequestHandler called with undefined requests"),this._requests&&0!==this._requests.length&&(this._requests.length>0&&this._processRequest(0),this._requests.length>1&&Math.abs(this._requests[0].rid-this._requests[1].rid)\s*)*/,"");if(""===b)return;b=a.data.replace(//,"");var c=(new DOMParser).parseFromString(b,"text/xml").documentElement;this._conn.xmlInput(c),this._conn.rawInput(a.data),this._handleStreamStart(c)&&(this._connect_cb(c),this.streamStart=a.data.replace(/^$/,""))}else{if(""===a.data)return this._conn.rawInput(a.data),this._conn.xmlInput(document.createElement("stream:stream")),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,error),void this._conn._doDisconnect();var d=this._streamWrap(a.data),e=(new DOMParser).parseFromString(d,"text/xml").documentElement;this.socket.onmessage=this._onMessage.bind(this),this._conn._connect_cb(e,null,a.data)}},_disconnect:function(a){if(this.socket.readyState!==WebSocket.CLOSED){a&&this._conn.send(a);var b="";this._conn.xmlOutput(document.createElement("stream:stream")),this._conn.rawOutput(b);try{this.socket.send(b)}catch(c){Strophe.info("Couldn't send closing stream tag.")}}this._conn._doDisconnect()},_doDisconnect:function(){Strophe.info("WebSockets _doDisconnect was called"),this._closeSocket()},_streamWrap:function(a){return this.streamStart+a+""},_closeSocket:function(){if(this.socket)try{this.socket.close()}catch(a){}this.socket=null},_emptyQueue:function(){return!0},_onClose:function(){this._conn.connected&&!this._conn.disconnecting?(Strophe.error("Websocket closed unexcectedly"),this._conn._doDisconnect()):Strophe.info("Websocket closed")},_no_auth_received:function(a){Strophe.error("Server did not send any auth methods"),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"Server did not send any auth methods"),a&&(a=a.bind(this._conn))(),this._conn._doDisconnect()},_onDisconnectTimeout:function(){},_onError:function(a){Strophe.error("Websocket error "+a),this._conn._changeConnectStatus(Strophe.Status.CONNFAIL,"The WebSocket connection could not be established was disconnected."),this._disconnect()},_onIdle:function(){var a=this._conn._data;if(a.length>0&&!this._conn.paused){for(i=0;i"===a.data){var c="";return this._conn.rawInput(c),this._conn.xmlInput(document.createElement("stream:stream")),void(this._conn.disconnecting||this._conn._doDisconnect())}if(0===a.data.search("/,""),b=(new DOMParser).parseFromString(data,"text/xml").documentElement,!this._handleStreamStart(b))return}else data=this._streamWrap(a.data),b=(new DOMParser).parseFromString(data,"text/xml").documentElement;if(!this._check_streamerror(b,Strophe.Status.ERROR))return this._conn.disconnecting&&"presence"===b.firstChild.nodeName&&"unavailable"===b.firstChild.getAttribute("type")?(this._conn.xmlInput(b),void this._conn.rawInput(Strophe.serialize(b))):void this._conn._dataRecv(b,a.data)},_onOpen:function(){Strophe.info("Websocket open");var a=this._buildStream();this._conn.xmlOutput(a.tree());var b=this._removeClosingTag(a);this._conn.rawOutput(b),this.socket.send(b)},_removeClosingTag:function(a){var b=Strophe.serialize(a);return b=b.replace(/<(stream:stream .*[^\/])\/>$/,"<$1>")},_reqToData:function(a){return a},_send:function(){this._conn.flush()},_sendRestart:function(){clearTimeout(this._conn._idleTimeout),this._conn._onIdle.bind(this._conn)()}},function(){var a,b,c,d=function(a,b){return function(){return a.apply(b,arguments)}};Strophe.addConnectionPlugin("muc",{_connection:null,rooms:{},roomNames:[],init:function(a){return this._connection=a,this._muc_handler=null,Strophe.addNamespace("MUC_OWNER",Strophe.NS.MUC+"#owner"),Strophe.addNamespace("MUC_ADMIN",Strophe.NS.MUC+"#admin"),Strophe.addNamespace("MUC_USER",Strophe.NS.MUC+"#user"),Strophe.addNamespace("MUC_ROOMCONF",Strophe.NS.MUC+"#roomconfig")},join:function(a,b,d,e,f,g,h){var i,j,k=this;return j=this.test_append_nick(a,b),i=$pres({from:this._connection.jid,to:j}).c("x",{xmlns:Strophe.NS.MUC}),null!=h&&(i=i.c("history",h).up),null!=g&&i.cnode(Strophe.xmlElement("password",[],g)),"undefined"!=typeof extended_presence&&null!==extended_presence&&i.up.cnode(extended_presence),null==this._muc_handler&&(this._muc_handler=this._connection.addHandler(function(b){var c,d,e,f,g,h,i,j,l,m;if(c=b.getAttribute("from"),!c)return!0;if(g=c.split("/")[0],!k.rooms[g])return!0;if(a=k.rooms[g],e={},"message"===b.nodeName)e=a._message_handlers;else if("presence"===b.nodeName&&(j=b.getElementsByTagName("x"),j.length>0))for(l=0,m=j.length;m>l;l++)if(h=j[l],i=h.getAttribute("xmlns"),i&&i.match(Strophe.NS.MUC)){e=a._presence_handlers;break}for(f in e)d=e[f],d(b,a)||delete e[f];return!0})),this.rooms.hasOwnProperty(a)||(this.rooms[a]=new c(this,a,b,g),this.roomNames.push(a)),e&&this.rooms[a].addHandler("presence",e),d&&this.rooms[a].addHandler("message",d),f&&this.rooms[a].addHandler("roster",f),this._connection.send(i)},leave:function(a,b,c,d){var e,f,g,h;return e=this.roomNames.indexOf(a),delete this.rooms[a],e>=0&&(this.roomNames.splice(e,1),0===this.roomNames.length&&(this._connection.deleteHandler(this._muc_handler),this._muc_handler=null)),h=this.test_append_nick(a,b),g=this._connection.getUniqueId(),f=$pres({type:"unavailable",id:g,from:this._connection.jid,to:h}),null!=d&&f.c("status",d),null!=c&&this._connection.addHandler(c,null,"presence",null,g),this._connection.send(f),g},message:function(a,b,c,d,e){var f,g,h,i;return i=this.test_append_nick(a,b),e=e||(null!=b?"chat":"groupchat"),g=this._connection.getUniqueId(),f=$msg({to:i,from:this._connection.jid,type:e,id:g}).c("body",{xmlns:Strophe.NS.CLIENT}).t(c),f.up(),null!=d&&(f.c("html",{xmlns:Strophe.NS.XHTML_IM}).c("body",{xmlns:Strophe.NS.XHTML}).t(d),0===f.node.childNodes.length?(h=f.node.parentNode,f.up().up(),f.node.removeChild(h)):f.up().up()),f.c("x",{xmlns:"jabber:x:event"}).c("composing"),this._connection.send(f),g},groupchat:function(a,b,c){return this.message(a,null,b,c)},invite:function(a,b,c){var d,e;return e=this._connection.getUniqueId(),d=$msg({from:this._connection.jid,to:a,id:e}).c("x",{xmlns:Strophe.NS.MUC_USER}).c("invite",{to:b}),null!=c&&d.c("reason",c),this._connection.send(d),e},directInvite:function(a,b,c,d){var e,f,g;return g=this._connection.getUniqueId(),e={xmlns:"jabber:x:conference",jid:a},null!=c&&(e.reason=c),null!=d&&(e.password=d),f=$msg({from:this._connection.jid,to:b,id:g}).c("x",e),this._connection.send(f),g},queryOccupants:function(a,b,c){var d,e;return d={xmlns:Strophe.NS.DISCO_ITEMS},e=$iq({from:this._connection.jid,to:a,type:"get"}).c("query",d),this._connection.sendIQ(e,b,c)},configure:function(a,b,c){var d,e;return d=$iq({to:a,type:"get"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}),e=d.tree(),this._connection.sendIQ(e,b,c)},cancelConfigure:function(a){var b,c;return b=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}).c("x",{xmlns:"jabber:x:data",type:"cancel"}),c=b.tree(),this._connection.sendIQ(c)},saveConfiguration:function(a,b,c,d){var e,f,g,h,i;if(f=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}),"undefined"!=typeof Form&&b instanceof Form)b.type="submit",f.cnode(b.toXML());else for(f.c("x",{xmlns:"jabber:x:data",type:"submit"}),h=0,i=b.length;i>h;h++)e=b[h],f.cnode(e).up();return g=f.tree(),this._connection.sendIQ(g,c,d)},createInstantRoom:function(a,b,c){var d;return d=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_OWNER}).c("x",{xmlns:"jabber:x:data",type:"submit"}),this._connection.sendIQ(d.tree(),b,c)},setTopic:function(a,b){var c;return c=$msg({to:a,from:this._connection.jid,type:"groupchat"}).c("subject",{xmlns:"jabber:client"}).t(b),this._connection.send(c.tree())},_modifyPrivilege:function(a,b,c,d,e){var f;return f=$iq({to:a,type:"set"}).c("query",{xmlns:Strophe.NS.MUC_ADMIN}).cnode(b.node),null!=c&&f.c("reason",c),this._connection.sendIQ(f.tree(),d,e)},modifyRole:function(a,b,c,d,e,f){var g;return g=$build("item",{nick:b,role:c}),this._modifyPrivilege(a,g,d,e,f)},kick:function(a,b,c,d,e){return this.modifyRole(a,b,"none",c,d,e)},voice:function(a,b,c,d,e){return this.modifyRole(a,b,"participant",c,d,e)},mute:function(a,b,c,d,e){return this.modifyRole(a,b,"visitor",c,d,e)},op:function(a,b,c,d,e){return this.modifyRole(a,b,"moderator",c,d,e)},deop:function(a,b,c,d,e){return this.modifyRole(a,b,"participant",c,d,e)},modifyAffiliation:function(a,b,c,d,e,f){var g;return g=$build("item",{jid:b,affiliation:c}),this._modifyPrivilege(a,g,d,e,f)},ban:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"outcast",c,d,e)},member:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"member",c,d,e)},revoke:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"none",c,d,e)},owner:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"owner",c,d,e)},admin:function(a,b,c,d,e){return this.modifyAffiliation(a,b,"admin",c,d,e)},changeNick:function(a,b){var c,d;return d=this.test_append_nick(a,b),c=$pres({from:this._connection.jid,to:d,id:this._connection.getUniqueId()}),this._connection.send(c.tree())},setStatus:function(a,b,c,d){var e,f;return f=this.test_append_nick(a,b),e=$pres({from:this._connection.jid,to:f}),null!=c&&e.c("show",c).up(),null!=d&&e.c("status",d),this._connection.send(e.tree())},listRooms:function(a,b,c){var d;return d=$iq({to:a,from:this._connection.jid,type:"get"}).c("query",{xmlns:Strophe.NS.DISCO_ITEMS}),this._connection.sendIQ(d,b,c)},test_append_nick:function(a,b){return a+(null!=b?"/"+Strophe.escapeNode(b):"")}}),c=function(){function b(a,b,c,e){this.client=a,this.name=b,this.nick=c,this.password=e,this._roomRosterHandler=d(this._roomRosterHandler,this),this._addOccupant=d(this._addOccupant,this),this.roster={},this._message_handlers={},this._presence_handlers={},this._roster_handlers={},this._handler_ids=0,a.muc&&(this.client=a.muc),this.name=Strophe.getBareJidFromJid(b),this.addHandler("presence",this._roomRosterHandler)}return b.prototype.join=function(a,b,c){return this.client.join(this.name,this.nick,a,b,c,this.password)},b.prototype.leave=function(a,b){return this.client.leave(this.name,this.nick,a,b),delete this.client.rooms[this.name]},b.prototype.message=function(a,b,c,d){return this.client.message(this.name,a,b,c,d)},b.prototype.groupchat=function(a,b){return this.client.groupchat(this.name,a,b)},b.prototype.invite=function(a,b){return this.client.invite(this.name,a,b)},b.prototype.directInvite=function(a,b){return this.client.directInvite(this.name,a,b,this.password)},b.prototype.configure=function(a){return this.client.configure(this.name,a)},b.prototype.cancelConfigure=function(){return this.client.cancelConfigure(this.name)},b.prototype.saveConfiguration=function(a){return this.client.saveConfiguration(this.name,a)},b.prototype.queryOccupants=function(a,b){return this.client.queryOccupants(this.name,a,b)},b.prototype.setTopic=function(a){return this.client.setTopic(this.name,a)},b.prototype.modifyRole=function(a,b,c,d,e){return this.client.modifyRole(this.name,a,b,c,d,e)},b.prototype.kick=function(a,b,c,d){return this.client.kick(this.name,a,b,c,d)},b.prototype.voice=function(a,b,c,d){return this.client.voice(this.name,a,b,c,d)},b.prototype.mute=function(a,b,c,d){return this.client.mute(this.name,a,b,c,d)},b.prototype.op=function(a,b,c,d){return this.client.op(this.name,a,b,c,d)},b.prototype.deop=function(a,b,c,d){return this.client.deop(this.name,a,b,c,d)},b.prototype.modifyAffiliation=function(a,b,c,d,e){return this.client.modifyAffiliation(this.name,a,b,c,d,e)},b.prototype.ban=function(a,b,c,d){return this.client.ban(this.name,a,b,c,d)},b.prototype.member=function(a,b,c,d){return this.client.member(this.name,a,b,c,d)},b.prototype.revoke=function(a,b,c,d){return this.client.revoke(this.name,a,b,c,d)},b.prototype.owner=function(a,b,c,d){return this.client.owner(this.name,a,b,c,d)},b.prototype.admin=function(a,b,c,d){return this.client.admin(this.name,a,b,c,d)},b.prototype.changeNick=function(a){return this.nick=a,this.client.changeNick(this.name,a)},b.prototype.setStatus=function(a,b){return this.client.setStatus(this.name,this.nick,a,b)},b.prototype.addHandler=function(a,b){var c;switch(c=this._handler_ids++,a){case"presence":this._presence_handlers[c]=b;break;case"message":this._message_handlers[c]=b;break;case"roster":this._roster_handlers[c]=b;break;default:return this._handler_ids--,null}return c},b.prototype.removeHandler=function(a){return delete this._presence_handlers[a],delete this._message_handlers[a],delete this._roster_handlers[a]},b.prototype._addOccupant=function(b){var c;return c=new a(b,this),this.roster[c.nick]=c,c},b.prototype._roomRosterHandler=function(a){var c,d,e,f,g,h;switch(c=b._parsePresence(a),g=c.nick,f=c.newnick||null,c.type){case"error":return;case"unavailable":f&&(c.nick=f,this.roster[g]&&this.roster[f]&&(this.roster[g].update(this.roster[f]),this.roster[f]=this.roster[g]),this.roster[g]&&!this.roster[f]&&(this.roster[f]=this.roster[g].update(c))),delete this.roster[g];break;default:this.roster[g]?this.roster[g].update(c):this._addOccupant(c)}h=this._roster_handlers;for(e in h)d=h[e],d(this.roster,this)||delete this._roster_handlers[e];return!0},b._parsePresence=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q;for(e={},b=a.attributes,e.nick=Strophe.getResourceFromJid(b.from.textContent),e.type=(null!=(j=b.type)?j.textContent:void 0)||null,e.states=[],k=a.childNodes,f=0,h=k.length;h>f;f++)switch(c=k[f],c.nodeName){case"status":e.status=c.textContent||null;break;case"show":e.show=c.textContent||null;break;case"x":if(b=c.attributes,(null!=(l=b.xmlns)?l.textContent:void 0)===Strophe.NS.MUC_USER)for(m=c.childNodes,g=0,i=m.length;i>g;g++)switch(d=m[g],d.nodeName){case"item":b=d.attributes,e.affiliation=(null!=(n=b.affiliation)?n.textContent:void 0)||null,e.role=(null!=(o=b.role)?o.textContent:void 0)||null,e.jid=(null!=(p=b.jid)?p.textContent:void 0)||null,e.newnick=(null!=(q=b.nick)?q.textContent:void 0)||null;break;case"status":d.attributes.code&&e.states.push(d.attributes.code.textContent)}}return e},b}(),b=function(){function a(a){this.parse=d(this.parse,this),null!=a&&this.parse(a)}return a.prototype.parse=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n;for(g=a.getElementsByTagName("query")[0].childNodes,this.identities=[],this.features=[],this.x=[],h=0,k=g.length;k>h;h++)switch(d=g[h],c=d.attributes,d.nodeName){case"identity":for(f={},i=0,l=c.length;l>i;i++)b=c[i],f[b.name]=b.textContent;this.identities.push(f);break;case"feature":this.features.push(c["var"].textContent);break;case"x":if(c=d.childNodes[0].attributes,"FORM_TYPE"===!c["var"].textContent||"hidden"===!c.type.textContent)break;for(n=d.childNodes,j=0,m=n.length;m>j;j++)e=n[j],e.attributes.type||(c=e.attributes,this.x.push({"var":c["var"].textContent,label:c.label.textContent||"",value:e.firstChild.textContent||""}))}return{identities:this.identities,features:this.features,x:this.x}},a}(),a=function(){function a(a,b){this.room=b,this.update=d(this.update,this),this.admin=d(this.admin,this),this.owner=d(this.owner,this),this.revoke=d(this.revoke,this),this.member=d(this.member,this),this.ban=d(this.ban,this),this.modifyAffiliation=d(this.modifyAffiliation,this),this.deop=d(this.deop,this),this.op=d(this.op,this),this.mute=d(this.mute,this),this.voice=d(this.voice,this),this.kick=d(this.kick,this),this.modifyRole=d(this.modifyRole,this),this.update(a)}return a.prototype.modifyRole=function(a,b,c,d){return this.room.modifyRole(this.nick,a,b,c,d)},a.prototype.kick=function(a,b,c){return this.room.kick(this.nick,a,b,c)},a.prototype.voice=function(a,b,c){return this.room.voice(this.nick,a,b,c)},a.prototype.mute=function(a,b,c){return this.room.mute(this.nick,a,b,c)},a.prototype.op=function(a,b,c){return this.room.op(this.nick,a,b,c)},a.prototype.deop=function(a,b,c){return this.room.deop(this.nick,a,b,c)},a.prototype.modifyAffiliation=function(a,b,c,d){return this.room.modifyAffiliation(this.jid,a,b,c,d)},a.prototype.ban=function(a,b,c){return this.room.ban(this.jid,a,b,c)},a.prototype.member=function(a,b,c){return this.room.member(this.jid,a,b,c)},a.prototype.revoke=function(a,b,c){return this.room.revoke(this.jid,a,b,c)},a.prototype.owner=function(a,b,c){return this.room.owner(this.jid,a,b,c)},a.prototype.admin=function(a,b,c){return this.room.admin(this.jid,a,b,c)},a.prototype.update=function(a){return this.nick=a.nick||null,this.affiliation=a.affiliation||null,this.role=a.role||null,this.jid=a.jid||null,this.status=a.status||null,this.show=a.show||null,this},a}()}.call(this),Strophe.addConnectionPlugin("disco",{_connection:null,_identities:[],_features:[],_items:[],init:function(a){this._connection=a,this._identities=[],this._features=[],this._items=[],a.addHandler(this._onDiscoInfo.bind(this),Strophe.NS.DISCO_INFO,"iq","get",null,null),a.addHandler(this._onDiscoItems.bind(this),Strophe.NS.DISCO_ITEMS,"iq","get",null,null)},addIdentity:function(a,b,c,d){for(var e=0;ef;f++){var g=b[f];a+=g.category+"/"+g.type+"/"+g.lang+"/"+g.name+"<"}for(var f=0;e>f;f++)a+=d[f]+"<";return this._ver=b64_sha1(a),this._ver},getCapabilitiesByJid:function(a){return this._jidVerIndex[a]?this._knownCapabilities[this._jidVerIndex[a]]:null},_delegateCapabilities:function(a){var b=a.getAttribute("from"),c=a.querySelector("c"),d=c.getAttribute("ver"),e=c.getAttribute("node");return this._knownCapabilities[d]?(this._jidVerIndex[b]=d,this._jidVerIndex[b]&&!this._jidVerIndex[b]===d||(this._jidVerIndex[b]=d),!0):this._requestCapabilities(b,e,d)},_requestCapabilities:function(a,b,c){if(a!==this._connection.jid){var d=this._connection.disco.info(a,b+"#"+c);this._connection.addHandler(this._handleDiscoInfoReply.bind(this),Strophe.NS.DISCO_INFO,"iq","result",d,a)}return!0},_handleDiscoInfoReply:function(a){var b=a.querySelector("query"),c=b.getAttribute("node").split("#"),d=c[1],e=a.getAttribute("from");if(this._knownCapabilities[d])this._jidVerIndex[e]&&!this._jidVerIndex[e]===d||(this._jidVerIndex[e]=d);else{var f=b.childNodes,g=f.length;this._knownCapabilities[d]=[];for(var h=0;g>h;h++){var c=f[h];this._knownCapabilities[d].push({name:c.nodeName,attributes:c.attributes})}this._jidVerIndex[e]=d}return!1},_sortIdentities:function(a,b){return a.category>b.category?1:a.categoryb.type?1:a.typeb.lang?1:a.lang|\\{|%)?([^\\/#\\^]+?)\\1?"+e.ctag+"+","g")},g=f(),h=function(a,d,h){switch(d){case"!":return"";case"=":return e.set_delimiters(h),g=f(),"";case">":return e.render_partial(h,b,c);case"{":return e.find(h,b);default:return e.escape(e.find(h,b))}},i=a.split("\n"),j=0;j\\]/g,function(a){switch(a){case"&":return"&";case"\\":return"\\\\";case'"':return""";case"'":return"'";case"<":return"<";case">":return">";default:return a}})},create_context:function(a){if(this.is_object(a))return a;var b=".";this.pragmas["IMPLICIT-ITERATOR"]&&(b=this.pragmas["IMPLICIT-ITERATOR"].iterator);var c={};return c[b]=a,c},is_object:function(a){return a&&"object"==typeof a},is_array:function(a){return"[object Array]"===Object.prototype.toString.call(a)},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},map:function(a,b){if("function"==typeof a.map)return a.map(b);for(var c=[],d=a.length,e=0;d>e;e++)c.push(b(a[e]));return c}},{name:"mustache.js",version:"0.3.1-dev",to_html:function(b,c,d,e){var f=new a;return e&&(f.send=e),f.render(b,c,d),e?void 0:f.buffer.join("\n")}}}();!function(a){var b=Array.prototype.slice,c={dict:null,load:function(b){null!==this.dict?a.extend(this.dict,b):this.dict=b},_:function(a){return dict=this.dict,dict&&dict.hasOwnProperty(a)&&(a=dict[a]),args=b.call(arguments),args[0]=a,this.printf.apply(this,args)},printf:function(c,d){return arguments.length<2?c:(d=a.isArray(d)?d:b.call(arguments,1),c.replace(/([^%]|^)%(?:(\d+)\$)?s/g,function(a,b,c){return c?b+d[parseInt(c)-1]:b+d.shift()}).replace(/%%s/g,"%s"))}};a.fn._t=function(){return a(this).html(c._.apply(c,arguments))},a.i18n=c}(jQuery);var dateFormat=function(){var a=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,b=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,c=/[^-+\dA-Z]/g,d=function(a,b){for(a=String(a),b=b||2;a.length99?Math.round(q/10):q),t:12>n?"a":"p",tt:12>n?"am":"pm",T:12>n?"A":"P",TT:12>n?"AM":"PM",Z:g?"UTC":(String(e).match(b)||[""]).pop().replace(c,""),o:(r>0?"-":"+")+d(100*Math.floor(Math.abs(r)/60)+Math.abs(r)%60,4),S:["th","st","nd","rd"][j%10>3?0:(j%100-j%10!=10)*j%10]};return f.replace(a,function(a){return a in s?s[a]:a.slice(1,a.length-1)})}}();dateFormat.masks={"default":"ddd mmm dd yyyy HH:MM:ss",shortDate:"m/d/yy",mediumDate:"mmm d, yyyy",longDate:"mmmm d, yyyy",fullDate:"dddd, mmmm d, yyyy",shortTime:"h:MM TT",mediumTime:"h:MM:ss TT",longTime:"h:MM:ss TT Z",isoDate:"yyyy-mm-dd",isoTime:"HH:MM:ss",isoDateTime:"yyyy-mm-dd'T'HH:MM:ss",isoUtcDateTime:"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"},dateFormat.i18n={dayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"]},Date.prototype.format=function(a,b){return dateFormat(this,a,b)}; \ No newline at end of file diff --git a/package.json b/package.json index 542185d7..016302ec 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "grunt": "~0.4.2", "grunt-sync-pkg": "~0.1.2", "grunt-contrib-uglify": "~0.3.0", - "grunt-contrib-concat": "~0.3.0", "grunt-contrib-watch": "~0.5.3", "grunt-natural-docs": "~0.1.1", "grunt-contrib-clean": "~0.5.0", diff --git a/src/core.js b/src/core.js index 5921d535..cf6915a1 100644 --- a/src/core.js +++ b/src/core.js @@ -111,13 +111,15 @@ Candy.Core = (function(self, Strophe, $) { // Enable debug logging if(_options.debug) { - self.log = function(str) { - try { // prevent erroring - if(typeof window.console !== undefined && typeof window.console.log !== undefined) { - console.log(str); - } - } catch(e) {} - }; + if(typeof window.console !== undefined && typeof window.console.log !== undefined) { + if(Function.prototype.bind) { + self.log = Function.prototype.bind.call(console.log, console); + } else { + self.log = function() { + Function.prototype.apply.call(console.log, console, arguments); + }; + } + } self.log('[Init] Debugging enabled'); }