diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..f02c9f24 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +# EditorConfig is awesome: http://EditorConfig.org + +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = tab +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6915f9e6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +res/notify.m4a binary +res/notify.ogg binary +res/notify.mp3 binary diff --git a/.gitignore b/.gitignore index d2809c08..778a5ff3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,14 @@ example/.htaccess .idea .ndproj/Data .ndproj/Menu.txt -node_modules \ No newline at end of file +node_modules +bower_components +candy.bundle.* +candy.min.* +libs.bundle.* +libs.min.* +.vagrant +*.log +lcov.info +candy.zip +github-credentials.json diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index fe85dab3..00000000 --- a/.gitmodules +++ /dev/null @@ -1,12 +0,0 @@ -[submodule "libs/jquery-i18n"] - path = libs/jquery-i18n - url = git://github.com/recurser/jquery-i18n.git -[submodule "libs/strophejs"] - path = libs/strophejs - url = git://github.com/strophe/strophejs.git -[submodule "libs/strophejs-plugins"] - path = libs/strophejs-plugins - url = git://github.com/strophe/strophejs-plugins.git -[submodule "libs/mustache.js"] - path = libs/mustache.js - url = git://github.com/janl/mustache.js.git diff --git a/.jshintrc b/.jshintrc index d2f32adb..6a2ea00e 100644 --- a/.jshintrc +++ b/.jshintrc @@ -8,5 +8,7 @@ "undef": true, "unused": true, "trailing": true, - "maxdepth": 4 -} \ No newline at end of file + "maxdepth": 5, + "laxcomma": true, + "browser": true +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..b4b016c8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +language: node_js +node_js: +- '0.10' +env: + global: + - SAUCE_USERNAME: candy-chat-ci + - SAUCE_ACCESS_KEY: 6c3e7f58-b230-4b91-8bcb-290cf28c1457 + - CANDY_VAGRANT: false +before_script: +- sudo apt-get update +- sudo apt-get install -y nginx +- sudo mkdir -p /usr/share/nginx/html +- sudo cp ${TRAVIS_BUILD_DIR}/devbox/nginx-default.conf /etc/nginx/sites-available/default +- sudo sed --in-place 's|{{ROOT_DIR}}|'"$TRAVIS_BUILD_DIR"'|g' /etc/nginx/sites-available/default +- sudo /etc/init.d/nginx restart +- sudo apt-get install -y naturaldocs +- npm install -g grunt-cli bower +- npm install +- bower install +script: +- grunt ci diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md old mode 100644 new mode 100755 index 870ce22a..a208b9d6 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,6 +7,8 @@ ## Learn & listen +[![Gitter chat](https://badges.gitter.im/candy-chat.png)](https://gitter.im/candy-chat) + * [Mailing list](http://groups.google.com/group/candy-chat) * yes, non-gmail users can signup as well * [FAQ](https://github.com/candy-chat/candy/wiki/Frequently-Asked-Questions) @@ -21,9 +23,8 @@ 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`) +3. Run `vagrant up`. +5. Create a branch based on the `master` 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) @@ -34,13 +35,22 @@ Please note that you should have a working XMPP server to test your changes (the 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` -3. Install [Node.js](http://nodejs.org/) -4. Install [Grunt](http://gruntjs.com/) (`npm install -g grunt-cli`) -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, fix eventual *jshint* errors & push them back to your fork -9. Create a [pull request](https://help.github.com/articles/using-pull-requests) +3. Checkout out `master` branch (`git checkout master`) +4. Install [Node.js](http://nodejs.org/) +5. Install [Grunt](http://gruntjs.com/) (`npm install -g grunt-cli`) +6. Install [Bower](http://bower.io/) (`npm install -g bower`) +7. Install npm dependencies (`npm install` in candy root directory) +8. Install bower dependencies (`bower install` in candy root directory) +9. Create a branch based on the `master` branch (`git checkout -B my-awesome-feature`) +10. Run `grunt watch` to automatically run jshint (syntax checker) and the build of `candy.bundle.js` and `candy.min.js` while developing. +11. Make your changes, fix eventual *jshint* errors & push them back to your fork +12. 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). + +### Running tests + +* Tests are run using [Intern](http://theintern.io). +* `grunt` and `grunt watch` will each run unit tests in Chrome on Linux (for fast feedback). +* `grunt test` will run both unit and integration tests in a variety of environments. Tests are run using Selenium Standalone and Phantom.JS while developing, and on Sauce Labs in CI or using `grunt test`. +* If you don't want to use the Vagrant box to run Selenium/PhantomJS, set `CANDY_VAGRANT='false'` to run tests. diff --git a/Gruntfile.js b/Gruntfile.js index 1934f5ff..1937469c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,13 +1,14 @@ 'use strict'; +var localInternConfig = process.env.CANDY_VAGRANT === 'false' ? 'tests/intern.local' : 'tests/intern.vagrant'; + module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), - jshint: { - all: ['Gruntfile.js', './src/**/*.js'], + all: ['Gruntfile.js', './src/**/*.js', './tests/**/*.js'], options: { jshintrc: "./.jshintrc", reporter: require('jshint-stylish') @@ -30,8 +31,11 @@ module.exports = function(grunt) { '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/core/chatUser.js', 'src/core/contact.js', + 'src/core/event.js', 'src/view/observer.js', + 'src/view/pane/chat.js', 'src/view/pane/message.js', + 'src/view/pane/privateRoom.js', 'src/view/pane/room.js', + 'src/view/pane/roster.js', 'src/view/pane/window.js', 'src/view/template.js', 'src/view/translation.js' ] }, @@ -53,14 +57,15 @@ module.exports = function(grunt) { }, 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' + 'libs.bundle.js': [ + 'bower_components/strophe/strophe.js', + 'bower_components/strophejs-plugins/muc/strophe.muc.js', + 'bower_components/strophejs-plugins/roster/strophe.roster.js', + 'bower_components/strophejs-plugins/disco/strophe.disco.js', + 'bower_components/strophejs-plugins/caps/strophe.caps.jsonly.js', + 'bower_components/mustache/mustache.js', + 'bower_components/jquery-i18n/jquery.i18n.js', + 'vendor_libs/dateformat/dateFormat.js' ] }, options: { @@ -73,23 +78,52 @@ module.exports = function(grunt) { }, 'libs-min': { files: { - 'libs/libs.min.js': ['libs/libs.bundle.js'] + 'libs.min.js': ['libs.bundle.js'] } } }, + concat: { + css:{ + src: [ + 'bower_components/bootstrap/dist/css/bootstrap.css' + ], + dest: 'libs.bundle.css' + } + }, + cssmin: { + css:{ + src: 'libs.bundle.css', + dest: 'libs.min.css' + } + }, watch: { + clear: { + files: ['src/*.js', 'src/**/*.js', 'tests/**/*.js'], + tasks: ['clear'] + }, + grunt: { + files: ['Gruntfile.js'] + }, bundle: { - files: ['src/*.js', 'src/**/*.js'], - tasks: ['jshint', 'uglify:bundle', 'uglify:min', 'notify:bundle'] + files: ['src/**/*.js'], + tasks: ['todo:src', 'jshint', 'uglify:bundle', 'uglify:min', 'notify:bundle', 'intern:unit'] }, libs: { - files: ['libs/*/**/*.js'], + files: ['bower_components/*/**/*.js', 'vendor_libs/*/**/*.js'], tasks: ['uglify:libs', 'uglify:libs-min', 'notify:libs'] + }, + tests: { + files: ['tests/candy/unit/**/*.js'], + tasks: ['todo:tests', 'jshint', 'intern:unit'] + }, + functional_tests: { + files: ['tests/candy/functional/**/*.js'], + tasks: ['todo:tests', 'jshint', 'intern:functional'] } }, natural_docs: { all: { - bin: process.env.NATURALDOCS_DIR + '/NaturalDocs', + bin: process.env.NATURALDOCS_DIR ? process.env.NATURALDOCS_DIR + '/NaturalDocs' : 'naturaldocs', flags: ['-r'], inputs: ['./src'], output: './docs', @@ -98,7 +132,7 @@ module.exports = function(grunt) { }, clean: { bundle: ['./candy.bundle.js', './candy.bundle.map', './candy.min.js'], - libs: ['./libs/libs.bundle.js', './libs/libs.bundle.map', './libs/libs.min.js'], + libs: ['./libs.bundle.js', './libs.bundle.map', './libs.min.js'], docs: ['./docs'] }, mkdir: { @@ -129,21 +163,129 @@ module.exports = function(grunt) { message: 'JsHint & bundling done' } } - } + }, + intern: { + all: { + options: { + runType: 'runner', + config: 'tests/intern' + } + }, + unit: { + options: { + runType: 'runner', + config: localInternConfig, + functionalSuites: [] + } + }, + functional: { + options: { + runType: 'runner', + config: localInternConfig, + suites: [] + } + } + }, + coveralls: { + options: { + force: true // prevent from failing CI build if coveralls is down etc. + }, + all: { + src: 'lcov.info', + } + }, + todo: { + options: {}, + src: ['src/**/*.js'], + tests: ['tests/**/*.js'] + }, + prompt: { + target: { + options: { + questions: [ + { + config: 'github-release.options.release.body', + type: 'input', + message: 'GitHub release body:' + } + ] + } + } + }, + compress: { + main: { + options: { + archive: 'candy.zip' + }, + files: [ + { + src: [ + 'example/**', + 'res/**', + 'bower.json', + 'candy.bundle.js', + 'candy.bundle.map', + 'candy.min.js', + 'candy.min.map', + 'CONTRIBUTING.md', + 'CREDITS.md', + 'libs.bundle.js', + 'libs.bundle.map', + 'libs.min.js', + 'LICENSE', + 'package.json', + 'README.md', + 'res/**', + ], + dest: './' + }, + ] + } + }, + 'github-release': { + options: { + repository: 'candy-chat/candy', + auth: grunt.file.exists('data.json') ? grunt.file.readJSON('github-credentials.json') : {}, + release: { + tag_name: 'v' + grunt.file.readJSON('package.json').version, + name: 'v' + grunt.file.readJSON('package.json').version + } + }, + files: { + src: ['candy.zip'] + } + }, }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-compress'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-cssmin'); + grunt.loadNpmTasks('grunt-github-releaser'); + grunt.loadNpmTasks('grunt-prompt'); grunt.loadNpmTasks('grunt-natural-docs'); grunt.loadNpmTasks('grunt-mkdir'); grunt.loadNpmTasks('grunt-notify'); grunt.loadNpmTasks('grunt-sync-pkg'); + grunt.loadNpmTasks('intern'); + grunt.loadNpmTasks('grunt-clear'); + grunt.loadNpmTasks('grunt-coveralls'); + grunt.loadNpmTasks('grunt-todo'); + grunt.registerTask('test', ['intern:all']); + grunt.registerTask('ci', ['todo', 'jshint', 'build', 'intern:all', 'coveralls:all', 'docs']); + grunt.registerTask('build', ['uglify:libs', 'uglify:libs-min', 'uglify:bundle', 'uglify:min', 'concat:css', 'cssmin:css']); grunt.registerTask('default', [ - 'jshint', 'uglify:libs', 'uglify:libs-min', - 'uglify:bundle', 'uglify:min', 'notify:default' + 'jshint', 'build', 'notify:default', 'intern:unit' ]); grunt.registerTask('docs', ['mkdir:docs', 'natural_docs', 'notify:docs']); -}; \ No newline at end of file + grunt.registerTask('release', [ + 'default', + 'prompt', + 'compress', + 'github-release' + ]); +}; diff --git a/LICENSE b/LICENSE index 8378f928..7273d898 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,6 @@ Copyright (c) 2011 Amiado Group AG Copyright (c) 2012-2014 Patrick Stadler & Michael Weibel +Copyright (c) 2015 Adhearsion Foundation Inc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index ee31a9ee..de47635d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ Candy — a JavaScript-based multi-user chat client ================================================== +[![Build Status](https://travis-ci.org/candy-chat/candy.png?branch=dev)](https://travis-ci.org/candy-chat/candy) +[![Coverage Status](https://coveralls.io/repos/candy-chat/candy/badge.png?branch=dev)](https://coveralls.io/r/candy-chat/candy) + Visit the official project page: http://candy-chat.github.io/candy Features @@ -11,7 +14,7 @@ Features - 100% well-documented JavaScript source code - Built for Jabber (XMPP), using famous technologies - Used and approved in a productive environment with up to 400 concurrent users -- Works with all major web browsers including IE7 +- Works with all major web browsers including IE9 Plugins ------- @@ -20,6 +23,6 @@ If you wish to add new functionality (to your candy installation) or contribute Support & Community ------------------- Take a look at our [FAQ](https://github.com/candy-chat/candy/wiki/Frequently-Asked-Questions). If it doesn't solve your questions, you're welcome to join our [Mailinglist on Google Groups](http://groups.google.com/group/candy-chat). -You don't need to have a Gmail account for it. +You don't need to have a Gmail account for it. [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/a41a8075608abeaf99db685d7ef29cf6 "githalytics.com")](http://githalytics.com/candy-chat/candy) diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 00000000..8682f53e --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,22 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = "ubuntu/trusty64" + config.vm.network :forwarded_port, guest: 80, host: 8080 + config.vm.network :forwarded_port, guest: 5280, host: 5280 + config.vm.network :forwarded_port, guest: 4444, host: 4444 + config.vm.network :private_network, ip: '192.168.88.4' + + config.vm.provision :shell, :path => "devbox/provisioning.sh" + + config.vm.synced_folder ".", "/vagrant", type: "nfs" + + config.vm.provider "virtualbox" do |v| + v.name = "candy" + v.customize ["modifyvm", :id, "--memory", 768] + end +end diff --git a/bower.json b/bower.json index 54714143..633c873e 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "candy", - "version": "1.7.0", + "version": "2.1.0", "homepage": "http://candy-chat.github.io/candy/", "authors": [ "Michael Weibel ", @@ -29,5 +29,13 @@ "bower_components", "test", "tests" - ] -} \ No newline at end of file + ], + "dependencies": { + "jquery": "~1.10.2", + "strophe": "1.1.3", + "strophejs-plugins": "benlangfeld/strophejs-plugins#30fb089457addc37e01d69c3536dee868a90a9ad", + "mustache": "0.3.0", + "jquery-i18n": "1.1.1", + "bootstrap": "~3.3.6" + } +} diff --git a/candy.bundle.js b/candy.bundle.js deleted file mode 100644 index 713a8b5a..00000000 --- a/candy.bundle.js +++ /dev/null @@ -1,5694 +0,0 @@ -/** File: candy.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global jQuery */ -/** Class: Candy - * Candy base class for initalizing the view and the core - * - * Parameters: - * (Candy) self - itself - * (jQuery) $ - jQuery - */ -var Candy = function(self, $) { - /** Object: about - * About candy - * - * Contains: - * (String) name - Candy - * (Float) version - Candy version - */ - self.about = { - name: "Candy", - version: "1.7.1" - }; - /** Function: init - * Init view & core - * - * Parameters: - * (String) service - URL to the BOSH interface - * (Object) options - Options for candy - * - * Options: - * (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); - -/** File: core.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy, window, Strophe, jQuery */ -/** Class: Candy.Core - * Candy Chat Core - * - * Parameters: - * (Candy.Core) self - itself - * (Strophe) Strophe - Strophe JS - * (jQuery) $ - jQuery - */ -Candy.Core = function(self, Strophe, $) { - /** PrivateVariable: _connection - * Strophe connection - */ - var _connection = null, /** PrivateVariable: _service - * URL of BOSH service - */ - _service = null, /** PrivateVariable: _user - * Current user (me) - */ - _user = null, /** PrivateVariable: _rooms - * Opened rooms, containing instances of Candy.Core.ChatRooms - */ - _rooms = {}, /** PrivateVariable: _anonymousConnection - * Set in when jidOrHost doesn't contain a @-char. - */ - _anonymousConnection = false, /** PrivateVariable: _status - * Current Strophe connection state - */ - _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 - * If set to `true` try to get the bookmarks and autojoin the rooms (supported by ejabberd, 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 - * Default priority for presence messages in order to receive messages across different resources - */ - 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 - * 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 - * 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"); - _addNamespace("PUBSUB", "http://jabber.org/protocol/pubsub"); - }, _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) { - if (typeof window.console !== undefined && typeof window.console.log !== undefined) { - // Strophe has a polyfill for bind which doesn't work in IE8. - if (Function.prototype.bind && Candy.Util.getIeVersion() > 8) { - 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 - * Connect to the jabber host. - * - * There are four different procedures to login: - * connect('JID', 'password') - Connect a registered user - * connect('domain') - Connect anonymously to the domain. The user should receive a random JID. - * connect('domain', null, 'nick') - Connect anonymously to the domain. The user should receive a random JID but with a nick set. - * connect('JID') - Show login form and prompt for password. JID input is hidden. - * connect() - Show login form and prompt for JID and password. - * - * See: - * for attaching an already established session. - * - * Parameters: - * (String) jidOrHost - JID or Host - * (String) password - Password of the user - * (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 - * Triggered before a connection attempt is made. - * - * Plugins should register their stanza handlers using this event - * to ensure that they are set. - * - * See also <#84 at https://github.com/candy-chat/candy/issues/84>. - * - * 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); - } 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 - * - * Parameters: - * (String) jid - Jabber ID - * (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 - * 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 - * Wrapper for Strophe.Connection.addHandler() to add a stanza handler for the connection. - * - * Parameters: - * (Function) handler - The user callback. - * (String) ns - The namespace to match. - * (String) name - The stanza name to match. - * (String) type - The stanza type attribute to match. - * (String) id - The stanza id attribute to match. - * (String) from - The stanza from attribute to match. - * (String) options - The handler options - * - * 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 - * Gets current user - * - * Returns: - * Instance of Candy.Core.ChatUser - */ - 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 - * Gets Strophe connection - * - * Returns: - * Instance of Strophe.Connection - */ - 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 - * Gets all joined rooms - * - * Returns: - * Object containing instances of Candy.Core.ChatRoom - */ - 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 - * Set the strophe status - * - * Called by: - * Candy.Core.Event.Strophe.Connect - * - * Parameters: - * (Strophe.Status.*) status - Strophe's status - */ - 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 - * Gets options - * - * Returns: - * Object - */ - self.getOptions = function() { - return _options; - }; - /** Function: getRoom - * Gets a specific room - * - * Parameters: - * (String) roomJid - JID of the room - * - * 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 - * 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 - * (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 - * (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 - * Overridden to do something useful if debug is set to true. - * - * See: Candy.Core#init - */ - self.log = function() {}; - return self; -}(Candy.Core || {}, Strophe, jQuery); - -/** File: view.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global jQuery, Candy, window, Mustache, document */ -/** Class: Candy.View - * The Candy View Class - * - * Parameters: - * (Candy.View) self - itself - * (jQuery) $ - jQuery - */ -Candy.View = function(self, $) { - /** PrivateObject: _current - * Object containing current container & roomJid which the client sees. - */ - var _current = { - container: null, - roomJid: null - }, /** PrivateObject: _options - * - * Options: - * (String) language - language to use - * (String) assets - path to assets (res) directory (with trailing slash) - * (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 - * (Bool) enableXHTML - [default: false] enables XHTML messages sending & displaying - */ - _options = { - language: "en", - assets: "res/", - messages: { - limit: 2e3, - remove: 500 - }, - crop: { - message: { - nickname: 15, - body: 1e3 - }, - roster: { - nickname: 15 - } - }, - enableXHTML: false - }, /** PrivateFunction: _setupTranslation - * Set dictionary using jQuery.i18n plugin. - * - * See: view/translation.js - * See: libs/jquery-i18n/jquery.i18n.js - * - * Parameters: - * (String) language - Language identifier - */ - _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 - * 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 - * Initialize toolbar. - */ - _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 - * 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) { - // #216 - // Rename `resources` to `assets` but prevent installations from failing - // after upgrade - if (options.resources) { - options.assets = options.resources; - } - delete options.resources; - $.extend(true, _options, options); - _setupTranslation(_options.language); - // Set path to emoticons - Candy.Util.Parser.setEmoticonPath(this.getOptions().assets + "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"), - assetsPath: this.getOptions().assets - }, { - 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 - * Gets options - * - * Returns: - * Object - */ - self.getOptions = function() { - return _options; - }; - return self; -}(Candy.View || {}, jQuery); - -/** File: util.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy, MD5, Strophe, document, escape, jQuery */ -/** Class: Candy.Util - * Candy utils - * - * Parameters: - * (Candy.Util) self - itself - * (jQuery) $ - jQuery - */ -Candy.Util = function(self, $) { - /** Function: jidToId - * Translates a jid to a MD5-Id - * - * Parameters: - * (String) jid - Jid - * - * Returns: - * MD5-ified jid - */ - self.jidToId = function(jid) { - return MD5.hexdigest(jid); - }; - /** Function: escapeJid - * Escapes a jid (node & resource get escaped) - * - * See: - * XEP-0106 - * - * Parameters: - * (String) jid - Jid - * - * 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 - * Unescapes a jid (node & resource get unescaped) - * - * See: - * XEP-0106 - * - * Parameters: - * (String) jid - Jid - * - * 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 - * 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: parseAndCropXhtml - * Parses the XHTML and applies various Candy related filters to it. - * - * - Ensures it contains only valid XHTML - * - Crops text to a max length - * - Parses the text in order to display html - * - * Parameters: - * (String) str - String containing XHTML - * (Integer) len - Max text length - */ - self.parseAndCropXhtml = function(str, len) { - return $("
").append(self.createHtml($(str).get(0), len)).html(); - }; - /** Function: setCookie - * Sets a new cookie - * - * Parameters: - * (String) name - cookie name - * (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 - * Tests if a cookie with the given name exists - * - * Parameters: - * (String) name - Cookie name - * - * Returns: - * (Boolean) - true/false - */ - 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: - * (String) name - Cookie name - * - * 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 - * 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 - * Fetches the window width and element width - * and checks if specified position + element width is bigger - * than the window width. - * - * If this evaluates to true, the position gets substracted by the element width. - * - * Parameters: - * (jQuery.Element) elem - Element to position - * (Integer) pos - Position left - * - * 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 - * Fetches the window height and element height - * and checks if specified position + element height is bigger - * than the window height. - * - * If this evaluates to true, the position gets substracted by the element height. - * - * Parameters: - * (jQuery.Element) elem - Element to position - * (Integer) pos - Position top - * - * 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 - * Localizes ISO-8610 Date with the time/dateformat specified in the translation. - * - * See: libs/dateformat/dateFormat.js - * See: src/view/translation.js - * See: jquery-i18n/jquery.i18n.js - * - * Parameters: - * (String) dateTime - ISO-8610 Datetime - * - * 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 - * Parses a ISO-8610 Date to a Date-Object. - * - * Uses a fallback if the client's browser doesn't support it. - * - * Quote: - * ECMAScript revision 5 adds native support for ISO-8601 dates in the Date.parse method, - * but many browsers currently on the market (Safari 4, Chrome 4, IE 6-8) do not support it. - * - * Credits: - * - * - * Parameters: - * (String) date - ISO-8610 Date - * - * 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 - * IE7 doesn't work with jQuery.isEmptyObject (<=1.5.1), workaround. - * - * Parameters: - * (Object) obj - the object to test for - * - * 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 - * 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 - * 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 - * 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 - * Parser for emoticons, links and also supports escaping. - */ - self.Parser = { - /** PrivateVariable: _emoticonPath - * Path to emoticons. - * - * Use setEmoticonPath() to change it - */ - _emoticonPath: "", - /** Function: setEmoticonPath - * Set emoticons location. - * - * Parameters: - * (String) path - location of emoticons with trailing slash - */ - 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|$))/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: - * (String) text - Text to emotify - * - * 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 - * Replaces URLs with a HTML-link. - * - * Parameters: - * (String) text - Text to linkify - * - * 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+&@#\/%=~_|])/gi, '$1'); - }, - /** Function: escape - * Escapes a text using a jQuery function (like htmlspecialchars in PHP) - * - * Parameters: - * (String) text - Text to escape - * - * Returns: - * Escaped text - */ - escape: function(text) { - return $("
").text(text).html(); - }, - /** Function: nl2br - * replaces newline characters with a
to make multi line messages look nice - * - * Parameters: - * (String) text - Text to process - * - * Returns: - * Processed text - */ - nl2br: function(text) { - return text.replace(/\r\n|\r|\n/g, "
"); - }, - /** Function: all - * Does everything of the parser: escaping, linkifying and emotifying. - * - * Parameters: - * (String) text - Text to parse - * - * Returns: - * (String) 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; - } - }; - /** Function: createHtml - * Copy an HTML DOM element into an XML DOM. - * - * This function copies a DOM element and all its descendants and returns - * the new copy. - * - * It's a function copied & adapted from [Strophe.js core.js](https://github.com/strophe/strophejs/blob/master/src/core.js). - * - * Parameters: - * (HTMLElement) elem - A DOM element. - * (Integer) maxLength - Max length of text - * (Integer) currentLength - Current accumulated text length - * - * Returns: - * A new, copied DOM element tree. - */ - self.createHtml = function(elem, maxLength, currentLength) { - /* jshint -W073 */ - currentLength = currentLength || 0; - var i, el, j, tag, attribute, value, css, cssAttrs, attr, cssName, cssValue; - if (elem.nodeType === Strophe.ElementType.NORMAL) { - tag = elem.nodeName.toLowerCase(); - if (Strophe.XHTML.validTag(tag)) { - try { - el = $("<" + 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; - } - } - // 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.attr(attribute, value); - } - } else { - el.attr(attribute, value); - } - } - for (i = 0; i < elem.childNodes.length; i++) { - el.append(self.createHtml(elem.childNodes[i], maxLength, currentLength)); - } - } catch (e) { - // invalid elements - Candy.Core.log("[Util:createHtml] Error while parsing XHTML:"); - Candy.Core.log(e); - el = Strophe.xmlTextNode(""); - } - } else { - el = Strophe.xmlGenerator().createDocumentFragment(); - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(self.createHtml(elem.childNodes[i], maxLength, currentLength)); - } - } - } else if (elem.nodeType === Strophe.ElementType.FRAGMENT) { - el = Strophe.xmlGenerator().createDocumentFragment(); - for (i = 0; i < elem.childNodes.length; i++) { - el.appendChild(self.createHtml(elem.childNodes[i], maxLength, currentLength)); - } - } else if (elem.nodeType === Strophe.ElementType.TEXT) { - var text = elem.nodeValue; - currentLength += text.length; - if (maxLength && currentLength > maxLength) { - text = text.substring(0, maxLength); - } - text = Candy.Util.Parser.all(text); - el = $.parseHTML(text); - } - return el; - }; - return self; -}(Candy.Util || {}, jQuery); - -/** File: action.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy, $iq, navigator, Candy, $pres, Strophe, jQuery, $msg */ -/** Class: Candy.Core.Action - * Chat Actions (basicly a abstraction of Jabber commands) - * - * Parameters: - * (Candy.Core.Action) self - itself - * (Strophe) Strophe - Strophe - * (jQuery) $ - jQuery - */ -Candy.Core.Action = function(self, Strophe, $) { - /** Class: Candy.Core.Action.Jabber - * Jabber actions - */ - self.Jabber = { - /** Function: Version - * Replies to a version request - * - * Parameters: - * (jQuery.element) msg - jQuery element - */ - Version: function(msg) { - Candy.Core.getConnection().sendIQ($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 - * - * Parameters: - * (String) nickname - New nickname - * (Array) rooms - Rooms - */ - SetNickname: function(nickname, rooms) { - rooms = rooms instanceof Array ? rooms : Candy.Core.getRooms(); - var roomNick, presence, conn = Candy.Core.getConnection(); - $.each(rooms, function(roomJid) { - roomNick = Candy.Util.escapeJid(roomJid + "/" + nickname); - presence = $pres({ - to: roomNick, - from: conn.jid, - id: "pres:" + conn.getUniqueId() - }); - Candy.Core.getConnection().send(presence); - }); - }, - /** Function: Roster - * Sends a request for a roster - */ - Roster: function() { - Candy.Core.getConnection().sendIQ($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 conn = Candy.Core.getConnection(); - attr = attr || {}; - if (!attr.id) { - attr.id = "pres:" + conn.getUniqueId(); - } - var pres = $pres(attr).c("priority").t(Candy.Core.getOptions().presencePriority.toString()).up().c("c", conn.caps.generateCapsAttrs()).up(); - if (el) { - pres.node.appendChild(el.node); - } - conn.send(pres.tree()); - }, - /** Function: Services - * Sends a request for disco items - */ - Services: function() { - Candy.Core.getConnection().sendIQ($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. - * Channel can be in jid:password format to pass room password if needed. - - * 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()); - var pubsubBookmarkRequest = Candy.Core.getConnection().getUniqueId("pubsub"); - Candy.Core.addHandler(Candy.Core.Event.Jabber.Bookmarks, Strophe.NS.PUBSUB, "iq", "result", pubsubBookmarkRequest); - Candy.Core.getConnection().sendIQ($iq({ - type: "get", - id: pubsubBookmarkRequest - }).c("pubsub", { - xmlns: Strophe.NS.PUBSUB - }).c("items", { - node: 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 - * 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 - * 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 - * 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 - * 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 - * 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 - * Room-specific commands - */ - Room: { - /** Function: Join - * Requests disco of specified room and joins afterwards. - * - * TODO: - * maybe we should wait for disco and later join the room? - * but what if we send disco but don't want/can join the room - * - * Parameters: - * (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, - id: "pres:" + conn.getUniqueId() - }).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 - * 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 - * Send message - * - * Parameters: - * (String) roomJid - Room to which send the message into - * (String) msg - Message - * (String) type - "groupchat" or "chat" ("chat" is for private messages) - * (String) xhtmlMsg - XHTML formatted message [optional] - * - * Returns: - * (Boolean) - true if message is not empty after trimming, false otherwise. - */ - Message: function(roomJid, msg, type, xhtmlMsg) { - // Trim message - msg = $.trim(msg); - if (msg === "") { - return false; - } - var nick = null; - if (type === "chat") { - nick = Strophe.getResourceFromJid(roomJid); - roomJid = Strophe.getBareJidFromJid(roomJid); - } - // muc takes care of the escaping now. - Candy.Core.getConnection().muc.message(roomJid, nick, msg, xhtmlMsg, type); - return true; - }, - /** Function: Invite - * Sends an invite stanza to multiple JIDs - * - * Parameters: - * (String) roomJid - Room to which send the message into - * (Array) invitees - Array of JIDs to be invited to the room - * (String) reason - Message to include with the invitation [optional] - * (String) password - Password for the MUC, if required [optional] - */ - Invite: function(roomJid, invitees, reason, password) { - reason = $.trim(reason); - var message = $msg({ - to: roomJid - }); - var x = message.c("x", { - xmlns: Strophe.NS.MUC_USER - }); - $.each(invitees, function(i, invitee) { - invitee = Strophe.getBareJidFromJid(invitee); - x.c("invite", { - to: invitee - }); - if (typeof reason !== "undefined" && reason !== "") { - x.c("reason", reason); - } - }); - if (typeof password !== "undefined" && password !== "") { - x.c("password", password); - } - Candy.Core.getConnection().send(message); - }, - /** 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. - * - * Parameters: - * (String) userJid - Target user jid - */ - 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 - * Room administration commands - */ - Admin: { - /** Function: UserAction - * Kick or ban a user - * - * Parameters: - * (String) roomJid - Room in which the kick/ban should be done - * (String) userJid - Victim - * (String) type - "kick" or "ban" - * (String) msg - Reason - * - * 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 - * 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); - -/** File: chatRoom.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy, Strophe */ -/** Class: Candy.Core.ChatRoom - * Candy Chat Room - * - * Parameters: - * (String) roomJid - Room jid - */ -Candy.Core.ChatRoom = function(roomJid) { - /** Object: room - * Object containing roomJid and name. - */ - this.room = { - jid: roomJid, - name: Strophe.getNodeFromJid(roomJid) - }; - /** Variable: user - * Current local user of this room. - */ - this.user = null; - /** Variable: Roster - * Candy.Core.ChatRoster instance - */ - 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 - * Get current local user - * - * Returns: - * (Object) - Candy.Core.ChatUser instance or null - */ - this.getUser = function() { - return this.user; - }; - /** Function: getJid - * Get room jid - * - * Returns: - * (String) - Room jid - */ - 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 - * Get room name - * - * Returns: - * (String) - Room name - */ - 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 - * Get roster - * - * Returns - * (Candy.Core.ChatRoster) - instance - */ - this.getRoster = function() { - return this.roster; - }; -}; - -/** File: chatRoster.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy */ -/** Class: Candy.Core.ChatRoster - * Chat Roster - */ -Candy.Core.ChatRoster = function() { - /** Object: items - * Roster items - */ - 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 - * Remove user from roster - * - * Parameters: - * (String) jid - User jid - */ - this.remove = function(jid) { - delete this.items[jid]; - }; - /** Function: get - * Get user from roster - * - * Parameters: - * (String) jid - User jid - * - * Returns: - * (Candy.Core.ChatUser) - User - */ - this.get = function(jid) { - return this.items[jid]; - }; - /** Function: getAll - * Get all items - * - * Returns: - * (Object) - all roster items - */ - this.getAll = function() { - return this.items; - }; -}; - -/** File: chatUser.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy, Strophe */ -/** Class: Candy.Core.ChatUser - * Chat User - */ -Candy.Core.ChatUser = function(jid, nick, affiliation, role) { - /** Constant: ROLE_MODERATOR - * Moderator role - */ - this.ROLE_MODERATOR = "moderator"; - /** Constant: AFFILIATION_OWNER - * Affiliation owner - */ - this.AFFILIATION_OWNER = "owner"; - /** Object: data - * User data containing: - * - 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 - * Gets an unescaped user jid - * - * See: - * - * - * Returns: - * (String) - jid - */ - 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: - * - * - * Returns: - * (String) - escaped jid - */ - 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 - * Gets user nick - * - * Returns: - * (String) - nick - */ - 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 - * Gets user role - * - * Returns: - * (String) - role - */ - this.getRole = function() { - return this.data.role; - }; - /** Function: setRole - * Sets user role - * - * Parameters: - * (String) role - Role - */ - this.setRole = function(role) { - this.data.role = role; - }; - /** Function: setAffiliation - * Sets user affiliation - * - * Parameters: - * (String) affiliation - new affiliation - */ - this.setAffiliation = function(affiliation) { - this.data.affiliation = affiliation; - }; - /** Function: getAffiliation - * Gets user affiliation - * - * Returns: - * (String) - affiliation - */ - 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 - * 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. - * - * Parameters: - * (String) list - To which privacy list the user should be added / removed from. Candy supports curently only the "ignore" list. - * (String) jid - User jid to add/remove - * - * 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 - * Returns the privacy list of the listname of the param. - * - * Parameters: - * (String) list - To which privacy list the user should be added / removed from. Candy supports curently only the "ignore" list. - * - * Returns: - * (Array) - Privacy List - */ - 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 - * Tests if this user ignores the user provided by jid. - * - * Parameters: - * (String) list - Privacy list - * (String) jid - Jid to test for - * - * Returns: - * (Boolean) - */ - 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 - * Retrieve custom data - * - * Returns: - * (Object) - Object containing custom data - */ - 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 - * Gets the previous nickname if available. - * - * Returns: - * (String) - previous nickname - */ - this.getPreviousNick = function() { - return this.data.previousNick; - }; -}; - -/** File: event.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy, Strophe, jQuery */ -/** Class: Candy.Core.Event - * Chat Events - * - * Parameters: - * (Candy.Core.Event) self - itself - * (Strophe) Strophe - Strophe - * (jQuery) $ - jQuery - */ -Candy.Core.Event = function(self, Strophe, $) { - /** Function: Login - * Notify view that the login window should be displayed - * - * Parameters: - * (String) presetJid - Preset user JID - * - * Triggers: - * candy:core.login using {presetJid} - */ - 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 - * Strophe-related events - */ - self.Strophe = { - /** Function: Connect - * Acts on strophe status events and notifies view. - * - * Parameters: - * (Strophe.Status) status - Strophe statuses - * - * 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 - * Connection status updates - * - * Parameters: - * (Strophe.Status) status - Strophe status - */ - $(Candy).triggerHandler("candy:core.chat.connection", { - status: status - }); - } - }; - /** Class: Candy.Core.Event.Jabber - * Jabber related events - */ - self.Jabber = { - /** Function: Version - * Responds to a version request - * - * Parameters: - * (String) msg - Raw XML Message - * - * Returns: - * (Boolean) - true - */ - Version: function(msg) { - Candy.Core.log("[Jabber] Version"); - Candy.Core.Action.Jabber.Version($(msg)); - return true; - }, - /** Function: Presence - * Acts on a presence event - * - * Parameters: - * (String) msg - Raw XML Message - * - * Triggers: - * candy:core.presence using {from, stanza} - * - * 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 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 - * Acts on a bookmarks event. When a bookmark has the attribute autojoin set, joins this room. - * - * Parameters: - * (String) msg - Raw XML Message - * - * Returns: - * (Boolean) - true - */ - Bookmarks: function(msg) { - Candy.Core.log("[Jabber] Bookmarks"); - // Autojoin bookmarks - $("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. - * - * Parameters: - * (String) msg - Raw XML Message - * - * 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 - * 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. - * - * Parameters: - * (String) msg - Raw XML Message - * - * 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 - * Acts on room, admin and server messages and notifies the view if required. - * - * Parameters: - * (String) msg - Raw XML Message - * - * Triggers: - * candy:core.chat.message.admin using {type, message} - * candy:core.chat.message.server {type, subject, message} - * - * Returns: - * (Boolean) - true - */ - Message: function(msg) { - Candy.Core.log("[Jabber] Message"); - msg = $(msg); - var fromJid = msg.attr("from"), type = msg.attr("type") || "undefined", toJid = msg.attr("to"); - // Inspect the message type. - if (type === "normal" || type === "undefined") { - var mediatedInvite = msg.find("invite"), directInvite = msg.find('x[xmlns="jabber:x:conference"]'); - if (mediatedInvite.length > 0) { - var passwordNode = msg.find("password"), password = null, continueNode = mediatedInvite.find("continue"), continuedThread = null; - if (passwordNode) { - password = passwordNode.text(); - } - if (continueNode) { - continuedThread = continueNode.attr("thread"); - } - /** Event: candy:core:chat:invite - * Incoming chat invite for a MUC. - * - * Parameters: - * (String) roomJid - The room the invite is to - * (String) from - User JID that invite is from text - * (String) reason - Reason for invite [default: ''] - * (String) password - Password for the room [default: null] - * (String) continuedThread - The thread ID if this is a continuation of a 1-on-1 chat [default: null] - */ - $(Candy).triggerHandler("candy:core:chat:invite", { - roomJid: fromJid, - from: mediatedInvite.attr("from") || "undefined", - reason: mediatedInvite.find("reason").html() || "", - password: password, - continuedThread: continuedThread - }); - } - if (directInvite.length > 0) { - /** Event: candy:core:chat:invite - * Incoming chat invite for a MUC. - * - * Parameters: - * (String) roomJid - The room the invite is to - * (String) from - User JID that invite is from text - * (String) reason - Reason for invite [default: ''] - * (String) password - Password for the room [default: null] - * (String) continuedThread - The thread ID if this is a continuation of a 1-on-1 chat [default: null] - */ - $(Candy).triggerHandler("candy:core:chat:invite", { - roomJid: directInvite.attr("jid"), - from: fromJid, - reason: directInvite.attr("reason") || "", - password: directInvite.attr("password"), - continuedThread: directInvite.attr("thread") - }); - } - /** Event: candy:core:chat:message:normal - * Messages with the type attribute of normal or those - * that do not have the optional type attribute. - * - * Parameters: - * (String) type - Type of the message [default: message] - * (Object) message - Message object. - */ - // Detect message with type normal or with no type. - $(Candy).triggerHandler("candy:core:chat:message:normal", { - type: type || "normal", - message: msg - }); - return true; - } else if (type !== "groupchat" && type !== "chat" && type !== "error" && type !== "headline") { - /** Event: candy:core:chat:message:other - * Messages with a type other than the ones listed in RFC3921 - * section 2.1.1. This allows plugins to catch custom message - * types. - * - * Parameters: - * (String) type - Type of the message [default: message] - * (Object) message - Message object. - */ - // Detect message with type normal or with no type. - $(Candy).triggerHandler("candy:core:chat:message:other", { - type: type, - message: msg - }); - return true; - } - // Room message - if (fromJid !== Strophe.getDomainFromJid(fromJid) && (type === "groupchat" || type === "chat" || type === "error")) { - 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() - }); - } else if (toJid && fromJid === Strophe.getDomainFromJid(fromJid)) { - /** Event: candy:core.chat.message.server - * Server message (e.g. subject) - * - * Parameters: - * (String) type - Message type [default: message] - * (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 - * Room specific events - */ - Room: { - /** Function: Leave - * Leaves a room and cleans up related data and notifies view. - * - * Parameters: - * (String) msg - Raw XML Message - * - * Triggers: - * candy:core.presence.leave using {roomJid, roomName, type, reason, actor, user} - * - * 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 - * When the local client leaves a room - * - * Also triggered when the local client gets kicked or banned from a room. - * - * Parameters: - * (String) roomJid - Room - * (String) roomName - Name of room - * (String) type - Presence type [kick, ban, leave] - * (String) reason - When type equals kick|ban, this is the reason the moderator has supplied. - * (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 - * Sets informations to rooms according to the disco info received. - * - * Parameters: - * (String) msg - Raw XML Message - * - * Returns: - * (Boolean) - true - */ - Disco: function(msg) { - Candy.Core.log("[Jabber:Room] Disco"); - msg = $(msg); - // Temp fix for #219 - // Don't go further if it's no conference disco reply - // FIXME: Do this in a more beautiful way - if (!msg.find('identity[category="conference"]').length) { - return true; - } - 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: - * (Object) msg - jQuery object of XML message - * - * Triggers: - * candy:core.presence.room using {roomJid, roomName, user, action, currentUser} - * - * 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)) { - // role/affiliation change - user = roster.get(from); - var role = item.attr("role"), affiliation = item.attr("affiliation"); - user.setRole(role); - user.setAffiliation(affiliation); - // FIXME: currently role/affilation changes are handled with this action - action = "join"; - } else { - 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: - * (String) roomJid - Room JID - * (String) roomName - Room name - * (Candy.Core.ChatUser) user - User which does the presence update - * (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 - * Acts when a presence of type error has been retrieved. - * - * Parameters: - * (Object) msg - jQuery object of XML message - * - * Triggers: - * candy:core.presence.error using {msg, type, roomJid, roomName} - * - * 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 - * Triggered when a presence error happened - * - * Parameters: - * (Object) msg - jQuery object of XML message - * (String) type - Error type - * (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 - * Acts on various message events (subject changed, private chat message, multi-user chat message) - * and notifies view. - * - * Parameters: - * (String) msg - jQuery object of XML message - * - * Triggers: - * candy:core.message using {roomJid, message, timestamp} - * - * Returns: - * (Boolean) - true - */ - Message: function(msg) { - Candy.Core.log("[Jabber:Room] Message"); - // Room subject - var roomJid, message, name; - if (msg.children("subject").length > 0 && msg.children("subject").text().length > 0 && msg.attr("type") === "groupchat") { - 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" - }; - } - } - var xhtmlChild = msg.children('html[xmlns="' + Strophe.NS.XHTML_IM + '"]'); - if (Candy.View.getOptions().enableXHTML === true && xhtmlChild.length > 0) { - var xhtmlMessage = xhtmlChild.children('body[xmlns="' + Strophe.NS.XHTML + '"]').first().html(); - message.xhtmlMessage = xhtmlMessage; - } - } else if (msg.children("composing").length > 0 || msg.children("inactive").length > 0 || msg.children("paused").length > 0) { - roomJid = Candy.Util.unescapeJid(msg.attr("from")); - name = Strophe.getResourceFromJid(roomJid); - var chatstate; - if (msg.children("composing").length > 0) { - chatstate = "composing"; - } else if (msg.children("paused").length > 0) { - chatstate = "paused"; - } else if (msg.children("inactive").length > 0) { - chatstate = "inactive"; - } else if (msg.children("gone").length > 0) { - chatstate = "gone"; - } - /** Event: candy:core.message.chatstate - * Triggers on any recieved chatstate notification. - * - * The resulting message object contains the name of the person, the roomJid, and the indicated chatstate. - * - * The following lists explain those parameters: - * - * Message Object Parameters: - * (String) name - User name - * (String) roomJid - Room jid - * (String) chatstate - Chatstate being indicated. ("paused", "inactive", "composing", "gone") - * - * TODO: - * Perhaps handle blank "active" as specified by XEP-0085? - */ - $(Candy).triggerHandler("candy:core.message.chatstate", { - name: name, - roomJid: roomJid, - chatstate: chatstate - }); - return true; - } 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 - * of the parameters itself. - * - * The following lists explain those parameters: - * - * Message Object Parameters: - * (String) name - Room name - * (String) body - Message text - * (String) type - Message type ([normal, chat, groupchat]) - * or 'info' which is used internally for displaying informational messages - * (Boolean) isNoConferenceRoomJid - 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. - * This flag tells if this is the case. - * - * Parameters: - * (String) roomJid - Room jid - * (Object) message - Depending on what kind of message, the object consists of different key-value pairs: - * - Room Subject: {name, body, type} - * - Error message: {type = 'info', body} - * - Private chat message: {name, body, type, isNoConferenceRoomJid} - * - MUC msg from a user: {name, body, type} - * - MUC msg from server: {name = '', body, type = 'info'} - * (String) timestamp - Timestamp, only when it's an offline message - * - * 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); - -/** File: observer.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel - */ -"use strict"; - -/* global Candy, Strophe, Mustache, jQuery */ -/** Class: Candy.View.Observer - * Observes Candy core events - * - * Parameters: - * (Candy.View.Observer) self - itself - * (jQuery) $ - jQuery - */ -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 - * Chat events - */ - self.Chat = { - /** Function: Connection - * The update method gets called whenever an event to which "Chat" is subscribed. - * - * Currently listens for connection status updates - * - * Parameters: - * (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- - * Using this event, you can alter the default Candy (View) behaviour when reacting - * to connection updates. - * - * STROPHE-STATUS has to be replaced by one of : - * - ERROR: 0, - * - CONNECTING: 1, - * - CONNFAIL: 2, - * - AUTHENTICATING: 3, - * - AUTHFAIL: 4, - * - CONNECTED: 5, - * - DISCONNECTED: 6, - * - DISCONNECTING: 7, - * - ATTACHED: 8 - * - * - * If your event handler returns `false`, no View changes will take place. - * You can, of course, also return `true` and do custom things but still - * let Candy (View) do it's job. - * - * This event has been implemented due to - * and here's an example use-case for it: - * - * (start code) - * // react to DISCONNECTED event - * $(Candy).on('candy:view.connection.status-6', function() { - * // on next browser event loop - * setTimeout(function() { - * // reload page to automatically reattach on disconnect - * window.location.reload(); - * }, 0); - * // stop view changes right here. - * return false; - * }); - * (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 - * 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 - * Presence update events - */ - self.Presence = { - /** Function: update - * Every presence update gets dispatched from this method. - * - * Parameters: - * (jQuery.Event) event - jQuery.Event object - * (Object) args - Arguments differ on each type - * - * 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); - } 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: - * (String) type - Presence type [kick, ban] - * (String) reason - Reason for the kick|ban [optional] - * (String) roomJid - Room JID - * (Candy.Core.ChatUser) user - User which has been kicked or banned - */ - $(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]) { - if (Candy.View.Pane.Room.init(args.roomJid, args.roomName) === false) { - return false; - } - 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 - * 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 - * 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.message.xhtmlMessage, 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 - * 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); - -/** File: pane.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy, document, Mustache, Strophe, Audio, jQuery */ -/** Class: Candy.View.Pane - * Candy view pane handles everything regarding DOM updates etc. - * - * Parameters: - * (Candy.View.Pane) self - itself - * (jQuery) $ - jQuery - */ -Candy.View.Pane = function(self, $) { - /** Class: Candy.View.Pane.Window - * Window related view updates - */ - self.Window = { - /** PrivateVariable: _hasFocus - * Window has focus - */ - _hasFocus: true, - /** PrivateVariable: _plainTitle - * Document title - */ - _plainTitle: document.title, - /** PrivateVariable: _unreadMessagesCount - * Unread messages count - */ - _unreadMessagesCount: 0, - /** Variable: autoscroll - * Boolean whether autoscroll is enabled - */ - autoscroll: true, - /** Function: hasFocus - * Checks if window has focus - * - * Returns: - * (Boolean) - */ - 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 - * 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 - * Clear unread message count in window title. - */ - 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 - * 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 - * Window blur event handler. - */ - onBlur: function() { - self.Window._hasFocus = false; - } - }; - /** Class: Candy.View.Pane.Chat - * Chat-View related view updates - */ - self.Chat = { - /** Variable: rooms - * Contains opened room elements - */ - rooms: [], - /** Function: addTab - * Add a tab to the chat pane. - * - * Parameters: - * (String) roomJid - JID of room - * (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 - * Get tab by JID. - * - * Parameters: - * (String) roomJid - JID of room - * - * Returns: - * (jQuery object) - Tab element - */ - 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 - * Set the active tab. - * - * Add CSS classname `active` to the choosen tab and remove `active` from all other. - * - * 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 - * Increase unread message count in a tab by one. - * - * Parameters: - * (String) roomJid - JID of room - * - * 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 - * Clear unread message count in a tab. - * - * Parameters: - * (String) roomJid - JID of room - * - * Uses: - * - - */ - 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 - * Tab close (click) event: Leave the room (groupchat) or simply close the tab (chat). - * - * Parameters: - * (DOMEvent) e - Event triggered - * - * 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); - } 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 - * - * Returns: - * (Boolean) - false, this will stop the event from bubbling - */ - 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 - * Display admin message - * - * Parameters: - * (String) subject - Admin message subject - * (String) message - Message to be displayed - * - * 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 - * After admin message display - * - * Parameters: - * (String) presetJid - Preset user JID - */ - $(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: - * (String) roomJid - Room JID - * (String) subject - Subject - * (String) message - Message - */ - 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). - * - * Parameters: - * (String) roomJid - Room JID - * (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 - * Chat toolbar for things like emoticons toolbar, room management etc. - */ - 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 - * Show toolbar. - */ - show: function() { - $("#chat-toolbar").show(); - }, - /** Function: hide - * Hide toolbar. - */ - 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 - * Play sound (default method). - */ - 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().assets + "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 - * 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 - * 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 - * Update usercount element with count. - * - * Parameters: - * (Integer) count - Current usercount - */ - updateUsercount: function(count) { - $("#chat-usercount").text(count); - } - }, - /** Class: Candy.View.Pane.Modal - * Modal window - */ - Modal: { - /** Function: show - * Display modal window - * - * Parameters: - * (String) html - HTML code to put into the modal window - * (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 - * 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 - * Show loading spinner - */ - showSpinner: function() { - $("#chat-modal-spinner").show(); - }, - /** Function: hideSpinner - * Hide loading spinner - */ - 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 - * Hide the close button - */ - 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 - * Shows a form for entering room password - * - * Parameters: - * (String) roomJid - Room jid to join - * (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 - * 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 - * 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 - * Class to display tooltips over specific elements - */ - 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. - * - * Parameters: - * (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 - * Context menu for actions and settings - */ - 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 - * Show context menu (positions it according to the window height/width) - * - * Parameters: - * (Element) elem - On which element it should be shown - * (String) roomJid - Room Jid of the room it should be shown - * (Candy.Core.chatUser) user - User - * - * Uses: - * for getting menulinks the user has access to - * for positioning - * for positioning - * - * 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 - * After context menu display - * - * Parameters: - * (String) roomJid - room where the context menu has been triggered - * (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 - * Extends with menu links gathered from candy:view.roster.contextmenu - * - * Parameters: - * (String) roomJid - Room in which the menu will be displayed - * (Candy.Core.ChatUser) user - User - * (jQuery.Element) elem - Parent element of the context menu - * - * Triggers: - * candy:view.roster.context-menu using {roomJid, user, elem} - * - * 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 - * Modify existing menu links (add links) - * - * In order to modify the links you need to change the object passed with an additional - * key "menulinks" containing the menulink object. - * - * Parameters: - * (String) roomJid - Room on which the menu should be displayed - * (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 - * Returns initial menulinks. The following are initial: - * - * - Private Chat - * - Ignore - * - Unignore - * - Kick - * - Ban - * - Change Subject - * - * 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; - }); - } - }, - 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: - * (Element) elem - Element on which it should be positioned to. - * - * 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 - * Everything which belongs to room view things belongs here. - */ - self.Room = { - /** Function: init - * Initialize a new room and inserts the room html into the DOM - * - * Parameters: - * (String) roomJid - Room JID - * (String) roomName - Room name - * (String) roomType - Type: either "groupchat" or "chat" (private chat) - * - * Uses: - * - - * - - * - - * - * Triggers: - * candy:view.room.after-add using {roomJid, type, element} - * - * Returns: - * (String) - the room id of the element created. - */ - init: function(roomJid, roomName, roomType) { - roomType = roomType || "groupchat"; - roomJid = Candy.Util.unescapeJid(roomJid); - var evtData = { - roomJid: roomJid, - type: roomType - }; - /** Event: candy:view.room.before-add - * Before initialising a room - * - * Parameters: - * (String) roomJid - Room JID - * (String) type - Room Type - * - * Returns: - * Boolean - if you don't want to initialise the room, return false. - */ - if ($(Candy).triggerHandler("candy:view.room.before-add", evtData) === false) { - return false; - } - // First room, show sound control - if (Candy.Util.isEmptyObject(self.Chat.rooms)) { - self.Chat.Toolbar.show(); - } - 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); - evtData.element = self.Room.getPane(roomJid); - /** Event: candy:view.room.after-add - * After initialising a room - * - * Parameters: - * (String) roomJid - Room JID - * (String) type - Room Type - * (jQuery.Element) element - Room element - */ - $(Candy).triggerHandler("candy:view.room.after-add", evtData); - return roomId; - }, - /** Function: show - * Show a specific room and hides the other rooms (if there are any) - * - * Parameters: - * (String) roomJid - room jid to show - * - * Triggers: - * 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: elem.attr("data-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 - * After hiding a room - * - * Parameters: - * (String) roomJid - Room JID - * (jQuery.Element) element - Room element - */ - $(Candy).triggerHandler("candy:view.room.after-hide", evtData); - } - }); - }, - /** Function: setSubject - * Called when someone changes the subject in the channel - * - * Triggers: - * candy:view.room.after-subject-change using {roomJid, element, subject} - * - * Parameters: - * (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 - * After changing the subject of a room - * - * Parameters: - * (String) roomJid - Room JID - * (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 - * 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. - * (Take a look in the source for a more detailed description) - * - * Triggers: - * candy:view.room.after-close using {roomJid} - * - * Parameters: - * (String) roomJid - Room to close - */ - 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 - * After closing a room - * - * Parameters: - * (String) roomJid - Room JID - */ - $(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 - * 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. - * - * The slice is only done when autoscroll is on, because otherwise someone might lose exactly the message he want to look for. - * - * 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 - * Scroll to bottom wrapper for to be able to disable it by overwriting the function. - * - * Parameters: - * (String) roomJid - Room JID - * - * Uses: - * - - */ - 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 - * 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 - * 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) {} - } - }, - /** 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). - * - * Parameters: - * (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 - * Get the current user in the room specified with the jid - * - * Parameters: - * (String) roomJid - Room of which the user should be returned from - * - * Returns: - * (Candy.Core.ChatUser) - user - */ - 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 - * 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 - * 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 - * 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 - * 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 - * 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 - * Private room handling - */ - self.PrivateRoom = { - /** Function: open - * Opens a new private room - * - * Parameters: - * (String) roomJid - Room jid to open - * (String) roomName - Room name - * (Boolean) switchToRoom - If true, displayed room switches automatically to this room - * (e.g. when user clicks itself on another user to open a private chat) - * (Boolean) isNoConferenceRoomJid - true 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. This param addresses this case. - * - * 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)), evtData = { - roomJid: roomJid, - roomName: roomName, - type: "chat" - }; - /** Event: candy:view.private-room.before-open - * Before opening a new private room - * - * Parameters: - * (String) roomJid - Room JID - * (String) roomName - Room name - * (String) type - 'chat' - * - * Returns: - * Boolean - if you don't want to open the private room, return false - */ - if ($(Candy).triggerHandler("candy:view.private-room.before-open", evtData) === false) { - return false; - } - // 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]) { - if (self.Room.init(roomJid, roomName, "chat") === false) { - return false; - } - } - 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")); - } - evtData.element = self.Room.getPane(roomJid); - /** Event: candy:view.private-room.after-open - * After opening a new private room - * - * Parameters: - * (String) roomJid - Room JID - * (String) type - 'chat' - * (jQuery.Element) element - User element - */ - $(Candy).triggerHandler("candy:view.private-room.after-open", evtData); - }, - /** 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 - * 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 - * 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 - * Handles everyhing regarding roster updates. - */ - 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.) - * - * TODO: Refactoring, this method has too much LOC. - * - * Parameters: - * (String) roomJid - Room JID in which the update happens - * (Candy.Core.ChatUser) user - User on which the update happens - * (String) action - one of "join", "leave", "kick" and "ban" - * (Candy.Core.ChatUser) currentUser - Current user - * - * Triggers: - * 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), evtData = { - roomJid: roomJid, - user: user, - action: action, - element: userElem - }; - /** Event: candy:view.roster.before-update - * Before updating the roster of a room - * - * Parameters: - * (String) roomJid - Room JID - * (Candy.Core.ChatUser) user - User - * (String) action - [join, leave, kick, ban] - * (jQuery.Element) element - User element - */ - $(Candy).triggerHandler("candy:view.roster.before-update", evtData); - // 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); - } - // in case there's been a join, the element is now there (previously not) - evtData.element = $("#user-" + roomId + "-" + userId); - /** Event: candy:view.roster.after-update - * After updating a room's roster - * - * Parameters: - * (String) roomJid - Room JID - * (Candy.Core.ChatUser) user - User - * (String) action - [join, leave, kick, ban] - * (jQuery.Element) element - User element - */ - $(Candy).triggerHandler("candy:view.roster.after-update", evtData); - }, - /** 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 - * 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 - * 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 - * 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 - * Change nick of an existing user in the roster - * - * UserId has to be recalculated from the user because at the time of this call, - * the user is already set with the new jid & nick. - * - * Parameters: - * (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 - * Message submit/show handling - */ - 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. - * - * Parameters: - * (Event) event - Triggered event - * - * Triggers: - * candy:view.message.before-send using {message} - * - * FIXME: as everywhere, `roomJid` might be slightly incorrect in this case - * - maybe rename this as part of a refactoring. - */ - submit: function(event) { - var roomJid = Candy.View.getCurrent().roomJid, roomType = Candy.View.Pane.Chat.rooms[roomJid].type, message = $(this).children(".field").val().substring(0, Candy.View.getOptions().crop.message.body), xhtmlMessage, evtData = { - roomJid: roomJid, - message: message, - xhtmlMessage: xhtmlMessage - }; - /** Event: candy:view.message.before-send - * Before sending a message - * - * Parameters: - * (String) roomJid - room to which the message should be sent - * (String) message - Message text - * (String) xhtmlMessage - XHTML formatted message [default: undefined] - * - * Returns: - * Boolean|undefined - if you like to stop sending the message, return false. - */ - if ($(Candy).triggerHandler("candy:view.message.before-send", evtData) === false) { - event.preventDefault(); - return; - } - message = evtData.message; - xhtmlMessage = evtData.xhtmlMessage; - Candy.Core.Action.Jabber.Room.Message(roomJid, message, roomType, xhtmlMessage); - // 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(roomJid, self.Room.getUser(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: - * (String) roomJid - room in which the message has been sent to - * (String) name - Name of the user which sent the message - * (String) message - Message - * (String) xhtmlMessage - XHTML formatted message [if options enableXHTML is true] - * (String) timestamp - [optional] Timestamp of the message, if not present, current date. - * - * Triggers: - * candy:view.message.before-show using {roomJid, name, message} - * candy.view.message.before-render using {template, templateData} - * candy:view.message.after-show using {roomJid, name, message, element} - */ - show: function(roomJid, name, message, xhtmlMessage, timestamp) { - message = Candy.Util.Parser.all(message.substring(0, Candy.View.getOptions().crop.message.body)); - if (xhtmlMessage) { - xhtmlMessage = Candy.Util.parseAndCropXhtml(xhtmlMessage, Candy.View.getOptions().crop.message.body); - } - var evtData = { - roomJid: roomJid, - name: name, - message: message, - xhtmlMessage: xhtmlMessage - }; - /** Event: candy:view.message.before-show - * Before showing a new message - * - * Parameters: - * (String) roomJid - Room JID - * (String) name - Name of the sending user - * (String) message - Message text - * - * Returns: - * Boolean - if you don't want to show the message, return false - */ - if ($(Candy).triggerHandler("candy:view.message.before-show", evtData) === false) { - return; - } - message = evtData.message; - xhtmlMessage = evtData.xhtmlMessage; - if (xhtmlMessage !== undefined && xhtmlMessage.length > 0) { - message = xhtmlMessage; - } - 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: - * (String) template - Template to use - * (Object) templateData - Template data consists of: - * - (String) name - Name of the sending user - * - (String) displayName - Cropped name of the sending user - * - (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)) { - if (Candy.View.Pane.PrivateRoom.open(roomJid + "/" + name, name, true) === false) { - return false; - } - } - }); - // 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.element = elem; - /** Event: candy:view.message.after-show - * Triggered after showing a message - * - * Parameters: - * (String) roomJid - Room JID - * (jQuery.Element) element - User element - * (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); - -/** File: template.js - * Candy - Chats are not dead yet. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"use strict"; - -/* global Candy */ -/** Class: Candy.View.Template - * Contains mustache.js templates - */ -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}}' + '×' + '
    • ', - 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. - * - * Authors: - * - Patrick Stadler - * - Michael Weibel - * - * Copyright: - * (c) 2011 Amiado Group AG. All rights reserved. - * (c) 2012-2014 Patrick Stadler & Michael Weibel. All rights reserved. - */ -"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." - } -}; -//# sourceMappingURL=candy.bundle.map \ No newline at end of file diff --git a/candy.bundle.map b/candy.bundle.map deleted file mode 100644 index 94dc4bc2..00000000 --- a/candy.bundle.map +++ /dev/null @@ -1 +0,0 @@ -{"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","Util","getIeVersion","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","assets","messages","limit","remove","crop","message","nickname","body","roster","enableXHTML","_setupTranslation","i18n","load","Translation","_registerObservers","on","Observer","Chat","AutojoinMissing","update","PresenceError","_registerWindowHandlers","document","focusin","Pane","Window","onFocus","focusout","onBlur","focus","blur","resize","fitTabs","_initToolbar","Toolbar","_delegateTooltips","delegate","Tooltip","show","resources","Parser","setEmoticonPath","html","Mustache","to_html","Template","pane","tooltipEmoticons","_","tooltipSound","tooltipAutoscroll","tooltipStatusmessage","tooltipAdministration","tooltipUsercount","assetsPath","tabs","rooms","modal","toolbar","soundcontrol","getCurrent","jidToId","MD5","hexdigest","escapeJid","getResourceFromJid","unescapeJid","unescapeNode","str","len","length","substr","parseAndCropXhtml","append","createHtml","get","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","maxLength","currentLength","el","j","tag","attribute","cssAttrs","attr","cssName","cssValue","nodeType","ElementType","NORMAL","nodeName","toLowerCase","XHTML","validTag","attributes","getAttribute","cssText","split","validCSS","push","join","childNodes","e","xmlTextNode","xmlGenerator","createDocumentFragment","appendChild","FRAGMENT","TEXT","nodeValue","substring","parseHTML","msg","sendIQ","$iq","to","c","os","navigator","userAgent","SetNickname","Array","roomNick","presence","conn","$pres","getUniqueId","send","Roster","xmlns","CLIENT","ROSTER","tree","pres","t","toString","up","generateCapsAttrs","Services","Autojoin","BOOKMARKS","pubsubBookmarkRequest","PUBSUB","isArray","Join","valueOf","ResetIgnoreList","getEscapedJid","PRIVACY","action","order","RemoveIgnoreList","GetIgnoreList","iq","iqId","PrivacyList","SetIgnoreListActive","GetJidIfAnonymous","getNick","MUC","muc","leave","xhtmlMsg","trim","getBareJidFromJid","Invite","invitees","reason","$msg","x","MUC_USER","invitee","IgnoreUnignore","userJid","addToOrRemoveFromPrivacyList","UpdatePrivacyList","currentUser","privacyList","getPrivacyList","index","Admin","UserAction","itemObj","role","affiliation","MUC_ADMIN","SetSubject","subject","setTopic","ChatRoom","room","ChatRoster","setName","getName","setRoster","getRoster","items","add","getAll","ROLE_MODERATOR","AFFILIATION_OWNER","privacyLists","customData","previousNick","setJid","setNick","getRole","setRole","setAffiliation","getAffiliation","isModerator","list","splice","setPrivacyLists","lists","isInPrivacyList","setCustomData","getCustomData","setPreviousNick","getPreviousNick","presetJid","Status","CONNECTED","ATTACHED","DISCONNECTED","AUTHFAIL","CONNECTING","DISCONNECTING","AUTHENTICATING","ERROR","CONNFAIL","children","stanza","item","PrivacyListError","fromJid","toJid","mediatedInvite","find","directInvite","passwordNode","continueNode","continuedThread","roomName","actor","code","identity","presenceType","nickAssign","nickChange","l","$status","tagName","error","bareRoomJid","isNoConferenceRoomJid","xhtmlChild","XHTML_IM","xhtmlMessage","first","chatstate","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","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","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","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 deleted file mode 100644 index 474fc855..00000000 --- a/candy.min.js +++ /dev/null @@ -1,4 +0,0 @@ -"use strict";var Candy=function(a,b){return a.about={name:"Candy",version:"1.7.1"},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"),k("PUBSUB","http://jabber.org/protocol/pubsub")},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&&Candy.Util.getIeVersion()>8?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",assets:"res/",messages:{limit:2e3,remove:500},crop:{message:{nickname:15,body:1e3},roster:{nickname:15}},enableXHTML:!1},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){j.resources&&(j.assets=j.resources),delete j.resources,b.extend(!0,d,j),e(d.language),Candy.Util.Parser.setEmoticonPath(this.getOptions().assets+"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"),assetsPath:this.getOptions().assets},{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.parseAndCropXhtml=function(c,d){return b("
          ").append(a.createHtml(b(c).get(0),d)).html()},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.createHtml=function(c,d,e){e=e||0;var f,g,h,i,j,k,l,m,n,o,p;if(c.nodeType===Strophe.ElementType.NORMAL)if(i=c.nodeName.toLowerCase(),Strophe.XHTML.validTag(i))try{for(g=b("<"+i+"/>"),f=0;f0&&(k=l.join("; "),g.attr(j,k))}else g.attr(j,k);for(f=0;fd&&(r=r.substring(0,d)),r=Candy.Util.Parser.all(r),g=b.parseHTML(r)}return g},a}(Candy.Util||{},jQuery),Candy.Core.Action=function(a,b,c){return a.Jabber={Version:function(a){Candy.Core.getConnection().sendIQ($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,f=Candy.Core.getConnection();c.each(b,function(b){d=Candy.Util.escapeJid(b+"/"+a),e=$pres({to:d,from:f.jid,id:"pres:"+f.getUniqueId()}),Candy.Core.getConnection().send(e)})},Roster:function(){Candy.Core.getConnection().sendIQ($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.ROSTER}).tree())},Presence:function(a,b){var c=Candy.Core.getConnection();a=a||{},a.id||(a.id="pres:"+c.getUniqueId());var d=$pres(a).c("priority").t(Candy.Core.getOptions().presencePriority.toString()).up().c("c",c.caps.generateCapsAttrs()).up();b&&d.node.appendChild(b.node),c.send(d.tree())},Services:function(){Candy.Core.getConnection().sendIQ($iq({type:"get",xmlns:b.NS.CLIENT}).c("query",{xmlns:b.NS.DISCO_ITEMS}).tree())},Autojoin:function(){if(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());var d=Candy.Core.getConnection().getUniqueId("pubsub");Candy.Core.addHandler(Candy.Core.Event.Jabber.Bookmarks,b.NS.PUBSUB,"iq","result",d),Candy.Core.getConnection().sendIQ($iq({type:"get",id:d}).c("pubsub",{xmlns:b.NS.PUBSUB}).c("items",{node:b.NS.BOOKMARKS}).tree())}else 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,id:"pres:"+e.getUniqueId()}).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,d,e,f){if(d=c.trim(d),""===d)return!1;var g=null;return"chat"===e&&(g=b.getResourceFromJid(a),a=b.getBareJidFromJid(a)),Candy.Core.getConnection().muc.message(a,g,d,f,e),!0},Invite:function(a,d,e,f){e=c.trim(e);var g=$msg({to:a}),h=g.c("x",{xmlns:b.NS.MUC_USER});c.each(d,function(a,c){c=b.getBareJidFromJid(c),h.c("invite",{to:c}),"undefined"!=typeof e&&""!==e&&h.c("reason",e)}),"undefined"!=typeof f&&""!==f&&h.c("password",f),Candy.Core.getConnection().send(g)},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.setRole=function(a){this.data.role=a},this.setAffiliation=function(a){this.data.affiliation=a},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")||"undefined",g=d.attr("to");if("normal"===f||"undefined"===f){var h=d.find("invite"),i=d.find('x[xmlns="jabber:x:conference"]');if(h.length>0){var j=d.find("password"),k=null,l=h.find("continue"),m=null;j&&(k=j.text()),l&&(m=l.attr("thread")),c(Candy).triggerHandler("candy:core:chat:invite",{roomJid:e,from:h.attr("from")||"undefined",reason:h.find("reason").html()||"",password:k,continuedThread:m})}return i.length>0&&c(Candy).triggerHandler("candy:core:chat:invite",{roomJid:i.attr("jid"),from:e,reason:i.attr("reason")||"",password:i.attr("password"),continuedThread:i.attr("thread")}),c(Candy).triggerHandler("candy:core:chat:message:normal",{type:f||"normal",message:d}),!0}return"groupchat"!==f&&"chat"!==f&&"error"!==f&&"headline"!==f?(c(Candy).triggerHandler("candy:core:chat:message:other",{type:f,message:d}),!0):(e===b.getDomainFromJid(e)||"groupchat"!==f&&"chat"!==f&&"error"!==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){if(Candy.Core.log("[Jabber:Room] Disco"),a=c(a),!a.find('identity[category="conference"]').length)return!0;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)){r=t.get(e);var v=u.attr("role"),w=u.attr("affiliation");r.setRole(v),r.setAffiliation(w),q="join"}else 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,f;if(a.children("subject").length>0&&a.children("subject").text().length>0&&"groupchat"===a.attr("type"))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 g=a.children("error");g.children("text").length>0&&(d=a.attr("from"),e={type:"info",body:g.children("text").text()})}else{if(!(a.children("body").length>0)){if(a.children("composing").length>0||a.children("inactive").length>0||a.children("paused").length>0){d=Candy.Util.unescapeJid(a.attr("from")),f=b.getResourceFromJid(d);var h;return a.children("composing").length>0?h="composing":a.children("paused").length>0?h="paused":a.children("inactive").length>0?h="inactive":a.children("gone").length>0&&(h="gone"),c(Candy).triggerHandler("candy:core.message.chatstate",{name:f,roomJid:d,chatstate:h}),!0}return!0}if("chat"===a.attr("type")||"normal"===a.attr("type")){d=Candy.Util.unescapeJid(a.attr("from"));var i=b.getBareJidFromJid(d),j=!Candy.Core.getRoom(i);f=j?b.getNodeFromJid(d):b.getResourceFromJid(d),e={name:f,body:a.children("body").text(),type:a.attr("type"),isNoConferenceRoomJid:j}}else{d=Candy.Util.unescapeJid(b.getBareJidFromJid(a.attr("from")));var k=b.getResourceFromJid(a.attr("from"));if(k)k=b.unescapeNode(k),e={name:k,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 l=a.children('html[xmlns="'+b.NS.XHTML_IM+'"]');if(Candy.View.getOptions().enableXHTML===!0&&l.length>0){var m=l.children('body[xmlns="'+b.NS.XHTML+'"]').first().html();e.xhtmlMessage=m}}var n=a.children(a.children("delay")?"delay":'x[xmlns="'+b.NS.DELAY+'"]'),o=void 0!==n?n.attr("stamp"):null;return c(Candy).triggerHandler("candy:core.message",{roomJid:d,message:e,timestamp:o}),!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 if(d.roomJid){if(d.roomJid=Candy.Util.unescapeJid(d.roomJid),!Candy.View.Pane.Chat.rooms[d.roomJid]){if(Candy.View.Pane.Room.init(d.roomJid,d.roomName)===!1)return!1;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.message.xhtmlMessage,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().assets+"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",c=Candy.Util.unescapeJid(c);var f={roomJid:c,type:e};if(b(Candy).triggerHandler("candy:view.room.before-add",f)===!1)return!1;Candy.Util.isEmptyObject(a.Chat.rooms)&&a.Chat.Toolbar.show();var g=Candy.Util.jidToId(c);return a.Chat.rooms[c]={id:g,usercount:0,name:d,type:e,messageCount:0,scrollPosition:-1},b("#chat-rooms").append(Mustache.to_html(Candy.View.Template.Room.pane,{roomId:g,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),f.element=a.Room.getPane(c),b(Candy).triggerHandler("candy:view.room.after-add",f),g},show:function(c){var d,e=a.Chat.rooms[c].id;b(".room-pane").each(function(){var f=b(this);d={roomJid:f.attr("data-roomjid"),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)),h={roomJid:c,roomName:d,type:"chat"};return b(Candy).triggerHandler("candy:view.private-room.before-open",h)===!1?!1:Candy.Core.getUser().isInPrivacyList("ignore",c)?!1:a.Chat.rooms[c]||a.Room.init(c,d,"chat")!==!1?(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")),h.element=a.Room.getPane(c),void b(Candy).triggerHandler("candy:view.private-room.after-open",h)):!1},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),k={roomJid:c,user:d,action:e,element:j};if(b(Candy).triggerHandler("candy:view.roster.before-update",k),"join"===e){i=1;var l=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 m=!1,n=a.Room.getPane(c,".roster-pane");if(n.children().length>0){var o=d.getNick().toUpperCase();n.children().each(function(){var a=b(this);return a.attr("data-nick").toUpperCase()>o?(a.before(l),m=!0,!1):!0})}m||n.append(l),a.Roster.showJoinAnimation(d,h,g,c,f)}else i=0,j.replaceWith(l),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 p=b.i18n._("userChangedNick",[d.getPreviousNick(),d.getNick()]);a.Chat.onInfoMessage(c,p)}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),k.element=b("#user-"+g+"-"+h),b(Candy).triggerHandler("candy:view.roster.after-update",k)},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,e=Candy.View.getCurrent().roomJid,f=Candy.View.Pane.Chat.rooms[e].type,g=b(this).children(".field").val().substring(0,Candy.View.getOptions().crop.message.body),h={roomJid:e,message:g,xhtmlMessage:d};return b(Candy).triggerHandler("candy:view.message.before-send",h)===!1?void c.preventDefault():(g=h.message,d=h.xhtmlMessage,Candy.Core.Action.Jabber.Room.Message(e,g,f,d),"chat"===f&&g&&a.Message.show(e,a.Room.getUser(e).getNick(),g),b(this).children(".field").val("").focus(),void c.preventDefault())},show:function(c,d,e,f,g){e=Candy.Util.Parser.all(e.substring(0,Candy.View.getOptions().crop.message.body)),f&&(f=Candy.Util.parseAndCropXhtml(f,Candy.View.getOptions().crop.message.body));var h={roomJid:c,name:d,message:e,xhtmlMessage:f};if(b(Candy).triggerHandler("candy:view.message.before-show",h)!==!1&&(e=h.message,f=h.xhtmlMessage,void 0!==f&&f.length>0&&(e=f),e)){var i={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(g||(new Date).toGMTString())}};b(Candy).triggerHandler("candy:view.message.before-render",i);var j=Mustache.to_html(i.template,i.templateData);a.Room.appendToMessagePane(c,j);var k=a.Room.getPane(c,".message-pane").children().last();k.find("a.label").click(function(b){b.preventDefault();var e=Candy.Core.getRoom(c);return e&&d!==a.Room.getUser(Candy.View.getCurrent().roomJid).getNick()&&e.getRoster().get(c+"/"+d)&&Candy.View.Pane.PrivateRoom.open(c+"/"+d,d,!0)===!1?!1:void 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),h.element=k,b(Candy).triggerHandler("candy:view.message.after-show",h)}}},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."}}; - -//# sourceMappingURL=candy.min.map \ No newline at end of file diff --git a/candy.min.map b/candy.min.map deleted file mode 100644 index 46000e80..00000000 --- a/candy.min.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"candy.min.js","sources":["candy.bundle.js"],"names":["Candy","self","$","about","name","version","init","service","options","viewClass","View","view","Core","core","jQuery","Strophe","_status","_connection","_service","_user","_rooms","_anonymousConnection","_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","Util","getIeVersion","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","assets","messages","limit","remove","crop","message","nickname","body","roster","enableXHTML","_setupTranslation","i18n","load","Translation","_registerObservers","on","Observer","Chat","AutojoinMissing","update","PresenceError","_registerWindowHandlers","document","focusin","Pane","Window","onFocus","focusout","onBlur","focus","blur","resize","fitTabs","_initToolbar","Toolbar","_delegateTooltips","delegate","Tooltip","show","resources","Parser","setEmoticonPath","html","Mustache","to_html","Template","pane","tooltipEmoticons","_","tooltipSound","tooltipAutoscroll","tooltipStatusmessage","tooltipAdministration","tooltipUsercount","assetsPath","tabs","rooms","modal","toolbar","soundcontrol","getCurrent","jidToId","MD5","hexdigest","escapeJid","getResourceFromJid","unescapeJid","unescapeNode","str","len","length","substr","parseAndCropXhtml","append","createHtml","get","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","format","toDateString","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","maxLength","currentLength","el","j","tag","attribute","cssAttrs","attr","cssName","cssValue","nodeType","ElementType","NORMAL","nodeName","toLowerCase","XHTML","validTag","attributes","getAttribute","cssText","split","validCSS","push","join","childNodes","e","xmlTextNode","xmlGenerator","createDocumentFragment","appendChild","FRAGMENT","TEXT","nodeValue","substring","parseHTML","msg","sendIQ","$iq","to","c","os","navigator","userAgent","SetNickname","Array","roomNick","presence","conn","$pres","getUniqueId","send","Roster","xmlns","CLIENT","ROSTER","tree","pres","t","toString","up","generateCapsAttrs","Services","Autojoin","BOOKMARKS","pubsubBookmarkRequest","PUBSUB","isArray","Join","valueOf","ResetIgnoreList","getEscapedJid","PRIVACY","action","order","RemoveIgnoreList","GetIgnoreList","iq","iqId","PrivacyList","SetIgnoreListActive","GetJidIfAnonymous","getNick","MUC","muc","leave","xhtmlMsg","trim","getBareJidFromJid","Invite","invitees","reason","$msg","x","MUC_USER","invitee","IgnoreUnignore","userJid","addToOrRemoveFromPrivacyList","UpdatePrivacyList","currentUser","privacyList","getPrivacyList","index","Admin","UserAction","itemObj","role","affiliation","MUC_ADMIN","SetSubject","subject","setTopic","ChatRoom","room","ChatRoster","setName","getName","setRoster","getRoster","items","add","getAll","ROLE_MODERATOR","AFFILIATION_OWNER","privacyLists","customData","previousNick","setJid","setNick","getRole","setRole","setAffiliation","getAffiliation","isModerator","list","splice","setPrivacyLists","lists","isInPrivacyList","setCustomData","getCustomData","setPreviousNick","getPreviousNick","presetJid","Status","CONNECTED","ATTACHED","DISCONNECTED","AUTHFAIL","CONNECTING","DISCONNECTING","AUTHENTICATING","ERROR","CONNFAIL","children","stanza","item","PrivacyListError","fromJid","toJid","mediatedInvite","find","directInvite","passwordNode","continueNode","continuedThread","actor","roomName","code","identity","presenceType","nickAssign","nickChange","l","$status","tagName","error","chatstate","bareRoomJid","isNoConferenceRoomJid","xhtmlChild","XHTML_IM","xhtmlMessage","first","delay","DELAY","_showConnectedMessageModal","event","args","eventName","Modal","hide","showLoginForm","adminMessage","onInfoMessage","close","notifyPrivateChats","actionLabel","actorName","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","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","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","roomTabElement","previousPrivateRoomJid","newPrivateRoomJid","previousPrivateRoomId","newPrivateRoomId","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","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/devbox/index.html b/devbox/index.html new file mode 100644 index 00000000..3e8de125 --- /dev/null +++ b/devbox/index.html @@ -0,0 +1,50 @@ + + + + + Candy - Chats are not dead yet + + + + + + + + + +
                + + diff --git a/devbox/nginx-default.conf b/devbox/nginx-default.conf new file mode 100644 index 00000000..eade3762 --- /dev/null +++ b/devbox/nginx-default.conf @@ -0,0 +1,18 @@ +server { + root {{ROOT_DIR}}; + + charset utf-8; + + server_name localhost; + # Redirect to devbox/index.html + # = means exact location + location = / { + try_files /devbox/index.html =404; + } + + location /http-bind/ { + proxy_pass http://localhost:5280/http-bind/; + proxy_buffering off; + tcp_nodelay on; + } +} diff --git a/devbox/prosody.cfg.lua b/devbox/prosody.cfg.lua new file mode 100644 index 00000000..5572bcb9 --- /dev/null +++ b/devbox/prosody.cfg.lua @@ -0,0 +1,184 @@ +-- Prosody Example Configuration File +-- +-- Information on configuring Prosody can be found on our +-- website at http://prosody.im/doc/configure +-- +-- Tip: You can check that the syntax of this file is correct +-- when you have finished by running: luac -p prosody.cfg.lua +-- If there are any errors, it will let you know what and where +-- they are, otherwise it will keep quiet. +-- +-- The only thing left to do is rename this file to remove the .dist ending, and fill in the +-- blanks. Good luck, and happy Jabbering! + + +---------- Server-wide settings ---------- +-- Settings in this section apply to the whole server and are the default settings +-- for any virtual hosts + +-- This is a (by default, empty) list of accounts that are admins +-- for the server. Note that you must create the accounts separately +-- (see http://prosody.im/doc/creating_accounts for info) +-- Example: admins = { "user1@example.com", "user2@example.net" } +admins = { } + +-- Enable use of libevent for better performance under high load +-- For more information see: http://prosody.im/doc/libevent +use_libevent = true; + +-- This is the list of modules Prosody will load on startup. +-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. +-- Documentation on modules can be found at: http://prosody.im/doc/modules +modules_enabled = { + + -- Generally required + "roster"; -- Allow users to have a roster. Recommended ;) + "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. + "tls"; -- Add support for secure TLS on c2s/s2s connections + "dialback"; -- s2s dialback support + "disco"; -- Service discovery + + -- Not essential, but recommended + "private"; -- Private XML storage (for room bookmarks, etc.) + --"vcard"; -- Allow users to set vCards + "privacy"; -- Support privacy lists + --"compression"; -- Stream compression + + -- Nice to have + --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots. + "version"; -- Replies to server version requests + "uptime"; -- Report how long server has been running + "time"; -- Let others know the time here on this server + "ping"; -- Replies to XMPP pings with pongs + --"pep"; -- Enables users to publish their mood, activity, playing music and more + "register"; -- Allow users to register on this server using a client and change passwords + "adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client + + -- Admin interfaces + "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands + --"admin_telnet"; -- Opens telnet console interface on localhost port 5582 + + -- Other specific functionality + "bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" + "websocket"; -- Websocket support + --"httpserver"; -- Serve static files from a directory over HTTP + --"groups"; -- Shared roster support + --"announce"; -- Send announcement to all online users + --"welcome"; -- Welcome users who register accounts + --"watchregistrations"; -- Alert admins of registrations + --"motd"; -- Send a message to users when they log in + "carbons"; + -- Debian: do not remove this module, or you lose syslog + -- support + "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. +}; + +-- These modules are auto-loaded, should you +-- (for some mad reason) want to disable +-- them then uncomment them below +modules_disabled = { + -- "presence"; -- Route user/contact status information + -- "message"; -- Route messages + -- "iq"; -- Route info queries + -- "offline"; -- Store offline messages +}; + +-- Disable account creation by default, for security +-- For more information see http://prosody.im/doc/creating_accounts +allow_registration = false; + +-- Debian: +-- send the server to background. +-- +daemonize = true; + +-- Debian: +-- Please, don't change this option since /var/run/prosody/ +-- is one of the few directories Prosody is allowed to write to +-- +pidfile = "/var/run/prosody/prosody.pid"; + +-- These are the SSL/TLS-related settings. If you don't want +-- to use SSL/TLS, you may comment or remove this +ssl = { + key = "/etc/prosody/certs/localhost.key"; + certificate = "/etc/prosody/certs/localhost.crt"; +} + +-- Only allow encrypted streams? Encryption is already used when +-- available. These options will cause Prosody to deny connections that +-- are not encrypted. Note that some servers do not support s2s +-- encryption or have it disabled, including gmail.com and Google Apps +-- domains. + +--c2s_require_encryption = false +--s2s_require_encryption = false + +-- Select the authentication backend to use. The 'internal' providers +-- use Prosody's configured data storage to store the authentication data. +-- To allow Prosody to offer secure authentication mechanisms to clients, the +-- default provider stores passwords in plaintext. If you do not trust your +-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed +-- for information about using the hashed backend. + +authentication = "anonymous" + +-- Select the storage backend to use. By default Prosody uses flat files +-- in its configured data directory, but it also supports more backends +-- through modules. An "sql" backend is included by default, but requires +-- additional dependencies. See http://prosody.im/doc/storage for more info. + +--storage = "sql" -- Default is "internal" + +-- For the "sql" backend, you can uncomment *one* of the below to configure: +--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename. +--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } +--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } + +-- Logging configuration +-- For advanced logging see http://prosody.im/doc/logging +-- +-- Debian: +-- Logs info and higher to /var/log +-- Logs errors to syslog also +log = { + -- Log files (change 'info' to 'debug' for debug logs): + info = "/var/log/prosody/prosody.log"; + error = "/var/log/prosody/prosody.err"; + -- Syslog: + { levels = { "error" }; to = "syslog"; }; +} + +----------- Virtual hosts ----------- +-- You need to add a VirtualHost entry for each domain you wish Prosody to serve. +-- Settings under each VirtualHost entry apply *only* to that host. + +-- Setup localhost VirtualHost +VirtualHost "localhost" + +------ Components ------ +-- You can specify components to add hosts that provide special services, +-- like multi-user conferences, and transports. +-- For more information on components, see http://prosody.im/doc/components + +---Set up a MUC (multi-user chat) room server on conference.example.com: +Component "conference.localhost" "muc" + +-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers: +--Component "proxy.example.com" "proxy65" + +---Set up an external component (default component port is 5347) +-- +-- External components allow adding various services, such as gateways/ +-- transports to other networks like ICQ, MSN and Yahoo. For more info +-- see: http://prosody.im/doc/components#adding_an_external_component +-- +--Component "gateway.example.com" +-- component_secret = "password" + +------ Additional config files ------ +-- For organizational purposes you may prefer to add VirtualHost and +-- Component definitions in their own config files. This line includes +-- all config files in /etc/prosody/conf.d/ + +Include "conf.d/*.cfg.lua" diff --git a/devbox/provisioning.sh b/devbox/provisioning.sh new file mode 100644 index 00000000..e52c891b --- /dev/null +++ b/devbox/provisioning.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# +# Vagrant provisioning script +# +# Legal: See the LICENSE file at the top-level directory of this distribution +# and at https://github.com/candy-chat/candy/blob/master/LICENSE +# + +# +# Install Prosody XMPP server +# +echo "deb http://packages.prosody.im/debian precise main" > /etc/apt/sources.list.d/prosody.list +wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo apt-key add - +apt-get update + +apt-get install -y liblua5.1-bitop prosody lua-event + +# Install Websockets module +wget -O /usr/lib/prosody/modules/mod_websocket.lua http://prosody-modules.googlecode.com/hg/mod_websocket/mod_websocket.lua + +# Install Carbons module +wget -O /usr/lib/prosody/modules/mod_websocket.lua http://prosody-modules.googlecode.com/hg/mod_carbons/mod_carbons.lua + +# Place config +cp /vagrant/devbox/prosody.cfg.lua /etc/prosody/prosody.cfg.lua + +/etc/init.d/prosody restart + +# +# Install nginx for static file serving +# +apt-get install -y nginx +cp /vagrant/devbox/nginx-default.conf /etc/nginx/sites-available/default +sed --in-place 's|{{ROOT_DIR}}|/vagrant|g' /etc/nginx/sites-available/default +/etc/init.d/nginx restart + +# +# Candy development dependencies +# +add-apt-repository ppa:chris-lea/node.js +apt-get update +apt-get install -y nodejs git +npm install -g grunt-cli +npm install -g bower + +cd /vagrant +sudo -H -u vagrant npm install +sudo -H -u vagrant bower install + +# +# Selenium & PhantomJS for testing +# +apt-get install -y openjdk-7-jre +mkdir /usr/lib/selenium/ +wget --no-verbose --output-document=/usr/lib/selenium/selenium-server-standalone-2.42.2.jar -- http://selenium-release.storage.googleapis.com/2.42/selenium-server-standalone-2.42.2.jar +mkdir -p /var/log/selenium/ +chmod a+w /var/log/selenium/ +cp /vagrant/devbox/selenium.init.sh /etc/init.d/selenium +chmod 755 /etc/init.d/selenium +/etc/init.d/selenium start +update-rc.d selenium defaults +apt-get install -y phantomjs diff --git a/devbox/selenium.init.sh b/devbox/selenium.init.sh new file mode 100644 index 00000000..e9841ca4 --- /dev/null +++ b/devbox/selenium.init.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +case "${1:-''}" in + 'start') + if test -f /tmp/selenium.pid + then + echo "Selenium is already running." + else + java -jar /usr/lib/selenium/selenium-server-standalone-2.42.2.jar -port 4444 > /var/log/selenium/selenium-output.log 2> /var/log/selenium/selenium-error.log & echo $! > /tmp/selenium.pid + echo "Starting Selenium..." + + error=$? + if test $error -gt 0 + then + echo "${bon}Error $error! Couldn't start Selenium!${boff}" + fi + fi + ;; + 'stop') + if test -f /tmp/selenium.pid + then + echo "Stopping Selenium..." + PID=`cat /tmp/selenium.pid` + kill -3 $PID + if kill -9 $PID ; + then + sleep 2 + test -f /tmp/selenium.pid && rm -f /tmp/selenium.pid + else + echo "Selenium could not be stopped..." + fi + else + echo "Selenium is not running." + fi + ;; + 'restart') + if test -f /tmp/selenium.pid + then + kill -HUP `cat /tmp/selenium.pid` + test -f /tmp/selenium.pid && rm -f /tmp/selenium.pid + sleep 1 + java -jar /usr/lib/selenium/selenium-server-standalone-2.42.2.jar -port 4444 > /var/log/selenium/selenium-output.log 2> /var/log/selenium/selenium-error.log & echo $! > /tmp/selenium.pid + echo "Reload Selenium..." + else + echo "Selenium isn't running..." + fi + ;; + *) # no parameter specified + echo "Usage: $SELF start|stop|restart|reload|force-reload|status" + exit 1 + ;; +esac diff --git a/example/index.html b/example/index.html index a0012373..d2a0551f 100644 --- a/example/index.html +++ b/example/index.html @@ -2,12 +2,14 @@ + Candy - Chats are not dead yet + - + ' + - '', Context: { menu: '
                ' + '
                  ', @@ -73,7 +62,7 @@ Candy.View.Template = (function(self){ self.Room = { pane: '
                  ' + '{{> roster}}{{> messages}}{{> form}}
                  ', - subject: '
                • {{time}}
                  ' + + subject: '
                • {{time}}
                  ' + '{{roomName}}' + '{{_roomSubject}} {{{subject}}}
                • ', form: '
                  ' + @@ -85,8 +74,8 @@ Candy.View.Template = (function(self){ self.Roster = { pane: '
                  ', user: '
                  ' + + ' id="user-{{roomId}}-{{userId}}" data-jid="{{userJid}}" data-real-jid="{{realJid}}"' + + ' data-nick="{{nick}}" data-role="{{role}}" data-affiliation="{{affiliation}}" data-status="{{status}}">' + '
                  {{displayNick}}
                    ' + '
                  • ' + '
                  • ' + @@ -95,7 +84,7 @@ Candy.View.Template = (function(self){ self.Message = { pane: '
                      ', - item: '
                    • {{time}}
                      ' + + item: '
                    • {{time}}
                      ' + '{{displayName}}' + '{{{message}}}
                    • ' }; @@ -104,7 +93,11 @@ Candy.View.Template = (function(self){ form: '