diff --git a/.gitignore b/.gitignore
index 464ea67f3..22b4a86c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,13 +8,27 @@
.svn/
.project
.pydevproject
+
Backbone.Overview
-node_modules
-components
-docs/doctrees/environment.pickle
tags
stamp-npm
stamp-bower
+# Sphinx
+docs/html
+docs/doctrees
+
+# Bower
+components
+
+# Node.js
+node_modules
+
+# Virtualenv/Buildout
+lib
+include
+bin
+develop-eggs
+
# OSX
.DS_Store
diff --git a/Makefile b/Makefile
index df6777b85..ae5a01c29 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ BOWER ?= node_modules/.bin/bower
BUILDDIR = ./docs
PAPER =
PHANTOMJS ?= node_modules/.bin/phantomjs
-SPHINXBUILD = sphinx-build
+SPHINXBUILD = ./bin/sphinx-build
SPHINXOPTS =
POTOJSON ?= node_modules/.bin/po2json
diff --git a/bootstrap.py b/bootstrap.py
new file mode 100644
index 000000000..5f2cb0835
--- /dev/null
+++ b/bootstrap.py
@@ -0,0 +1,260 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+"""
+
+import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess
+from optparse import OptionParser
+
+if sys.platform == 'win32':
+ def quote(c):
+ if ' ' in c:
+ return '"%s"' % c # work around spawn lamosity on windows
+ else:
+ return c
+else:
+ quote = str
+
+# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
+stdout, stderr = subprocess.Popen(
+ [sys.executable, '-Sc',
+ 'try:\n'
+ ' import ConfigParser\n'
+ 'except ImportError:\n'
+ ' print 1\n'
+ 'else:\n'
+ ' print 0\n'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+has_broken_dash_S = bool(int(stdout.strip()))
+
+# In order to be more robust in the face of system Pythons, we want to
+# run without site-packages loaded. This is somewhat tricky, in
+# particular because Python 2.6's distutils imports site, so starting
+# with the -S flag is not sufficient. However, we'll start with that:
+if not has_broken_dash_S and 'site' in sys.modules:
+ # We will restart with python -S.
+ args = sys.argv[:]
+ args[0:0] = [sys.executable, '-S']
+ args = map(quote, args)
+ os.execv(sys.executable, args)
+# Now we are running with -S. We'll get the clean sys.path, import site
+# because distutils will do it later, and then reset the path and clean
+# out any namespace packages from site-packages that might have been
+# loaded by .pth files.
+clean_path = sys.path[:]
+import site
+sys.path[:] = clean_path
+for k, v in sys.modules.items():
+ if k in ('setuptools', 'pkg_resources') or (
+ hasattr(v, '__path__') and
+ len(v.__path__)==1 and
+ not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
+ # This is a namespace package. Remove it.
+ sys.modules.pop(k)
+
+is_jython = sys.platform.startswith('java')
+
+setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
+distribute_source = 'http://python-distribute.org/distribute_setup.py'
+
+# parsing arguments
+def normalize_to_url(option, opt_str, value, parser):
+ if value:
+ if '://' not in value: # It doesn't smell like a URL.
+ value = 'file://%s' % (
+ urllib.pathname2url(
+ os.path.abspath(os.path.expanduser(value))),)
+ if opt_str == '--download-base' and not value.endswith('/'):
+ # Download base needs a trailing slash to make the world happy.
+ value += '/'
+ else:
+ value = None
+ name = opt_str[2:].replace('-', '_')
+ setattr(parser.values, name, value)
+
+usage = '''\
+[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
+
+Bootstraps a buildout-based project.
+
+Simply run this script in a directory containing a buildout.cfg, using the
+Python that you want bin/buildout to use.
+
+Note that by using --setup-source and --download-base to point to
+local resources, you can keep this script from going over the network.
+'''
+
+parser = OptionParser(usage=usage)
+parser.add_option("-v", "--version", dest="version",
+ help="use a specific zc.buildout version")
+parser.add_option("-d", "--distribute",
+ action="store_true", dest="use_distribute", default=False,
+ help="Use Distribute rather than Setuptools.")
+parser.add_option("--setup-source", action="callback", dest="setup_source",
+ callback=normalize_to_url, nargs=1, type="string",
+ help=("Specify a URL or file location for the setup file. "
+ "If you use Setuptools, this will default to " +
+ setuptools_source + "; if you use Distribute, this "
+ "will default to " + distribute_source +"."))
+parser.add_option("--download-base", action="callback", dest="download_base",
+ callback=normalize_to_url, nargs=1, type="string",
+ help=("Specify a URL or directory for downloading "
+ "zc.buildout and either Setuptools or Distribute. "
+ "Defaults to PyPI."))
+parser.add_option("--eggs",
+ help=("Specify a directory for storing eggs. Defaults to "
+ "a temporary directory that is deleted when the "
+ "bootstrap script completes."))
+parser.add_option("-t", "--accept-buildout-test-releases",
+ dest='accept_buildout_test_releases',
+ action="store_true", default=False,
+ help=("Normally, if you do not specify a --version, the "
+ "bootstrap script and buildout gets the newest "
+ "*final* versions of zc.buildout and its recipes and "
+ "extensions for you. If you use this flag, "
+ "bootstrap and buildout will get the newest releases "
+ "even if they are alphas or betas."))
+parser.add_option("-c", None, action="store", dest="config_file",
+ help=("Specify the path to the buildout configuration "
+ "file to be used."))
+
+options, args = parser.parse_args()
+
+# if -c was provided, we push it back into args for buildout's main function
+if options.config_file is not None:
+ args += ['-c', options.config_file]
+
+if options.eggs:
+ eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
+else:
+ eggs_dir = tempfile.mkdtemp()
+
+if options.setup_source is None:
+ if options.use_distribute:
+ options.setup_source = distribute_source
+ else:
+ options.setup_source = setuptools_source
+
+if options.accept_buildout_test_releases:
+ args.append('buildout:accept-buildout-test-releases=true')
+args.append('bootstrap')
+
+try:
+ import pkg_resources
+ import setuptools # A flag. Sometimes pkg_resources is installed alone.
+ if not hasattr(pkg_resources, '_distribute'):
+ raise ImportError
+except ImportError:
+ ez_code = urllib2.urlopen(
+ options.setup_source).read().replace('\r\n', '\n')
+ ez = {}
+ exec ez_code in ez
+ setup_args = dict(to_dir=eggs_dir, download_delay=0)
+ if options.download_base:
+ setup_args['download_base'] = options.download_base
+ if options.use_distribute:
+ setup_args['no_fake'] = True
+ ez['use_setuptools'](**setup_args)
+ if 'pkg_resources' in sys.modules:
+ reload(sys.modules['pkg_resources'])
+ import pkg_resources
+ # This does not (always?) update the default working set. We will
+ # do it.
+ for path in sys.path:
+ if path not in pkg_resources.working_set.entries:
+ pkg_resources.working_set.add_entry(path)
+
+cmd = [quote(sys.executable),
+ '-c',
+ quote('from setuptools.command.easy_install import main; main()'),
+ '-mqNxd',
+ quote(eggs_dir)]
+
+if not has_broken_dash_S:
+ cmd.insert(1, '-S')
+
+find_links = options.download_base
+if not find_links:
+ find_links = os.environ.get('bootstrap-testing-find-links')
+if find_links:
+ cmd.extend(['-f', quote(find_links)])
+
+if options.use_distribute:
+ setup_requirement = 'distribute'
+else:
+ setup_requirement = 'setuptools'
+ws = pkg_resources.working_set
+setup_requirement_path = ws.find(
+ pkg_resources.Requirement.parse(setup_requirement)).location
+env = dict(
+ os.environ,
+ PYTHONPATH=setup_requirement_path)
+
+requirement = 'zc.buildout'
+version = options.version
+if version is None and not options.accept_buildout_test_releases:
+ # Figure out the most recent final version of zc.buildout.
+ import setuptools.package_index
+ _final_parts = '*final-', '*final'
+ def _final_version(parsed_version):
+ for part in parsed_version:
+ if (part[:1] == '*') and (part not in _final_parts):
+ return False
+ return True
+ index = setuptools.package_index.PackageIndex(
+ search_path=[setup_requirement_path])
+ if find_links:
+ index.add_find_links((find_links,))
+ req = pkg_resources.Requirement.parse(requirement)
+ if index.obtain(req) is not None:
+ best = []
+ bestv = None
+ for dist in index[req.project_name]:
+ distv = dist.parsed_version
+ if _final_version(distv):
+ if bestv is None or distv > bestv:
+ best = [dist]
+ bestv = distv
+ elif distv == bestv:
+ best.append(dist)
+ if best:
+ best.sort()
+ version = best[-1].version
+if version:
+ requirement = '=='.join((requirement, version))
+cmd.append(requirement)
+
+if is_jython:
+ import subprocess
+ exitcode = subprocess.Popen(cmd, env=env).wait()
+else: # Windows prefers this, apparently; otherwise we would prefer subprocess
+ exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
+if exitcode != 0:
+ sys.stdout.flush()
+ sys.stderr.flush()
+ print ("An error occurred when trying to install zc.buildout. "
+ "Look above this message for any errors that "
+ "were output by easy_install.")
+ sys.exit(exitcode)
+
+ws.add_entry(eggs_dir)
+ws.require(requirement)
+import zc.buildout.buildout
+zc.buildout.buildout.main(args)
+if not options.eggs: # clean up temporary egg directory
+ shutil.rmtree(eggs_dir)
diff --git a/buildout.cfg b/buildout.cfg
new file mode 100644
index 000000000..c4a512a47
--- /dev/null
+++ b/buildout.cfg
@@ -0,0 +1,22 @@
+[buildout]
+parts =
+ sphinx
+
+versions = versions
+
+[sphinx]
+recipe = zc.recipe.egg
+eggs =
+ Sphinx
+ sphinx-bootstrap-theme
+
+[versions]
+docutils = 0.12
+Jinja2 = 2.7.3
+MarkupSafe = 0.23
+Pygments = 2.0.1
+setuptools = 7.0
+six = 1.8.0
+Sphinx = 1.2.1
+z3c.recipe.egg = 2.0.1
+zc.buildout = 2.2.5
diff --git a/converse.js b/converse.js
index 02b173942..0af01c0cd 100644
--- a/converse.js
+++ b/converse.js
@@ -232,7 +232,7 @@
bosh_service_url: undefined, // The BOSH connection manager URL.
cache_otr_key: false,
debug: false,
- domain_placeholder: " e.g. conversejs.org", // Placeholder text to show in the domain input on the registration form
+ domain_placeholder: " e.g. conversejs.org", // Placeholder text shown in the domain input on the registration form
default_box_height: 400, // The default height, in pixels, for the control box, chat boxes and chatrooms.
expose_rid_and_sid: false,
forward_messages: false,
diff --git a/docs/doctrees/index.doctree b/docs/doctrees/index.doctree
deleted file mode 100644
index ea64d1dd9..000000000
Binary files a/docs/doctrees/index.doctree and /dev/null differ
diff --git a/docs/html/.buildinfo b/docs/html/.buildinfo
deleted file mode 100644
index 69ff69567..000000000
--- a/docs/html/.buildinfo
+++ /dev/null
@@ -1,4 +0,0 @@
-# Sphinx build info version 1
-# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 3f4a36d61c791a5fe1cf45900ea08867
-tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/html/_sources/index.txt b/docs/html/_sources/index.txt
deleted file mode 100644
index b41f75a01..000000000
--- a/docs/html/_sources/index.txt
+++ /dev/null
@@ -1,1479 +0,0 @@
-.. Converse.js documentation master file, created by
- sphinx-quickstart on Fri Apr 26 20:48:03 2013.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-.. toctree::
- :maxdepth: 2
-
-.. contents:: Table of Contents
- :depth: 3
- :local:
-
-
-=========================================
-Quickstart (to get a demo up and running)
-=========================================
-
-When you download a specific release of *Converse.js* there will be two minified files inside the zip file.
-
-* builds/converse.min.js
-* css/converse.min.css
-
-You can include these two files inside the *
* element of your website via the *script* and *link*
-tags:
-
-::
-
-
-
-
-You need to initialize Converse.js with configuration settings according to
-your requirements.
-
-Please refer to the `Configuration variables`_ section further below for info on
-all the available configuration settings.
-
-To configure Converse.js, put the following inline Javascript code at the
-bottom of your page (after the closing ** element).
-
-::
-
- require(['converse'], function (converse) {
- converse.initialize({
- auto_list_rooms: false,
- auto_subscribe: false,
- bosh_service_url: 'https://bind.conversejs.org', // Please use this connection manager only for testing purposes
- hide_muc_server: false,
- i18n: locales.en, // Refer to ./locale/locales.js to see which locales are supported
- prebind: false,
- show_controlbox_by_default: true,
- roster_groups: true
- });
- });
-
-The `index.html `_ file inside the
-Converse.js repository may serve as a nice usable example.
-
-These minified files provide the same demo-like functionality as is available
-on the `conversejs.org `_ website. Useful for testing or demoing.
-
-You'll most likely want to implement some kind of single persistent session solution for
-your website, where users authenticate once in your website and then stay
-logged in to their XMPP session upon the next page reload.
-
-For more info on this, read: `Prebinding and Single Session Support`_.
-
-You might also want to have more fine-grained control of what gets included in
-the minified Javascript file. Read `Configuration`_ and `Minification`_ for more info on how to do
-that.
-
-
-============
-Introduction
-============
-
-Even though you can connect to public XMPP servers on the `conversejs.org`_
-website, *Converse.js* is not really meant to be a "Software-as-a-service" (SaaS)
-webchat.
-
-Instead, its goal is to provide the means for website owners to add a tightly
-integrated instant messaging service to their own websites.
-
-As a website owner, you are expected to host *Converse.js* yourself, and to do some legwork to
-properly configure and integrate it into your site.
-
-The benefit in doing this, is that your users have a much more streamlined and integrated
-webchat experience and that you have control over the data. The latter being a
-requirement for many sites dealing with sensitive information.
-
-You'll need to set up your own XMPP server and in order to have
-`Session Support`_ (i.e. single-signon functionality whereby users are authenticated once and stay
-logged in to XMPP upon page reload) you will likely also have to add some server-side
-code.
-
-The `What you will need`_ section has more information on all these
-requirements.
-
-
-========
-Features
-========
-
-Off-the-record encryption
-=========================
-
-Converse.js supports `Off-the-record (OTR) `_
-encrypted messaging.
-
-The OTR protocol not only **encrypts your messages**, it provides ways to
-**verify the identity** of the person you are talking to,
-**plausible deniability** and **perfect forward secrecy** by generating
-new encryption keys for each conversation.
-
-In its current state, Javascript cryptography is fraught with dangers and
-challenges that make it impossible to reach the same standard of security that
-is available with native "desktop" software.
-
-This is due to its runtime malleability, the way it is "installed" (e.g.
-served) and the browser's lack of cryptographic primitives needed to implement
-secure crypto.
-
-For harsh but fairly valid criticism of Javascript cryptography, read:
-`Javascript Cryptography Considered Harmful `_.
-
-To get an idea on how this applies to OTR support in Converse.js, please read
-`my thoughts on it `_.
-
-For now, suffice to say that although its useful to have OTR support in
-Converse.js in order to avoid most eavesdroppers, if you need serious
-communications privacy, then you're much better off using native software.
-
-Sound Notifications
-===================
-
-From version 0.8.1 Converse.js can play a sound notification when you receive a
-message.
-
-For more info, please see the `play_sounds`_ configuration setting.
-
-Multilingual Support
-====================
-
-Converse.js is translated into multiple languages. The default build,
-``converse.min.js``, includes all languages.
-
-Languages increase the size of the Converse.js significantly.
-
-If you only need one, or a subset of the available languages, it's better to
-make a custom build which includes only those languages that you need.
-
-Chat Rooms
-==========
-
-Commands
---------
-
-Here are the different commands that may be used in a chat room:
-
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| Event Type | When is it triggered? | Example (substitue $nickname with an actual user's nickname) |
-+============+==============================================================================================+===============================================================+
-| **ban** | Ban a user from the chat room. They will not be able to join again. | /ban $nickname |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **clear** | Clear the messages shown in the chat room. | /clear |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **deop** | Make a moderator a normal participant. | /deop $nickname [$reason] |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **help** | Show the list of available commands. | /help |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **kick** | Kick a user out of a room. They will be able to join again. | /kick $nickname [$reason] |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **me** | Speak in the 3rd person. | /me $message |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **mute** | Remove a user's ability to post messages to the room. They will still be able to observe. | /mute $nickname [$reason] |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **nick** | Change your nickname. | /nick $nickname |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **op** | Make a normal participant a moderator. | /op $nickname [$reason] |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **topic** | Set the topic of the chat room. | /topic ${topic text} |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-| **voice** | Allow a muted user to post messages to the room. | /voice $nickname [$reason] |
-+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
-
-
-==================
-What you will need
-==================
-
-An XMPP server
-==============
-
-*Converse.js* implements `XMPP`_ as its messaging protocol, and therefore needs
-to connect to an XMPP/Jabber server (Jabber is really just a synonym for XMPP).
-
-You can connect to public XMPP servers like ``jabber.org`` but if you want to
-have `Session Support`_ you'll have to set up your own XMPP server.
-
-You can find a list of public XMPP servers/providers on `xmpp.net`_ and a list of
-servers that you can set up yourself on `xmpp.org`_.
-
-
-A BOSH Connection Manager
-=========================
-
-Your website and *Converse.js* use `HTTP`_ as protocol to communicate with
-the webserver. HTTP connections are stateless and usually shortlived.
-
-`XMPP`_ on the other hand, is the protocol that enables instant messaging, and
-its connections are stateful and usually longer.
-
-To enable a web application like *Converse.js* to communicate with an XMPP
-server, we need a proxy in the middle that can act as a bridge between the two
-protocols.
-
-The `index.html `_ file inside the
-
-This is the job of a connection manager. A connection manager can be either a
-standalone application or part of an XMPP server. Popular XMPP servers such as
-`ejabberd `_, `prosody `_ and
-`openfire `_ all include their own connection managers
-(but you usually have to enable them in the configuration).
-
-Standalone connection managers also exist, see for example `Punjab `_.
-
-The demo on the `Converse.js homepage`_ uses a connection manager located at https://bind.conversejs.org.
-This connection manager is available for testing purposes only, please don't use it in production.
-
-Overcoming cross-domain request restrictions
---------------------------------------------
-
-Lets say your domain is *example.org*, but the domain of your connection
-manager is *example.com*.
-
-HTTP requests are made by *Converse.js* to the connection manager via XmlHttpRequests (XHR).
-Until recently, it was not possible to make such requests to a different domain
-than the one currently being served (to prevent XSS attacks).
-
-Luckily there is now a standard called `CORS`_ (Cross-origin resource sharing), which enables exactly that.
-Modern browsers support CORS, but there are problems with Internet Explorer <
-10.
-
-IE 8 and 9 partially support CORS via a proprietary implementation called
-XDomainRequest. There is a `Strophe.js plugin`_ which you can use to enable
-support for XDomainRequest when it is present.
-
-In IE < 8, there is no support for CORS.
-
-Instead of using CORS, you can add a reverse proxy in
-Apache/Nginx which serves the connection manager under the same domain as your
-website. This will remove the need for any cross-domain XHR support.
-
-For example:
-~~~~~~~~~~~~
-
-Assuming your site is accessible on port ``80`` for the domain ``mysite.com``
-and your connection manager manager is running at ``someothersite.com/http-bind``.
-
-The *bosh_service_url* value you want to give Converse.js to overcome
-the cross-domain restriction is ``mysite.com/http-bind`` and not
-``someothersite.com/http-bind``.
-
-Your ``nginx`` or ``apache`` configuration will look as follows:
-
-Nginx
-~~~~~
-::
-
- http {
- server {
- listen 80
- server_name mysite.com;
- location ~ ^/http-bind/ {
- proxy_pass http://someothersite.com;
- }
- }
- }
-
-Apache
-~~~~~~
-::
-
-
- ServerName mysite.com
- RewriteEngine On
- RewriteRule ^/http-bind(.*) http://someothersite.com/http-bind$1 [P,L]
-
-
-
-Server-side authentication
-==========================
-
-.. _`Session Support`:
-
-Prebinding and Single Session Support
--------------------------------------
-
-It's possible to enable single-site login, whereby users already
-authenticated in your website will also automatically be logged in on the chat server,
-
-This session should also persist across page loads. In other words, we don't
-want the user to have to give their chat credentials every time they reload the
-page.
-
-To do this you will require a `BOSH server `_
-for converse.js to connect to (see the `bosh_service_url`_ under `Configuration variables`_)
-as well as a BOSH client on your own server (written for example in Python, Ruby or PHP) that will
-do the pre-authentication before the web page loads.
-
-.. note::
- A BOSH server acts as a bridge between HTTP, the protocol of the web, and
- XMPP, the instant messaging protocol.
- Converse.js can only communicate via HTTP, but we need to communicate with
- an XMPP server in order to chat. So the BOSH server acts as a middle man,
- translating our HTTP requests into XMPP stanzas and vice versa.
-
-Jack Moffitt has a great `blogpost`_ about this and even provides an `example Django application`_ to demonstrate it.
-
-When you authenticate to the XMPP server on your backend application (for
-example via a BOSH client in Django), you'll receive two tokens, RID (request ID) and SID (session ID).
-
-The **Session ID (SID)** is a unique identifier for the current *session*. This
-number stays constant for the entire session.
-
-The **Request ID (RID)** is a unique identifier for the current *request* (i.e.
-page load). Each page load is a new request which requires a new unique RID.
-The best way to achieve this is to simply increment the RID with each page
-load.
-
-When you initialize converse.js in your browser, you need to pass it these two
-tokens. Converse.js will then use them to attach to the session you just
-created.
-
-You can embed the RID and SID tokens in your HTML markup or you can do an
-XMLHttpRequest call to your server and ask it to return them for you.
-
-Below is one example of how this could work. An Ajax call is made to the
-relative URL **/prebind** and it expects to receive JSON data back.
-
-::
-
- $.getJSON('/prebind', function (data) {
- converse.initialize({
- prebind: true,
- bosh_service_url: data.bosh_service_url,
- jid: data.jid,
- sid: data.sid,
- rid: data.rid
- });
- );
-
-**Here's what's happening:**
-
-The JSON data returned from the Ajax call to example.com/prebind contains the user's JID (jabber ID), RID, SID and the URL to the
-BOSH server (also called a *connection manager*).
-
-These values are then passed to converse.js's ``initialize`` method.
-
-.. note::
- If you want to enable single session support, you need to set **prebind: true**
- when calling **converse.initialize** (see ./index.html).
- Additionally you need to pass in valid **jid**, **sid**, **rid** and
- **bosh_service_url** values.
-
-
-Example code for server-side prebinding
----------------------------------------
-
-* PHP:
- See `xmpp-prebind-php `_ by
- Michael Weibel and the folks from Candy chat.
-
-* Python:
- See this `example Django application`_ by Jack Moffitt.
-
-
-===========
-Development
-===========
-
-If you want to work with the non-minified Javascript and CSS files you'll soon
-notice that there are references to a missing *components* folder. Please
-follow the instructions below to create this folder and fetch Converse's
-3rd-party dependencies.
-
-.. note::
- Users have reported that converse.js cannot be built on Windows. Patches to
- fix this are welcome.
-
-
-Install the development and front-end dependencies
-==================================================
-
-We use development tools (`Grunt `_ and `Bower `_)
-which depend on Node.js and npm (the Node package manager).
-
-If you don't have Node.js installed, you can download and install the latest
-version `here `_.
-
-Also make sure you have ``git`` installed. `Details `_.
-
-Once you have *Node.js* and *git* installed, run the following command inside the Converse.js
-directory:
-
-::
-
- make dev
-
-Or alternatively, if you don't have GNU Make:
-
-::
-
- npm install
- bower update
-
-This will first install the Node.js development tools (like Grunt and Bower)
-and then use Bower to install all of Converse.js's front-end dependencies.
-
-The front-end dependencies are those javascript files on which
-Converse.js directly depends and which will be loaded in the browser.
-
-If you are curious to know what the different dependencies are:
-
-* Development dependencies:
- Take a look at whats under the *devDependencies* key in
- `package.json `_.
-
-* Front-end dependencies:
- See *dependencies* in
- `bower.json `_.
-
-.. note::
- After running ```make dev```, you should now have a new directory *components*,
- which contains all the front-end dependencies of Converse.js.
- If this directory does NOT exist, something must have gone wrong.
- Double-check the output of ```make dev``` to see if there are any errors
- listed. For support, you can write to the mailing list: conversejs@librelist.com
-
-
-With AMD and require.js (recommended)
-=====================================
-
-Converse.js uses `require.js `_ to asynchronously load dependencies.
-
-If you want to develop or customize converse.js, you'll want to load the
-non-minified javascript files.
-
-Add the following two lines to the ** section of your webpage:
-
-::
-
-
-
-
-require.js will then let the main.js file be parsed (because of the *data-main*
-attribute on the *script* tag), which will in turn cause converse.js to be
-parsed.
-
-Without AMD and require.js
-==========================
-
-Converse.js can also be used without require.js. If you for some reason prefer
-to use it this way, please refer to
-`non_amd.html `_
-for an example of how and in what order all the Javascript files that converse.js
-depends on need to be loaded.
-
-
-Before submitting a pull request
-================================
-
-Add tests for your bugfix or feature
-------------------------------------
-
-Add a test for any bug fixed or feature added. We use Jasmine
-for testing.
-
-Take a look at ``tests.html`` and ``spec/MainSpec.js`` to see how
-the tests are implemented.
-
-If you are unsure how to write tests, please
-`contact me `_ and I'll be happy to help.
-
-Check that the tests pass
--------------------------
-
-Check that the Jasmine tests complete sucessfully. Open
-`tests.html `_
-in your browser, and the tests will run automatically.
-
-On the command line you can run:
-
-::
-
- grunt test
-
-Check your code for errors or bad habits by running JSHint
-----------------------------------------------------------
-
-`JSHint `_ will do a static analysis of your code and hightlight potential errors
-and/or bad habits.
-
-::
-
- grunt jshint
-
-
-You can run both the tests and jshint in one go by calling:
-
-::
-
- grunt check
-
-
-Developer API
-=============
-
-.. note:: The API documented here is available in Converse.js 0.8.4 and higher.
- Earlier versions of Converse.js might have different API methods or none at all.
-
-In the Converse.js API, you traverse towards a logical grouping, from
-which you can then call certain standardised accessors and mutators, like::
-
- .get
- .set
- .add
- .all
- .remove
-
-This is done to increase readability and to allow intuitive method chaining.
-
-For example, to get a contact, you would do the following::
-
- converse.contacts.get('jid@example.com');
-
-To get multiple contacts, just pass in an array of jids::
-
- converse.contacts.get(['jid1@example.com', 'jid2@example.com']);
-
-
-**Here follows now a breakdown of all API groupings and methods**:
-
-
-initialize
-----------
-
-.. note:: This method is the one exception of a method which is not logically grouped
- as explained above.
-
-Initializes converse.js. This method must always be called when using
-converse.js.
-
-The `initialize` method takes a map (also called a hash or dictionary) of
-`configuration variables`_.
-
-Example::
-
- converse.initialize({
- allow_otr: true,
- auto_list_rooms: false,
- auto_subscribe: false,
- bosh_service_url: 'https://bind.example.com',
- hide_muc_server: false,
- i18n: locales['en'],
- keepalive: true,
- play_sounds: true,
- prebind: false,
- show_controlbox_by_default: true,
- debug: false,
- roster_groups: true
- });
-
-
-"contacts" grouping
--------------------
-
-get
-~~~
-
-Returns a map of attributes for a given buddy (i.e. roster contact), specified
-by JID (Jabber ID).
-
-Example::
-
- converse.contacts.get('buddy@example.com')
-
-The map of attributes:
-
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| Attribute | |
-+================+======================================================================================================================================+
-| ask | If ask === 'subscribe', then we have asked this person to be our chat buddy. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| fullname | The person's full name. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| jid | The person's Jabber/XMPP username. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| requesting | If true, then this person is asking to be our chat buddy. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| subscription | The subscription state between the current user and this chat buddy. Can be `none`, `to`, `from` or `both`. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| id | A unique id, same as the jid. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| chat_status | The person's chat status. Can be `online`, `offline`, `busy`, `xa` (extended away) or `away`. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| user_id | The user id part of the JID (the part before the `@`). |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| resources | The known resources for this chat buddy. Each resource denotes a separate and connected chat client. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| groups | The roster groups in which this chat buddy was placed. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| status | Their human readable custom status message. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| image_type | The image's file type. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| image | The Base64 encoded image data. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| url | The buddy's website URL, as specified in their VCard data. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-| vcard_updated | When last the buddy's VCard was updated. |
-+----------------+--------------------------------------------------------------------------------------------------------------------------------------+
-
-"chats" grouping
-----------------
-
-get
-~~~
-
-Returns an object/map representing a chat box (without opening or affecting that chat box).
-
-Example::
-
- converse.chats.get('buddy@example.com')
-
-*The returned chat box contains the following methods:*
-
-+-------------+------------------------------------------+
-| Method | Description |
-+=============+==========================================+
-| endOTR | End an OTR (Off-the-record) session. |
-+-------------+------------------------------------------+
-| get | Get an attribute (i.e. accessor). |
-+-------------+------------------------------------------+
-| initiateOTR | Start an OTR (off-the-record) session. |
-+-------------+------------------------------------------+
-| maximize | Minimize the chat box. |
-+-------------+------------------------------------------+
-| minimize | Maximize the chat box. |
-+-------------+------------------------------------------+
-| set | Set an attribute (i.e. mutator). |
-+-------------+------------------------------------------+
-
-*The get and set methods can be used to retrieve and change the following attributes:*
-
-+-------------+-----------------------------------------------------+
-| Attribute | Description |
-+=============+=====================================================+
-| height | The height of the chat box. |
-+-------------+-----------------------------------------------------+
-| url | The URL of the chat box heading. |
-+-------------+-----------------------------------------------------+
-
-"tokens" grouping
------------------
-
-get
-~~~
-
-Returns a token, either the RID or SID token depending on what's asked for.
-
-Example::
-
- converse.tokens.get('rid')
-
-"listen" grouping
------------------
-
-Converse.js emits events to which you can subscribe from your own Javascript.
-
-Concerning events, the following methods are available under the "listen"
-grouping:
-
-* **on(eventName, callback)**:
-
- Calling the ``on`` method allows you to subscribe to an event.
- Every time the event fires, the callback method specified by ``callback`` will be
- called.
-
- Parameters:
-
- * ``eventName`` is the event name as a string.
- * ``callback`` is the callback method to be called when the event is emitted.
-
- For example::
-
- converse.listen.on('message', function (messageXML) { ... });
-
-* **once(eventName, callback)**:
-
- Calling the ``once`` method allows you to listen to an event
- exactly once.
-
- Parameters:
-
- * ``eventName`` is the event name as a string.
- * ``callback`` is the callback method to be called when the event is emitted.
-
- For example::
-
- converse.listen.once('message', function (messageXML) { ... });
-
-* **not(eventName, callback)**
-
- To stop listening to an event, you can use the ``not`` method.
-
- Parameters:
-
- * ``eventName`` is the event name as a string.
- * ``callback`` refers to the function that is to be no longer executed.
-
- For example::
-
- converse.listen.not('message', function (messageXML) { ... });
-
-Events
-======
-
-.. note:: see also the `"listen" grouping`_ API section above.
-
-Event Types
------------
-
-Here are the different events that are emitted:
-
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| Event Type | When is it triggered? | Example |
-+================================+===================================================================================================+=========================================================================================+
-| **initialized** | Once converse.js has been initialized. | ``converse.on('initialized', function () { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **ready** | After connection has been established and converse.js has got all its ducks in a row. | ``converse.on('ready', function () { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **reconnect** | After the connection has dropped. Converse.js will attempt to reconnect when not in prebind mode. | ``converse.on('reconnect', function () { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **message** | When a message is received. | ``converse.on('message', function (messageXML) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **messageSend** | When a message will be sent out. | ``converse.on('messageSend', function (messageText) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **noResumeableSession** | When keepalive=true but there aren't any stored prebind tokens. | ``converse.on('noResumeableSession', function () { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **roster** | When the roster is updated. | ``converse.on('roster', function (items) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **callButtonClicked** | When a call button (i.e. with class .toggle-call) on a chat box has been clicked. | ``converse.on('callButtonClicked', function (connection, model) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **chatBoxOpened** | When a chat box has been opened. | ``converse.on('chatBoxOpened', function (chatbox) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **chatRoomOpened** | When a chat room has been opened. | ``converse.on('chatRoomOpened', function (chatbox) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **chatBoxClosed** | When a chat box has been closed. | ``converse.on('chatBoxClosed', function (chatbox) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **chatBoxFocused** | When the focus has been moved to a chat box. | ``converse.on('chatBoxFocused', function (chatbox) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **chatBoxToggled** | When a chat box has been minimized or maximized. | ``converse.on('chatBoxToggled', function (chatbox) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **roomInviteSent** | After the user has sent out a direct invitation, to a roster contact, asking them to join a room. | ``converse.on('roomInvite', function (roomview, invitee_jid, reason) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **roomInviteReceived** | After the user has sent out a direct invitation, to a roster contact, asking them to join a room. | ``converse.on('roomInvite', function (roomview, invitee_jid, reason) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **statusChanged** | When own chat status has changed. | ``converse.on('statusChanged', function (status) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **statusMessageChanged** | When own custom status message has changed. | ``converse.on('statusMessageChanged', function (message) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **buddyStatusChanged** | When a chat buddy's chat status has changed. | ``converse.on('buddyStatusChanged', function (buddy, status) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-| **buddyStatusMessageChanged** | When a chat buddy's custom status message has changed. | ``converse.on('buddyStatusMessageChanged', function (buddy, messageText) { ... });`` |
-+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
-
-
-Minification
-============
-
-Minifying Javascript and CSS
-----------------------------
-
-Please make sure to read the section `Development`_ and that you have installed
-all development dependencies (long story short, you can run ``npm install``
-and then ``grunt fetch``).
-
-We use `require.js`_ to keep track of *Converse.js* and its dependencies and to
-to bundle them together in a single minified file fit for deployment to a
-production site.
-
-To minify the Javascript and CSS, run the following command:
-
-::
-
- grunt minify
-
-Javascript will be bundled and minified with `require.js`_'s optimization tool,
-using `almond `_.
-
-You can `read more about require.js's optimizer here`_.
-
-CSS is minified via `cssmin `_.
-
-Translations
-============
-
-.. note::
- Translations take up a lot of space and will bloat your minified file.
- At the time of writing, all the translations add about 50KB of extra data to
- the minified javascript file. Therefore, make sure to only
- include those languages that you intend to support and remove from
- ./locale/locales.js those which you don't need. Remember to rebuild the
- minified file afterwards.
-
-The gettext POT file located in ./locale/converse.pot is the template
-containing all translations and from which for each language an individual PO
-file is generated.
-
-The POT file contains all translateable strings extracted from converse.js.
-
-To make a user facing string translateable, wrap it in the double underscore helper
-function like so:
-
-::
-
- __('This string will be translated at runtime');
-
-After adding the string, you'll need to regenerate the POT file, like so:
-
-::
-
- make pot
-
-To create a new PO file for a language in which converse.js is not yet
-translated into, do the following
-
-.. note:: In this example we use Polish (pl), you need to substitute 'pl' to your own language's code.
-
-::
-
- mkdir -p ./locale/pl/LC_MESSAGES
- msginit -i ./locale/converse.pot -o ./locale/pl/LC_MESSAGES/converse.po -l pl
-
-You can then create or update the PO file for a specific language by doing the following:
-
-.. note:: In this example we use German (de), you need to substitute 'de' to your own language's code.
-
-::
-
- msgmerge ./locale/de/LC_MESSAGES/converse.po ./locale/converse.pot -U
-
-To do this for ALL languages, run:
-
-::
-
- make po
-
-The resulting PO file is then what gets translated.
-
-If you've created a new PO file, please make sure to add the following
-attributes at the top of the file (under *Content-Transfer-Encoding*). They are
-required as configuration settings for Jed, the Javascript translations library
-that we're using.
-
-::
-
- "domain: converse\n"
- "lang: de\n"
- "plural_forms: nplurals=2; plural=(n != 1);\n"
-
-
-Unfortunately `Jed `_ cannot use the PO files directly. We have to generate from it
-a file in JSON format and then put that in a .js file for the specific
-language.
-
-To generate JSON from a PO file, you'll need po2json for node.js. Run the
-following command to install it (npm being the node.js package manager):
-
-::
-
- npm install po2json
-
-You can then convert the translations into JSON format:
-
-::
-
- po2json locale/de/LC_MESSAGES/converse.po locale/de/LC_MESSAGES/converse.json
-
-Now from converse.json paste the data as a value for the "locale_data" key in the
-object in the language's .js file.
-
-So, if you are for example translating into German (language code 'de'), you'll
-create or update the file ./locale/LC_MESSAGES/de.js with the following code:
-
-::
-
- (function (root, factory) {
- define("de", ['jed'], function () {
- return factory(new Jed({
- "domain": "converse",
- "locale_data": {
- // Paste the JSON data from converse.json here
- }
- })
- }
- }(this, function (i18n) {
- return i18n;
- }));
-
-making sure to also paste the JSON data as value to the "locale_data" key.
-
-.. note::
- If you are adding translations for a new language that is not already supported,
- you'll have to add the language path in main.js and make one more edit in ./locale/locales.js
- to make sure the language is loaded by require.js.
-
-Congratulations, you've now succesfully added your translations. Sorry for all
-those hoops you had to jump through.
-
-
-
-===============
-Troubleshooting
-===============
-
-Conflicts with other Javascript libraries
-=========================================
-
-Problem:
----------
-
-You are using other Javascript libraries (like JQuery plugins), and
-get errors like these in your browser console::
-
- Uncaught TypeError: Object [object Object] has no method 'xxx' from example.js
-
-Solution:
----------
-
-First, find out which object is referred to by ``Object [object Object]``.
-
-It will probably be the jQuery object ``$`` or perhaps the underscore.js object ``_``.
-
-For the purpose of demonstration, I'm going to assume its ``$``, but the same
-rules apply if its something else.
-
-The bundled and minified default build of converse.js, ``converse.min.js``
-includes within it all of converse.js's dependencies, which include for example *jQuery*.
-
-If you are having conflicts where attributes or methods aren't available
-on the jQuery object, you are probably loading ``converse.min.js`` (which
-includes jQuery) as well as your own jQuery version separately.
-
-What then happens is that there are two ``$`` objects (one from
-converse.js and one from the jQuery version you included manually)
-and only one of them has been extended to have the methods or attributes you require.
-
-Which jQuery object you get depends on the order in which you load the libraries.
-
-There are multiple ways to solve this issue.
-
-Firstly, make sure whether you really need to include a separate version of
-jQuery. Chances are that you don't. If you can remove the separate
-version, your problem should be solved, as long as your libraries are loaded in
-the right order.
-
-Either case, whether you need to keep two versions or not, the solution depends
-on whether you'll use require.js to manage your libraries or whether you'll
-load them manually.
-
-With require.js
-~~~~~~~~~~~~~~~
-
-Instead of using ``converse.min.js``, manage all the libraries in your project
-(i.e. converse.js and its dependencies plus all other libraries you use) as one
-require.js project, making sure everything is loaded in the correct order.
-
-Then, before deployment, you make your own custom minified build that bundles everything
-you need.
-
-With
-
-
-
-
-
-
-