瀏覽代碼

Split development docs into separate files/sections

JC Brand 8 年之前
父節點
當前提交
575e9da705

+ 5 - 0
docs/source/_static/style.css

@@ -15,6 +15,11 @@ h5 {
     font-weight: bold;
     font-weight: bold;
 }
 }
 
 
+.toctree-l1 > a {
+    font-size: 110%;
+    font-weight: bold;
+}
+
 .navbar-brand {
 .navbar-brand {
     padding-top: 7px;
     padding-top: 7px;
 }
 }

+ 124 - 0
docs/source/dependencies.rst

@@ -0,0 +1,124 @@
+Developer guidelines
+====================
+
+If you want to work with the non-minified Javascript and CSS files you'll soon
+notice that there are references to missing *components* and *node_modules* directories.
+Please follow the instructions below to create these directories and fetch Converse's
+3rd-party dependencies.
+
+.. note::
+    Windows environment: We recommend installing the required tools using `Chocolatey <https://chocolatey.org/>`_
+    You will need Node.js (nodejs.install), Git (git.install) and optionally to build using Makefile, GNU Make (make)
+    If you have trouble setting up a development environment on Windows,
+    please read `this post <http://librelist.com/browser//conversejs/2014/11/5/openfire-converse-and-visual-studio-questions/#b28387e7f8f126693b11598a8acbe810>`_
+    in the mailing list.:
+
+Installing the development and front-end dependencies
+-----------------------------------------------------
+
+We use development tools (`Grunt <http://gruntjs.com>`_ and `Bower <http://bower.io>`_)
+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 <https://nodejs.org/download>`_.
+
+Also make sure you have ``Git`` installed. `Details <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
+
+.. note::
+    Windows users should use Chocolatey as recommended above.
+
+.. note::
+    Debian & Ubuntu users : apt-get install git npm nodejs-legacy
+
+Once you have *Node.js* and *git* installed, run the following command inside the Converse.js
+directory:
+
+::
+
+    make dev
+
+On Windows you need to specify Makefile.win to be used by running: ::
+
+    make -f Makefile.win 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)
+as well as 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.
+
+To see the dependencies, take a look at whats under the *devDependencies* key in
+    `package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
+
+.. note::
+    After running ```make dev```, you should now have new directories *components*
+    and *node_modules*, which contain all the front-end dependencies of Converse.js.
+    If these 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
+
+Loading converse.js and its dependencies
+----------------------------------------
+
+With AMD and require.js (recommended)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Converse.js uses `require.js <http://requirejs.org>`_ 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 *<head>* section of your webpage:
+
+.. code-block:: html
+
+    <link rel="stylesheet" type="text/css" media="screen" href="converse.css">
+    <script data-main="main" src="components/requirejs/require.js"></script>
+
+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 <https://github.com/jcbrand/converse.js/blob/master/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
+--------------------------------
+
+Please follow the usual github workflow. Create your own local fork of this repository,
+make your changes and then submit a pull request.
+
+Follow the programming style guide
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Please read the `style guide </docs/html/style_guide.html>`_ and make sure that your code follows it.
+
+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 <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
+and the `spec files <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
+to see how tests are implemented.
+
+Check that the tests pass
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Check that all tests complete sucessfully.
+
+Run ``make check`` in your terminal or open `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
+in your browser.

+ 678 - 0
docs/source/developer_api.rst

@@ -0,0 +1,678 @@
+The converse.js 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, such as::
+
+    .get
+    .set
+    .add
+    .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']);
+
+To get all contacts, simply call ``get`` without any jids::
+
+    converse.contacts.get();
+
+
+**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 :ref:`configuration-variables`.
+
+Example:
+
+.. code-block:: javascript
+
+    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
+        });
+
+send
+----
+
+Allows you to send XML stanzas.
+
+For example, to send a message stanza:
+
+.. code-block:: javascript
+
+    var msg = converse.env.$msg({
+        from: 'juliet@example.com/balcony',
+        to:'romeo@example.net',
+        type:'chat'
+    });
+    converse.send(msg);
+
+
+The "archive" grouping
+----------------------
+
+Converse.js supports the *Message Archive Management*
+(`XEP-0313 <https://xmpp.org/extensions/xep-0313.html>`_) protocol,
+through which it is able to query an XMPP server for archived messages.
+
+See also the **message_archiving** option in the :ref:`configuration-variables` section, which you'll usually
+want to  in conjunction with this API.
+
+query
+~~~~~
+
+The ``query`` method is used to query for archived messages.
+
+It accepts the following optional parameters:
+
+* **options** an object containing the query parameters. Valid query parameters
+  are ``with``, ``start``, ``end``, ``first``, ``last``, ``after``, ``before``, ``index`` and ``count``.
+* **callback** is the callback method that will be called when all the messages
+  have been received.
+* **errback** is the callback method to be called when an error is returned by
+  the XMPP server, for example when it doesn't support message archiving.
+
+Examples
+^^^^^^^^
+
+**Requesting all archived messages**
+
+The simplest query that can be made is to simply not pass in any parameters.
+Such a query will return all archived messages for the current user.
+
+Generally, you'll however always want to pass in a callback method, to receive
+the returned messages.
+
+.. code-block:: javascript
+
+    var errback = function (iq) {
+        // The query was not successful, perhaps inform the user?
+        // The IQ stanza returned by the XMPP server is passed in, so that you
+        // may inspect it and determine what the problem was.
+    }
+    var callback = function (messages) {
+        // Do something with the messages, like showing them in your webpage.
+    }
+    converse.archive.query(callback, errback))
+
+
+**Waiting until server support has been determined**
+
+The query method will only work if converse.js has been able to determine that
+the server supports MAM queries, otherwise the following error will be raised:
+
+- *This server does not support XEP-0313, Message Archive Management*
+
+The very first time converse.js loads in a browser tab, if you call the query
+API too quickly, the above error might appear because service discovery has not
+yet been completed.
+
+To work solve this problem, you can first listen for the ``serviceDiscovered`` event,
+through which you can be informed once support for MAM has been determined.
+
+For example:
+
+.. code-block:: javascript
+
+    converse.listen.on('serviceDiscovered', function (event, feature) {
+        if (feature.get('var') === converse.env.Strophe.NS.MAM) {
+            converse.archive.query()
+        }
+    });
+
+**Requesting all archived messages for a particular contact or room**
+
+To query for messages sent between the current user and another user or room,
+the query options need to contain the the JID (Jabber ID) of the user or
+room under the  ``with`` key.
+
+.. code-block:: javascript
+
+    // For a particular user
+    converse.archive.query({'with': 'john@doe.net'}, callback, errback);)
+
+    // For a particular room
+    converse.archive.query({'with': 'discuss@conference.doglovers.net'}, callback, errback);)
+
+
+**Requesting all archived messages before or after a certain date**
+
+The ``start`` and ``end`` parameters are used to query for messages
+within a certain timeframe. The passed in date values may either be ISO8601
+formatted date strings, or Javascript Date objects.
+
+.. code-block:: javascript
+
+    var options = {
+        'with': 'john@doe.net',
+        'start': '2010-06-07T00:00:00Z',
+        'end': '2010-07-07T13:23:54Z'
+    };
+    converse.archive.query(options, callback, errback);
+
+
+**Limiting the amount of messages returned**
+
+The amount of returned messages may be limited with the ``max`` parameter.
+By default, the messages are returned from oldest to newest.
+
+.. code-block:: javascript
+
+    // Return maximum 10 archived messages
+    converse.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
+
+
+**Paging forwards through a set of archived messages**
+
+When limiting the amount of messages returned per query, you might want to
+repeatedly make a further query to fetch the next batch of messages.
+
+To simplify this usecase for you, the callback method receives not only an array
+with the returned archived messages, but also a special RSM (*Result Set
+Management*) object which contains the query parameters you passed in, as well
+as two utility methods ``next``, and ``previous``.
+
+When you call one of these utility methods on the returned RSM object, and then
+pass the result into a new query, you'll receive the next or previous batch of
+archived messages. Please note, when calling these methods, pass in an integer
+to limit your results.
+
+.. code-block:: javascript
+
+    var callback = function (messages, rsm) {
+        // Do something with the messages, like showing them in your webpage.
+        // ...
+        // You can now use the returned "rsm" object, to fetch the next batch of messages:
+        converse.archive.query(rsm.next(10), callback, errback))
+
+    }
+    converse.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
+
+**Paging backwards through a set of archived messages**
+
+To page backwards through the archive, you need to know the UID of the message
+which you'd like to page backwards from and then pass that as value for the
+``before`` parameter. If you simply want to page backwards from the most recent
+message, pass in the ``before`` parameter with an empty string value ``''``.
+
+.. code-block:: javascript
+
+    converse.archive.query({'before': '', 'max':5}, function (message, rsm) {
+        // Do something with the messages, like showing them in your webpage.
+        // ...
+        // You can now use the returned "rsm" object, to fetch the previous batch of messages:
+        rsm.previous(5); // Call previous method, to update the object's parameters,
+                         // passing in a limit value of 5.
+        // Now we query again, to get the previous batch.
+        converse.archive.query(rsm, callback, errback);
+    }
+
+The "connection" grouping
+-------------------------
+
+This grouping collects API functions related to the XMPP connection.
+
+connected
+~~~~~~~~~
+
+A boolean attribute (i.e. not a callable) which is set to `true` or `false` depending
+on whether there is an established connection.
+
+disconnect
+~~~~~~~~~~
+
+Terminates the connection.
+
+
+The "user" grouping
+-------------------
+
+This grouping collects API functions related to the current logged in user.
+
+jid
+~~~
+
+Return's the current user's full JID (Jabber ID).
+
+.. code-block:: javascript
+
+    converse.user.jid()
+    // Returns for example jc@opkode.com/conversejs-351236
+
+login
+~~~~~
+
+Logs the user in. This method can accept a map with the credentials, like this:
+
+.. code-block:: javascript
+
+    converse.user.login({
+        'jid': 'dummy@example.com',
+        'password': 'secret'
+    });
+
+or it can be called without any parameters, in which case converse.js will try
+to log the user in by calling the `prebind_url` or `credentials_url` depending
+on whether prebinding is used or not.
+
+logout
+~~~~~~
+
+Log the user out of the current XMPP session.
+
+.. code-block:: javascript
+
+    converse.user.logout();
+
+
+The "status" sub-grouping
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set and get the user's chat status, also called their *availability*.
+
+get
+^^^
+
+Return the current user's availability status:
+
+.. code-block:: javascript
+
+    converse.user.status.get(); // Returns for example "dnd"
+
+set
+^^^
+
+The user's status can be set to one of the following values:
+
+* **away**
+* **dnd**
+* **offline**
+* **online**
+* **unavailable**
+* **xa**
+
+For example:
+
+.. code-block:: javascript
+
+    converse.user.status.set('dnd');
+
+Because the user's availability is often set together with a custom status
+message, this method also allows you to pass in a status message as a
+second parameter:
+
+.. code-block:: javascript
+
+    converse.user.status.set('dnd', 'In a meeting');
+
+The "message" sub-grouping
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The ``user.status.message`` sub-grouping exposes methods for setting and
+retrieving the user's custom status message.
+
+.. code-block:: javascript
+
+    converse.user.status.message.set('In a meeting');
+
+    converse.user.status.message.get(); // Returns "In a meeting"
+
+
+The "contacts" grouping
+-----------------------
+
+get
+~~~
+
+This method is used to retrieve roster contacts.
+
+To get a single roster contact, call the method with the contact's JID (Jabber ID):
+
+.. code-block:: javascript
+
+    converse.contacts.get('buddy@example.com')
+
+To get multiple contacts, pass in an array of JIDs:
+
+.. code-block:: javascript
+
+    converse.contacts.get(['buddy1@example.com', 'buddy2@example.com'])
+
+To return all contacts, simply call ``get`` without any parameters:
+
+.. code-block:: javascript
+
+    converse.contacts.get()
+
+
+The returned roster contact objects have these 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.                                                                        |
++----------------+-----------------------------------------------------------------------------------------------------------------+
+
+add
+~~~
+
+Add a contact.
+
+Provide the JID of the contact you want to add:
+
+.. code-block:: javascript
+
+    converse.contacts.add('buddy@example.com')
+
+You may also provide the fullname. If not present, we use the jid as fullname:
+
+.. code-block:: javascript
+
+    converse.contacts.add('buddy@example.com', 'Buddy')
+
+The "chats" grouping
+--------------------
+
+Note, for MUC chat rooms, you need to use the "rooms" grouping instead.
+
+get
+~~~
+
+Returns an object representing a chat box.
+
+To return a single chat box, provide the JID of the contact you're chatting
+with in that chat box:
+
+.. code-block:: javascript
+
+    converse.chats.get('buddy@example.com')
+
+To return an array of chat boxes, provide an array of JIDs:
+
+.. code-block:: javascript
+
+    converse.chats.get(['buddy1@example.com', 'buddy2@example.com'])
+
+To return all open chat boxes, call the method without any JIDs::
+
+    converse.chats.get()
+
+open
+~~~~
+
+Opens a chat box and returns an object representing a chat box.
+
+To open a single chat box, provide the JID of the contact:
+
+.. code-block:: javascript
+
+    converse.chats.open('buddy@example.com')
+
+To return an array of chat boxes, provide an array of JIDs:
+
+.. code-block:: javascript
+
+    converse.chats.open(['buddy1@example.com', 'buddy2@example.com'])
+
+
+*The returned chat box object 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).         |
++-------------+------------------------------------------+
+| close       | Close the chat box.                      |
++-------------+------------------------------------------+
+| open        | Opens the chat box.                      |
++-------------+------------------------------------------+
+
+*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.                    |
++-------------+-----------------------------------------------------+
+
+The "rooms" grouping
+--------------------
+
+get
+~~~
+
+Returns an object representing a multi user chat box (room).
+It takes 3 parameters:
+
+* the room JID (if not specified, all rooms will be returned).
+* a map (object) containing any extra room attributes For example, if you want
+  to specify the nickname, use ``{'nick': 'bloodninja'}``. Previously (before
+  version 1.0.7, the second parameter only accepted the nickname (as a string
+  value). This is currently still accepted, but then you can't pass in any
+  other room attributes. If the nickname is not specified then the node part of
+  the user's JID will be used.
+* a boolean, indicating whether the room should be created if not found (default: `false`)
+
+.. code-block:: javascript
+
+    var nick = 'dread-pirate-roberts';
+    var create_if_not_found = true;
+    converse.rooms.open('group@muc.example.com', {'nick': nick}, create_if_not_found)
+
+open
+~~~~
+
+Opens a multi user chat box and returns an object representing it.
+Similar to chats.get API
+
+It takes 2 parameters:
+
+* the room JID (if not specified, all rooms will be returned).
+* a map (object) containing any extra room attributes. For example, if you want
+  to specify the nickname, use ``{'nick': 'bloodninja'}``.
+
+To open a single multi user chat box, provide the JID of the room:
+
+.. code-block:: javascript
+
+    converse.rooms.open('group@muc.example.com')
+
+To return an array of rooms, provide an array of room JIDs:
+
+.. code-block:: javascript
+
+    converse.rooms.open(['group1@muc.example.com', 'group2@muc.example.com'])
+
+To setup a custom nickname when joining the room, provide the optional nick argument:
+
+.. code-block:: javascript
+
+    converse.rooms.open('group@muc.example.com', {'nick': 'mycustomnick'})
+
+close
+~~~~~
+
+Lets you close open chat rooms. You can call this method without any arguments
+to close all open chat rooms, or you can specify a single JID or an array of
+JIDs.
+
+The "settings" grouping
+-----------------------
+
+This grouping allows you to get or set the configuration settings of converse.js.
+
+get(key)
+~~~~~~~~
+
+Returns the value of a configuration settings. For example:
+
+.. code-block:: javascript
+
+    converse.settings.get("play_sounds"); // default value returned would be false;
+
+set(key, value) or set(object)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set one or many configuration settings. For example:
+
+.. code-block:: javascript
+
+    converse.settings.set("play_sounds", true);
+
+or :
+
+.. code-block:: javascript
+
+    converse.settings.set({
+        "play_sounds", true,
+        "hide_offline_users" true
+    });
+
+Note, this is not an alternative to calling ``converse.initialize``, which still needs
+to be called. Generally, you'd use this method after converse.js is already
+running and you want to change the configuration on-the-fly.
+
+The "tokens" grouping
+---------------------
+
+get
+~~~
+
+Returns a token, either the RID or SID token depending on what's asked for.
+
+Example:
+
+.. code-block:: javascript
+
+    converse.tokens.get('rid')
+
+
+.. _`listen-grouping`:
+
+The "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, [context])**:
+
+    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.
+    * ``context`` (optional), the value of the `this` parameter for the callback.
+
+    For example:
+
+.. code-block:: javascript
+
+        converse.listen.on('message', function (event, messageXML) { ... });
+
+* **once(eventName, callback, [context])**:
+
+    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.
+    * ``context`` (optional), the value of the `this` parameter for the callback.
+
+    For example:
+
+.. code-block:: javascript
+
+        converse.listen.once('message', function (event, 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:
+
+.. code-block:: javascript
+
+        converse.listen.not('message', function (event, messageXML) { ... });
+

+ 124 - 0
docs/source/developer_guidelines.rst

@@ -0,0 +1,124 @@
+Developer guidelines
+====================
+
+If you want to work with the non-minified Javascript and CSS files you'll soon
+notice that there are references to missing *components* and *node_modules* directories.
+Please follow the instructions below to create these directories and fetch Converse's
+3rd-party dependencies.
+
+.. note::
+    Windows environment: We recommend installing the required tools using `Chocolatey <https://chocolatey.org/>`_
+    You will need Node.js (nodejs.install), Git (git.install) and optionally to build using Makefile, GNU Make (make)
+    If you have trouble setting up a development environment on Windows,
+    please read `this post <http://librelist.com/browser//conversejs/2014/11/5/openfire-converse-and-visual-studio-questions/#b28387e7f8f126693b11598a8acbe810>`_
+    in the mailing list.:
+
+Installing the development and front-end dependencies
+-----------------------------------------------------
+
+We use development tools (`Grunt <http://gruntjs.com>`_ and `Bower <http://bower.io>`_)
+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 <https://nodejs.org/download>`_.
+
+Also make sure you have ``Git`` installed. `Details <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
+
+.. note::
+    Windows users should use Chocolatey as recommended above.
+
+.. note::
+    Debian & Ubuntu users : apt-get install git npm nodejs-legacy
+
+Once you have *Node.js* and *git* installed, run the following command inside the Converse.js
+directory:
+
+::
+
+    make dev
+
+On Windows you need to specify Makefile.win to be used by running: ::
+
+    make -f Makefile.win 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)
+as well as 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.
+
+To see the dependencies, take a look at whats under the *devDependencies* key in
+    `package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
+
+.. note::
+    After running ```make dev```, you should now have new directories *components*
+    and *node_modules*, which contain all the front-end dependencies of Converse.js.
+    If these 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
+
+Loading converse.js and its dependencies
+----------------------------------------
+
+With AMD and require.js (recommended)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Converse.js uses `require.js <http://requirejs.org>`_ 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 *<head>* section of your webpage:
+
+.. code-block:: html
+
+    <link rel="stylesheet" type="text/css" media="screen" href="converse.css">
+    <script data-main="main" src="components/requirejs/require.js"></script>
+
+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 <https://github.com/jcbrand/converse.js/blob/master/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
+--------------------------------
+
+Please follow the usual github workflow. Create your own local fork of this repository,
+make your changes and then submit a pull request.
+
+Follow the programming style guide
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Please read the `style guide </docs/html/style_guide.html>`_ and make sure that your code follows it.
+
+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 <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
+and the `spec files <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
+to see how tests are implemented.
+
+Check that the tests pass
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Check that all tests complete sucessfully.
+
+Run ``make check`` in your terminal or open `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
+in your browser.

+ 21 - 1298
docs/source/development.rst

@@ -8,1301 +8,24 @@
 Development
 Development
 ===========
 ===========
 
 
-.. contents:: Table of Contents
-   :depth: 2
-   :local:
-
-If you want to work with the non-minified Javascript and CSS files you'll soon
-notice that there are references to missing *components* and *node_modules* directories.
-Please follow the instructions below to create these directories and fetch Converse's
-3rd-party dependencies.
-
-.. note::
-    Windows environment: We recommend installing the required tools using `Chocolatey <https://chocolatey.org/>`_
-    You will need Node.js (nodejs.install), Git (git.install) and optionally to build using Makefile, GNU Make (make)
-    If you have trouble setting up a development environment on Windows,
-    please read `this post <http://librelist.com/browser//conversejs/2014/11/5/openfire-converse-and-visual-studio-questions/#b28387e7f8f126693b11598a8acbe810>`_
-    in the mailing list.:
-
-Install the development and front-end dependencies
-==================================================
-
-We use development tools (`Grunt <http://gruntjs.com>`_ and `Bower <http://bower.io>`_)
-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 <https://nodejs.org/download>`_.
-
-Also make sure you have ``Git`` installed. `Details <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
-
-.. note::
-    Windows users should use Chocolatey as recommended above.
-
-.. note::
-    Debian & Ubuntu users : apt-get install git npm nodejs-legacy
-
-Once you have *Node.js* and *git* installed, run the following command inside the Converse.js
-directory:
-
-::
-
-    make dev
-
-On Windows you need to specify Makefile.win to be used by running: ::
-
-    make -f Makefile.win 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)
-as well as 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.
-
-To see the dependencies, take a look at whats under the *devDependencies* key in
-    `package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
-
-.. note::
-    After running ```make dev```, you should now have new directories *components*
-    and *node_modules*, which contain all the front-end dependencies of Converse.js.
-    If these 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 <http://requirejs.org>`_ 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 *<head>* section of your webpage:
-
-.. code-block:: html
-
-    <link rel="stylesheet" type="text/css" media="screen" href="converse.css">
-    <script data-main="main" src="components/requirejs/require.js"></script>
-
-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 <https://github.com/jcbrand/converse.js/blob/master/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
-================================
-
-Please follow the usual github workflow. Create your own local fork of this repository,
-make your changes and then submit a pull request.
-
-The programming style guide
----------------------------
-
-Please read the `style guide </docs/html/style_guide.html>`_ and make sure that your code follows it.
-
-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 <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
-and the `spec files <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
-to see how tests are implemented.
-
-Check that the tests pass
--------------------------
-Check that all tests complete sucessfully.
-
-Run ``make check`` in your terminal or open `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
-in your browser.
-
-
-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, such as::
-
-    .get
-    .set
-    .add
-    .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']);
-
-To get all contacts, simply call ``get`` without any jids::
-
-    converse.contacts.get();
-
-
-**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 :ref:`configuration-variables`.
-
-Example:
-
-.. code-block:: javascript
-
-    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
-        });
-
-send
-----
-
-Allows you to send XML stanzas.
-
-For example, to send a message stanza:
-
-.. code-block:: javascript
-
-    var msg = converse.env.$msg({
-        from: 'juliet@example.com/balcony',
-        to:'romeo@example.net',
-        type:'chat'
-    });
-    converse.send(msg);
-
-
-The "archive" grouping
-----------------------
-
-Converse.js supports the *Message Archive Management*
-(`XEP-0313 <https://xmpp.org/extensions/xep-0313.html>`_) protocol,
-through which it is able to query an XMPP server for archived messages.
-
-See also the **message_archiving** option in the :ref:`configuration-variables` section, which you'll usually
-want to  in conjunction with this API.
-
-query
-~~~~~
-
-The ``query`` method is used to query for archived messages.
-
-It accepts the following optional parameters:
-
-* **options** an object containing the query parameters. Valid query parameters
-  are ``with``, ``start``, ``end``, ``first``, ``last``, ``after``, ``before``, ``index`` and ``count``.
-* **callback** is the callback method that will be called when all the messages
-  have been received.
-* **errback** is the callback method to be called when an error is returned by
-  the XMPP server, for example when it doesn't support message archiving.
-
-Examples
-^^^^^^^^
-
-**Requesting all archived messages**
-
-The simplest query that can be made is to simply not pass in any parameters.
-Such a query will return all archived messages for the current user.
-
-Generally, you'll however always want to pass in a callback method, to receive
-the returned messages.
-
-.. code-block:: javascript
-
-    var errback = function (iq) {
-        // The query was not successful, perhaps inform the user?
-        // The IQ stanza returned by the XMPP server is passed in, so that you
-        // may inspect it and determine what the problem was.
-    }
-    var callback = function (messages) {
-        // Do something with the messages, like showing them in your webpage.
-    }
-    converse.archive.query(callback, errback))
-
-
-**Waiting until server support has been determined**
-
-The query method will only work if converse.js has been able to determine that
-the server supports MAM queries, otherwise the following error will be raised:
-
-- *This server does not support XEP-0313, Message Archive Management*
-
-The very first time converse.js loads in a browser tab, if you call the query
-API too quickly, the above error might appear because service discovery has not
-yet been completed.
-
-To work solve this problem, you can first listen for the ``serviceDiscovered`` event,
-through which you can be informed once support for MAM has been determined.
-
-For example:
-
-.. code-block:: javascript
-
-    converse.listen.on('serviceDiscovered', function (event, feature) {
-        if (feature.get('var') === converse.env.Strophe.NS.MAM) {
-            converse.archive.query()
-        }
-    });
-
-**Requesting all archived messages for a particular contact or room**
-
-To query for messages sent between the current user and another user or room,
-the query options need to contain the the JID (Jabber ID) of the user or
-room under the  ``with`` key.
-
-.. code-block:: javascript
-
-    // For a particular user
-    converse.archive.query({'with': 'john@doe.net'}, callback, errback);)
-
-    // For a particular room
-    converse.archive.query({'with': 'discuss@conference.doglovers.net'}, callback, errback);)
-
-
-**Requesting all archived messages before or after a certain date**
-
-The ``start`` and ``end`` parameters are used to query for messages
-within a certain timeframe. The passed in date values may either be ISO8601
-formatted date strings, or Javascript Date objects.
-
-.. code-block:: javascript
-
-    var options = {
-        'with': 'john@doe.net',
-        'start': '2010-06-07T00:00:00Z',
-        'end': '2010-07-07T13:23:54Z'
-    };
-    converse.archive.query(options, callback, errback);
-
-
-**Limiting the amount of messages returned**
-
-The amount of returned messages may be limited with the ``max`` parameter.
-By default, the messages are returned from oldest to newest.
-
-.. code-block:: javascript
-
-    // Return maximum 10 archived messages
-    converse.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
-
-
-**Paging forwards through a set of archived messages**
-
-When limiting the amount of messages returned per query, you might want to
-repeatedly make a further query to fetch the next batch of messages.
-
-To simplify this usecase for you, the callback method receives not only an array
-with the returned archived messages, but also a special RSM (*Result Set
-Management*) object which contains the query parameters you passed in, as well
-as two utility methods ``next``, and ``previous``.
-
-When you call one of these utility methods on the returned RSM object, and then
-pass the result into a new query, you'll receive the next or previous batch of
-archived messages. Please note, when calling these methods, pass in an integer
-to limit your results.
-
-.. code-block:: javascript
-
-    var callback = function (messages, rsm) {
-        // Do something with the messages, like showing them in your webpage.
-        // ...
-        // You can now use the returned "rsm" object, to fetch the next batch of messages:
-        converse.archive.query(rsm.next(10), callback, errback))
-
-    }
-    converse.archive.query({'with': 'john@doe.net', 'max':10}, callback, errback);
-
-**Paging backwards through a set of archived messages**
-
-To page backwards through the archive, you need to know the UID of the message
-which you'd like to page backwards from and then pass that as value for the
-``before`` parameter. If you simply want to page backwards from the most recent
-message, pass in the ``before`` parameter with an empty string value ``''``.
-
-.. code-block:: javascript
-
-    converse.archive.query({'before': '', 'max':5}, function (message, rsm) {
-        // Do something with the messages, like showing them in your webpage.
-        // ...
-        // You can now use the returned "rsm" object, to fetch the previous batch of messages:
-        rsm.previous(5); // Call previous method, to update the object's parameters,
-                         // passing in a limit value of 5.
-        // Now we query again, to get the previous batch.
-        converse.archive.query(rsm, callback, errback);
-    }
-
-The "connection" grouping
--------------------------
-
-This grouping collects API functions related to the XMPP connection.
-
-connected
-~~~~~~~~~
-
-A boolean attribute (i.e. not a callable) which is set to `true` or `false` depending
-on whether there is an established connection.
-
-disconnect
-~~~~~~~~~~
-
-Terminates the connection.
-
-
-The "user" grouping
--------------------
-
-This grouping collects API functions related to the current logged in user.
-
-jid
-~~~
-
-Return's the current user's full JID (Jabber ID).
-
-.. code-block:: javascript
-
-    converse.user.jid()
-    // Returns for example jc@opkode.com/conversejs-351236
-
-login
-~~~~~
-
-Logs the user in. This method can accept a map with the credentials, like this:
-
-.. code-block:: javascript
-
-    converse.user.login({
-        'jid': 'dummy@example.com',
-        'password': 'secret'
-    });
-
-or it can be called without any parameters, in which case converse.js will try
-to log the user in by calling the `prebind_url` or `credentials_url` depending
-on whether prebinding is used or not.
-
-logout
-~~~~~~
-
-Log the user out of the current XMPP session.
-
-.. code-block:: javascript
-
-    converse.user.logout();
-
-
-The "status" sub-grouping
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Set and get the user's chat status, also called their *availability*.
-
-get
-^^^
-
-Return the current user's availability status:
-
-.. code-block:: javascript
-
-    converse.user.status.get(); // Returns for example "dnd"
-
-set
-^^^
-
-The user's status can be set to one of the following values:
-
-* **away**
-* **dnd**
-* **offline**
-* **online**
-* **unavailable**
-* **xa**
-
-For example:
-
-.. code-block:: javascript
-
-    converse.user.status.set('dnd');
-
-Because the user's availability is often set together with a custom status
-message, this method also allows you to pass in a status message as a
-second parameter:
-
-.. code-block:: javascript
-
-    converse.user.status.set('dnd', 'In a meeting');
-
-The "message" sub-grouping
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The ``user.status.message`` sub-grouping exposes methods for setting and
-retrieving the user's custom status message.
-
-.. code-block:: javascript
-
-    converse.user.status.message.set('In a meeting');
-
-    converse.user.status.message.get(); // Returns "In a meeting"
-
-
-The "contacts" grouping
------------------------
-
-get
-~~~
-
-This method is used to retrieve roster contacts.
-
-To get a single roster contact, call the method with the contact's JID (Jabber ID):
-
-.. code-block:: javascript
-
-    converse.contacts.get('buddy@example.com')
-
-To get multiple contacts, pass in an array of JIDs:
-
-.. code-block:: javascript
-
-    converse.contacts.get(['buddy1@example.com', 'buddy2@example.com'])
-
-To return all contacts, simply call ``get`` without any parameters:
-
-.. code-block:: javascript
-
-    converse.contacts.get()
-
-
-The returned roster contact objects have these 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.                                                                        |
-+----------------+-----------------------------------------------------------------------------------------------------------------+
-
-add
-~~~
-
-Add a contact.
-
-Provide the JID of the contact you want to add:
-
-.. code-block:: javascript
-
-    converse.contacts.add('buddy@example.com')
-
-You may also provide the fullname. If not present, we use the jid as fullname:
-
-.. code-block:: javascript
-
-    converse.contacts.add('buddy@example.com', 'Buddy')
-
-The "chats" grouping
---------------------
-
-Note, for MUC chat rooms, you need to use the "rooms" grouping instead.
-
-get
-~~~
-
-Returns an object representing a chat box.
-
-To return a single chat box, provide the JID of the contact you're chatting
-with in that chat box:
-
-.. code-block:: javascript
-
-    converse.chats.get('buddy@example.com')
-
-To return an array of chat boxes, provide an array of JIDs:
-
-.. code-block:: javascript
-
-    converse.chats.get(['buddy1@example.com', 'buddy2@example.com'])
-
-To return all open chat boxes, call the method without any JIDs::
-
-    converse.chats.get()
-
-open
-~~~~
-
-Opens a chat box and returns an object representing a chat box.
-
-To open a single chat box, provide the JID of the contact:
-
-.. code-block:: javascript
-
-    converse.chats.open('buddy@example.com')
-
-To return an array of chat boxes, provide an array of JIDs:
-
-.. code-block:: javascript
-
-    converse.chats.open(['buddy1@example.com', 'buddy2@example.com'])
-
-
-*The returned chat box object 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).         |
-+-------------+------------------------------------------+
-| close       | Close the chat box.                      |
-+-------------+------------------------------------------+
-| open        | Opens the chat box.                      |
-+-------------+------------------------------------------+
-
-*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.                    |
-+-------------+-----------------------------------------------------+
-
-The "rooms" grouping
---------------------
-
-get
-~~~
-
-Returns an object representing a multi user chat box (room).
-It takes 3 parameters:
-
-* the room JID (if not specified, all rooms will be returned).
-* a map (object) containing any extra room attributes For example, if you want
-  to specify the nickname, use ``{'nick': 'bloodninja'}``. Previously (before
-  version 1.0.7, the second parameter only accepted the nickname (as a string
-  value). This is currently still accepted, but then you can't pass in any
-  other room attributes. If the nickname is not specified then the node part of
-  the user's JID will be used.
-* a boolean, indicating whether the room should be created if not found (default: `false`)
-
-.. code-block:: javascript
-
-    var nick = 'dread-pirate-roberts';
-    var create_if_not_found = true;
-    converse.rooms.open('group@muc.example.com', {'nick': nick}, create_if_not_found)
-
-open
-~~~~
-
-Opens a multi user chat box and returns an object representing it.
-Similar to chats.get API
-
-It takes 2 parameters:
-
-* the room JID (if not specified, all rooms will be returned).
-* a map (object) containing any extra room attributes. For example, if you want
-  to specify the nickname, use ``{'nick': 'bloodninja'}``.
-
-To open a single multi user chat box, provide the JID of the room:
-
-.. code-block:: javascript
-
-    converse.rooms.open('group@muc.example.com')
-
-To return an array of rooms, provide an array of room JIDs:
-
-.. code-block:: javascript
-
-    converse.rooms.open(['group1@muc.example.com', 'group2@muc.example.com'])
-
-To setup a custom nickname when joining the room, provide the optional nick argument:
-
-.. code-block:: javascript
-
-    converse.rooms.open('group@muc.example.com', {'nick': 'mycustomnick'})
-
-close
-~~~~~
-
-Lets you close open chat rooms. You can call this method without any arguments
-to close all open chat rooms, or you can specify a single JID or an array of
-JIDs.
-
-The "settings" grouping
------------------------
-
-This grouping allows you to get or set the configuration settings of converse.js.
-
-get(key)
-~~~~~~~~
-
-Returns the value of a configuration settings. For example:
-
-.. code-block:: javascript
-
-    converse.settings.get("play_sounds"); // default value returned would be false;
-
-set(key, value) or set(object)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Set one or many configuration settings. For example:
-
-.. code-block:: javascript
-
-    converse.settings.set("play_sounds", true);
-
-or :
-
-.. code-block:: javascript
-
-    converse.settings.set({
-        "play_sounds", true,
-        "hide_offline_users" true
-    });
-
-Note, this is not an alternative to calling ``converse.initialize``, which still needs
-to be called. Generally, you'd use this method after converse.js is already
-running and you want to change the configuration on-the-fly.
-
-The "tokens" grouping
----------------------
-
-get
-~~~
-
-Returns a token, either the RID or SID token depending on what's asked for.
-
-Example:
-
-.. code-block:: javascript
-
-    converse.tokens.get('rid')
-
-
-.. _`listen-grouping`:
-
-The "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, [context])**:
-
-    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.
-    * ``context`` (optional), the value of the `this` parameter for the callback.
-
-    For example:
-
-.. code-block:: javascript
-
-        converse.listen.on('message', function (event, messageXML) { ... });
-
-* **once(eventName, callback, [context])**:
-
-    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.
-    * ``context`` (optional), the value of the `this` parameter for the callback.
-
-    For example:
-
-.. code-block:: javascript
-
-        converse.listen.once('message', function (event, 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:
-
-.. code-block:: javascript
-
-        converse.listen.not('message', function (event, messageXML) { ... });
-
-Events
-======
-
-.. note:: see also :ref:`listen-grouping` above.
-
-Event Types
------------
-
-Here are the different events that are emitted:
-
-cachedRoster
-~~~~~~~~~~~~
-
-The contacts roster has been retrieved from the local cache (`sessionStorage`).
-
-``converse.listen.on('cachedRoster', function (event, items) { ... });``
-
-See also the `roster` event further down.
-
-callButtonClicked
-~~~~~~~~~~~~~~~~~
-
-When a call button (i.e. with class .toggle-call) on a chat box has been clicked.
-
-``converse.listen.on('callButtonClicked', function (event, connection, model) { ... });``
-
-chatBoxInitialized
-~~~~~~~~~~~~~~~~~~
-
-When a chat box has been initialized. Relevant to converse-chatview.js plugin.
-
-``converse.listen.on('chatBoxInitialized', function (event, chatbox) { ... });``
-
-chatBoxOpened
-~~~~~~~~~~~~~
-
-When a chat box has been opened. Relevant to converse-chatview.js plugin.
-
-``converse.listen.on('chatBoxOpened', function (event, chatbox) { ... });``
-
-chatRoomOpened
-~~~~~~~~~~~~~~
-
-When a chat room has been opened. Relevant to converse-chatview.js plugin.
-
-``converse.listen.on('chatRoomOpened', function (event, chatbox) { ... });``
-
-chatBoxClosed
-~~~~~~~~~~~~~
-
-When a chat box has been closed. Relevant to converse-chatview.js plugin.
-
-``converse.listen.on('chatBoxClosed', function (event, chatbox) { ... });``
-
-chatBoxFocused
-~~~~~~~~~~~~~~
-
-When the focus has been moved to a chat box. Relevant to converse-chatview.js plugin.
-
-``converse.listen.on('chatBoxFocused', function (event, chatbox) { ... });``
-
-chatBoxToggled
-~~~~~~~~~~~~~~
-
-When a chat box has been minimized or maximized. Relevant to converse-chatview.js plugin.
-
-``converse.listen.on('chatBoxToggled', function (event, chatbox) { ... });``
-
-connected
-~~~~~~~~~
-
-After connection has been established and converse.js has got all its ducks in a row.
-
-``converse.listen.on('connected', function (event) { ... });``
-
-contactRequest
-~~~~~~~~~~~~~~
-
-Someone has requested to subscribe to your presence (i.e. to be your contact).
-
-``converse.listen.on('contactRequest', function (event, user_data) { ... });``
-
-contactRemoved
-~~~~~~~~~~~~~~
-
-The user has removed a contact.
-
-``converse.listen.on('contactRemoved', function (event, data) { ... });``
-
-
-contactStatusChanged
-~~~~~~~~~~~~~~~~~~~~
-
-When a chat buddy's chat status has changed.
-
-``converse.listen.on('contactStatusChanged', function (event, buddy) { ... });``
-
-contactStatusMessageChanged
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When a chat buddy's custom status message has changed.
-
-``converse.listen.on('contactStatusMessageChanged', function (event, data) { ... });``
-
-disconnected
-~~~~~~~~~~~~
-
-After converse.js has disconnected from the XMPP server.
-
-``converse.listen.on('disconnected', function (event) { ... });``
-
-initialized
-~~~~~~~~~~~
-
-Once converse.js has been initialized.
-
-``converse.listen.on('initialized', function (event) { ... });``
-
-See also `pluginsInitialized`_.
-
-messageSend
-~~~~~~~~~~~
-
-When a message will be sent out.
-
-``converse.listen.on('messageSend', function (event, messageText) { ... });``
-
-noResumeableSession
-~~~~~~~~~~~~~~~~~~~
-
-When keepalive=true but there aren't any stored prebind tokens.
-
-``converse.listen.on('noResumeableSession', function (event) { ... });``
-
-pluginsInitialized
-~~~~~~~~~~~~~~~~~~
-
-Once all plugins have been initialized. This is a useful event if you want to
-register event handlers but would like your own handlers to be overridable by
-plugins. In that case, you need to first wait until all plugins have been
-initialized, so that their overrides are active. One example where this is used
-is in [converse-notifications.js](https://github.com/jcbrand/converse.js/blob/master/src/converse-notification.js).
-
-``converse.listen.on('pluginsInitialized', function (event) { ... });``
-
-reconnected
-~~~~~~~~~~~
-
-After the connection has dropped and converse.js has reconnected.
-Any Strophe stanza handlers (as registered via `converse.listen.stanza`) will
-have to be registered anew.
-
-``converse.listen.on('reconnected', function (event) { ... });``
-
-roomInviteSent
-~~~~~~~~~~~~~~
-
-After the user has sent out a direct invitation, to a roster contact, asking them to join a room.
-
-``converse.listen.on('roomInvite', function (event, data) { ... });``
-
-roomInviteReceived
-~~~~~~~~~~~~~~~~~~
-
-After the user has sent out a direct invitation, to a roster contact, asking them to join a room.
-
-``converse.listen.on('roomInvite', function (event, data) { ... });``
-
-roster
-~~~~~~
-
-When the roster has been received from the XMPP server.
-
-``converse.listen.on('roster', function (event, items) { ... });``
-
-See also the `cachedRoster` event further up, which gets called instead of
-`roster` if its already in `sessionStorage`.
-
-rosterContactsFetched
-~~~~~~~~~~~~~~~~~~~~~
-
-Triggered once roster contacts have been fetched. Used by the
-`converse-rosterview.js` plugin to know when it can start to show the roster.
-
-rosterGroupsFetched
-~~~~~~~~~~~~~~~~~~~
-
-Triggered once roster groups have been fetched. Used by the
-`converse-rosterview.js` plugin to know when it can start alphabetically
-position roster groups.
-
-rosterPush
-~~~~~~~~~~
-
-When the roster receives a push event from server. (i.e. New entry in your buddy list)
-
-``converse.listen.on('rosterPush', function (event, items) { ... });``
-
-statusInitialized
-~~~~~~~~~~~~~~~~~
-
-When own chat status has been initialized.
-
-``converse.listen.on('statusInitialized', function (event, status) { ... });``
-
-statusChanged
-~~~~~~~~~~~~~
-
-When own chat status has changed.
-
-``converse.listen.on('statusChanged', function (event, status) { ... });``
-
-statusMessageChanged
-~~~~~~~~~~~~~~~~~~~~
-
-When own custom status message has changed.
-
-``converse.listen.on('statusMessageChanged', function (event, message) { ... });``
-
-serviceDiscovered
-~~~~~~~~~~~~~~~~~
-
-When converse.js has learned of a service provided by the XMPP server. See XEP-0030.
-
-``converse.listen.on('serviceDiscovered', function (event, service) { ... });``
-
-Integration into other frameworks
-=================================
-
-Angular.js
-----------
-
-Angular.js has the concept of a `service <https://docs.angularjs.org/guide/services#!>`_,
-which is a special kind of `provider <https://docs.angularjs.org/guide/providers>`_.
-
-An angular.js service is a constructor or object which provides an API defined by the
-writer of the service. The goal of a service is to organize and share code, so
-that it can be used across an application.
-
-So, if we wanted to properly integrate converse.js into an angular.js
-application, then putting it into a service is a good approach.
-
-This lets us avoid having a global ``converse`` API object (accessible via
-``windows.converse``), and instead we can get hold of the converse API via
-angular.js dependency injection, when we specify it as a dependency for our
-angular components.
-
-Below is an example code that wraps converse.js as an angular.js service.
-
-.. code-block:: javascript
-
-    angular.module('converse', []).service('converse', function() {
-        var deferred = new $.Deferred(),
-            promise = deferred.promise();
-
-        var service = {
-            'load': _.constant(promise),
-            'initialize': function initConverse(options) {
-                this.load().done(_.partial(this.api.initialize, options));
-            }
-        };
-
-        define("converse", [
-            "converse-api",
-            // START: Removable components
-            // --------------------
-            // Any of the following components may be removed if they're not needed.
-            "locales",               // Translations for converse.js. This line can be removed
-                                     // to remove *all* translations, or you can modify the
-                                     // file src/locales.js to include only those
-                                     // translations that you care about.
-
-            "converse-chatview",     // Renders standalone chat boxes for single user chat
-            "converse-controlbox",   // The control box
-            "converse-bookmarks",    // XEP-0048 Bookmarks
-            "converse-mam",          // XEP-0313 Message Archive Management
-            "converse-muc",          // XEP-0045 Multi-user chat
-            "converse-vcard",        // XEP-0054 VCard-temp
-            "converse-otr",          // Off-the-record encryption for one-on-one messages
-            "converse-register",     // XEP-0077 In-band registration
-            "converse-ping",         // XEP-0199 XMPP Ping
-            "converse-notification", // HTML5 Notifications
-            "converse-minimize",     // Allows chat boxes to be minimized
-            "converse-dragresize",   // Allows chat boxes to be resized by dragging them
-            "converse-headline",     // Support for headline messages
-            // END: Removable components
-
-        ], function(converse_api) {
-            service.api = converse_api;
-            return deferred.resolve();
-        });
-        require(["converse"]);
-        return service;
-    });
-
-The above code is a modified version of the file `src/converse.js <https://github.com/jcbrand/converse.js/blob/master/src/converse.js>`_
-which defines the converse AMD module and specifies which plugins will go into
-this build.
-
-You should replace the contents of that file with the above, if you want such a
-service registered. Then, you should run `make build`, to create new build
-files in the `dist` directory, containing your new angular.js service.
-
-The above code registers an angular.js module and service, both named ``converse``.
-
-This module should then be added as a dependency for your own angular.js
-modules, for example::
-
-    angular.module('my-module', ['converse']);
-
-Then you can have the converse service dependency injected into
-your components, for example::
-
-    angular.module('my-module').provider('my-provider', function(converse) {
-        // Your custom code can come here..
-
-        // Then when you're ready, you can initialize converse.js
-        converse.load().done(function () {
-            converse.initialize({
-                'allow_logout': false,
-                'auto_login': 'true',
-                'auto_reconnect': true,
-                'bosh_service_url': bosh_url,
-                'jid': bare_jid,
-                'keepalive': true,
-                'credentials_url': credentials_url,
-            });
-
-        // More custom code could come here...
-        });
-    });
-
-You might have noticed the ``load()`` method being called on the ``converse``
-service. This is a special method added to the service (see the implementation
-example above) that makes sure that converse.js is loaded and available. It
-returns a jQuery promise which resolves once converse.js is available.
-
-This is necessary because with otherwise you might run into race-conditions
-when your angular application loads more quickly then converse.js.
-
-The API of converse is available via the ``.api`` attribute on the service.
-So you can call it like this for example::
-
-    converse.api.user.status.set('online');
-
-
-Writing a converse.js plugin
-============================
-
-Developers are able to extend and override the objects, functions and the
-Backbone models and views that make up converse.js by means of writing plugins.
-
-Converse.js uses `pluggable.js <https://github.com/jcbrand/pluggable.js/>`_ as
-its plugin architecture.
-
-To understand how this plugin architecture works, please read the
-`pluggable.js documentation <https://jcbrand.github.io/pluggable.js/>`_
-and to grok its inner workins, please refer to the `annotated source code
-<https://jcbrand.github.io/pluggable.js/docs/pluggable.html>`_.
-
-You register a converse.js plugin as follows:
-
-.. code-block:: javascript
-
-    converse.plugins.add('myplugin', {
-        // Your plugin code goes in here
-    });
-
-Security and access to the inner workings
------------------------------------------
-
-The globally available ``converse`` object, which exposes the API methods, such
-as ``initialize`` and ``plugins.add``, is a wrapper that encloses and protects
-a sensitive inner object.
-
-This inner object contains all the Backbone models and views, as well as
-various other attributes and functions.
-
-Within a plugin, you will have access to this internal
-`"closured" <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures>`_
-converse object, which is normally not exposed in the global variable scope. The
-hiding of this inner object is due to the fact that it contains sensitive information,
-such as the user's JID and password (if they logged in manually). You should
-therefore make sure NOT to expose this object globally.
-
-An example plugin
------------------
-
-.. code-block:: javascript
-
-    (function (root, factory) {
-        if (typeof define === 'function' && define.amd) {
-            // AMD. Register as a module called "myplugin"
-            define("myplugin", ["converse"], factory);
-        } else {
-            // Browser globals. If you're not using a module loader such as require.js,
-            // then this line below executes. Make sure that your plugin's <script> tag
-            // appears after the one from converse.js.
-            factory(converse);
-        }
-    }(this, function (converse_api) {
-
-        // Commonly used utilities and variables can be found under the "env"
-        // namespace of converse_api
-
-        // Strophe methods for building stanzas
-        var Strophe = converse_api.env.Strophe,
-            $iq = converse_api.env.$iq,
-            $msg = converse_api.env.$msg,
-            $pres = converse_api.env.$pres,
-            $build = converse_api.env.$build,
-            b64_sha1 = converse_api.env.b64_sha1;
-
-        // Other frequently used utilities
-        var $ = converse_api.env.jQuery,
-            _ = converse_api.env._,
-            moment = converse_api.env.moment;
-
-
-        // The following line registers your plugin.
-        converse_api.plugins.add('myplugin', {
-
-            initialize: function () {
-                // Converse.js's plugin mechanism will call the initialize
-                // method on any plugin (if it exists) as soon as the plugin has
-                // been loaded.
-
-                // Inside this method, you have access to the protected "inner"
-                // converse object, from which you can get any configuration
-                // options that the user might have passed in via
-                // converse.initialize. These values are stored in the
-                // "user_settings" attribute.
-
-                // Let's assume the user might in a custom setting, like so:
-                // converse.initialize({
-                //      "initialize_message": "My plugin has been initialized"
-                // });
-                //
-                // Then we can alert that message, like so:
-                alert(this.converse.user_settings.initialize_message);
-            },
-
-            myFunction: function () {
-                // This is a function which does not override anything in
-                // converse.js itself, but in which you still have access to
-                // the protected "inner" converse object.
-                var converse = this.converse;
-                // Custom code comes here
-                // ...
-            },
-
-            overrides: {
-                // If you want to override some function or a Backbone model or
-                // view defined inside converse, then you do that under this
-                // "overrides" namespace.
-
-                // For example, the inner protected *converse* object has a
-                // method "onConnected". You can override that method as follows:
-                onConnected: function () {
-                    // Overrides the onConnected method in converse.js
-
-                    // Top-level functions in "overrides" are bound to the
-                    // inner "converse" object.
-                    var converse = this;
-
-                    // Your custom code comes here.
-                    // ...
-
-                    // You can access the original function being overridden
-                    // via the __super__ attribute.
-                    // Make sure to pass on the arguments supplied to this
-                    // function and also to apply the proper "this" object.
-                    this.__super__.onConnected.apply(this, arguments);
-                },
-
-                XMPPStatus: {
-                    // Override converse.js's XMPPStatus Backbone model so that we can override the
-                    // function that sends out the presence stanza.
-                    sendPresence: function (type, status_message, jid) {
-                        // The "converse" object is available via the __super__
-                        // attribute.
-                        var converse = this.__super__.converse;
-
-                        // Custom code can come here
-                        // ...
-
-                        // You can call the original overridden method, by
-                        // accessing it via the __super__ attribute.
-                        // When calling it, you need to apply the proper
-                        // context as reference by the "this" variable.
-                        this.__super__.sendPresence.apply(this, arguments);
-                    }
-                },
-            }
-        });
-    }));
+Welcome to the developer documentation of converse.js. Read the documentation
+linked to below, if you want to add new features or create your own customized
+version of converse.js.
+
+Converse.js itself composed of plugins, and exposes an API with which you can
+create and register your own plugins. This is the recommended way to customize
+or add new functionality to converse.js.
+
+Table of Contents
+=================
+
+.. toctree::
+   :maxdepth: 2
+
+   developer_guidelines
+   style_guide
+   plugin_development
+   developer_api
+   events 
+   other_frameworks
+   builds

+ 6 - 6
docs/source/documentation.rst

@@ -12,8 +12,8 @@ Writing Documentation
 
 
 .. note:: Contributions to the documentation are much appreciated.
 .. note:: Contributions to the documentation are much appreciated.
 
 
-What is used to write the documentation
-=======================================
+What is used to write the documentation?
+========================================
 
 
 This documentation is written in `Sphinx <http://sphinx-doc.org/>`_, a
 This documentation is written in `Sphinx <http://sphinx-doc.org/>`_, a
 documentation generator written in `Python <http://python.org>`_.
 documentation generator written in `Python <http://python.org>`_.
@@ -24,15 +24,15 @@ a very easy to write plain text format, relatively similar to Markdown.
 So see what the source looks like, click the **Source** link in the footer of
 So see what the source looks like, click the **Source** link in the footer of
 this page.
 this page.
 
 
-Where is the documentation
-==========================
+Where is the documentation?
+===========================
 
 
 The reST documentation files are located in the
 The reST documentation files are located in the
 `converse.js code repository <https://github.com/jcbrand/converse.js/tree/master/docs/source>`_
 `converse.js code repository <https://github.com/jcbrand/converse.js/tree/master/docs/source>`_
 under ``docs/source``.
 under ``docs/source``.
 
 
-How to generate HTML from the source files
-==========================================
+How to generate HTML from the source files?
+===========================================
 
 
 Install Dependencies
 Install Dependencies
 --------------------
 --------------------

+ 225 - 0
docs/source/events.rst

@@ -0,0 +1,225 @@
+Events emitted by converse.js
+=============================
+
+.. note:: see also :ref:`listen-grouping` above.
+
+Event Types
+-----------
+
+Here are the different events that are emitted:
+
+cachedRoster
+~~~~~~~~~~~~
+
+The contacts roster has been retrieved from the local cache (`sessionStorage`).
+
+``converse.listen.on('cachedRoster', function (event, items) { ... });``
+
+See also the `roster` event further down.
+
+callButtonClicked
+~~~~~~~~~~~~~~~~~
+
+When a call button (i.e. with class .toggle-call) on a chat box has been clicked.
+
+``converse.listen.on('callButtonClicked', function (event, connection, model) { ... });``
+
+chatBoxInitialized
+~~~~~~~~~~~~~~~~~~
+
+When a chat box has been initialized. Relevant to converse-chatview.js plugin.
+
+``converse.listen.on('chatBoxInitialized', function (event, chatbox) { ... });``
+
+chatBoxOpened
+~~~~~~~~~~~~~
+
+When a chat box has been opened. Relevant to converse-chatview.js plugin.
+
+``converse.listen.on('chatBoxOpened', function (event, chatbox) { ... });``
+
+chatRoomOpened
+~~~~~~~~~~~~~~
+
+When a chat room has been opened. Relevant to converse-chatview.js plugin.
+
+``converse.listen.on('chatRoomOpened', function (event, chatbox) { ... });``
+
+chatBoxClosed
+~~~~~~~~~~~~~
+
+When a chat box has been closed. Relevant to converse-chatview.js plugin.
+
+``converse.listen.on('chatBoxClosed', function (event, chatbox) { ... });``
+
+chatBoxFocused
+~~~~~~~~~~~~~~
+
+When the focus has been moved to a chat box. Relevant to converse-chatview.js plugin.
+
+``converse.listen.on('chatBoxFocused', function (event, chatbox) { ... });``
+
+chatBoxToggled
+~~~~~~~~~~~~~~
+
+When a chat box has been minimized or maximized. Relevant to converse-chatview.js plugin.
+
+``converse.listen.on('chatBoxToggled', function (event, chatbox) { ... });``
+
+connected
+~~~~~~~~~
+
+After connection has been established and converse.js has got all its ducks in a row.
+
+``converse.listen.on('connected', function (event) { ... });``
+
+contactRequest
+~~~~~~~~~~~~~~
+
+Someone has requested to subscribe to your presence (i.e. to be your contact).
+
+``converse.listen.on('contactRequest', function (event, user_data) { ... });``
+
+contactRemoved
+~~~~~~~~~~~~~~
+
+The user has removed a contact.
+
+``converse.listen.on('contactRemoved', function (event, data) { ... });``
+
+
+contactStatusChanged
+~~~~~~~~~~~~~~~~~~~~
+
+When a chat buddy's chat status has changed.
+
+``converse.listen.on('contactStatusChanged', function (event, buddy) { ... });``
+
+contactStatusMessageChanged
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When a chat buddy's custom status message has changed.
+
+``converse.listen.on('contactStatusMessageChanged', function (event, data) { ... });``
+
+disconnected
+~~~~~~~~~~~~
+
+After converse.js has disconnected from the XMPP server.
+
+``converse.listen.on('disconnected', function (event) { ... });``
+
+initialized
+~~~~~~~~~~~
+
+Once converse.js has been initialized.
+
+``converse.listen.on('initialized', function (event) { ... });``
+
+See also `pluginsInitialized`_.
+
+messageSend
+~~~~~~~~~~~
+
+When a message will be sent out.
+
+``converse.listen.on('messageSend', function (event, messageText) { ... });``
+
+noResumeableSession
+~~~~~~~~~~~~~~~~~~~
+
+When keepalive=true but there aren't any stored prebind tokens.
+
+``converse.listen.on('noResumeableSession', function (event) { ... });``
+
+pluginsInitialized
+~~~~~~~~~~~~~~~~~~
+
+Once all plugins have been initialized. This is a useful event if you want to
+register event handlers but would like your own handlers to be overridable by
+plugins. In that case, you need to first wait until all plugins have been
+initialized, so that their overrides are active. One example where this is used
+is in `converse-notifications.js <https://github.com/jcbrand/converse.js/blob/master/src/converse-notification.js>`.
+
+``converse.listen.on('pluginsInitialized', function (event) { ... });``
+
+reconnected
+~~~~~~~~~~~
+
+After the connection has dropped and converse.js has reconnected.
+Any Strophe stanza handlers (as registered via `converse.listen.stanza`) will
+have to be registered anew.
+
+``converse.listen.on('reconnected', function (event) { ... });``
+
+roomInviteSent
+~~~~~~~~~~~~~~
+
+After the user has sent out a direct invitation, to a roster contact, asking them to join a room.
+
+``converse.listen.on('roomInvite', function (event, data) { ... });``
+
+roomInviteReceived
+~~~~~~~~~~~~~~~~~~
+
+After the user has sent out a direct invitation, to a roster contact, asking them to join a room.
+
+``converse.listen.on('roomInvite', function (event, data) { ... });``
+
+roster
+~~~~~~
+
+When the roster has been received from the XMPP server.
+
+``converse.listen.on('roster', function (event, items) { ... });``
+
+See also the `cachedRoster` event further up, which gets called instead of
+`roster` if its already in `sessionStorage`.
+
+rosterContactsFetched
+~~~~~~~~~~~~~~~~~~~~~
+
+Triggered once roster contacts have been fetched. Used by the
+`converse-rosterview.js` plugin to know when it can start to show the roster.
+
+rosterGroupsFetched
+~~~~~~~~~~~~~~~~~~~
+
+Triggered once roster groups have been fetched. Used by the
+`converse-rosterview.js` plugin to know when it can start alphabetically
+position roster groups.
+
+rosterPush
+~~~~~~~~~~
+
+When the roster receives a push event from server. (i.e. New entry in your buddy list)
+
+``converse.listen.on('rosterPush', function (event, items) { ... });``
+
+statusInitialized
+~~~~~~~~~~~~~~~~~
+
+When own chat status has been initialized.
+
+``converse.listen.on('statusInitialized', function (event, status) { ... });``
+
+statusChanged
+~~~~~~~~~~~~~
+
+When own chat status has changed.
+
+``converse.listen.on('statusChanged', function (event, status) { ... });``
+
+statusMessageChanged
+~~~~~~~~~~~~~~~~~~~~
+
+When own custom status message has changed.
+
+``converse.listen.on('statusMessageChanged', function (event, message) { ... });``
+
+serviceDiscovered
+~~~~~~~~~~~~~~~~~
+
+When converse.js has learned of a service provided by the XMPP server. See XEP-0030.
+
+``converse.listen.on('serviceDiscovered', function (event, service) { ... });``

+ 0 - 3
docs/source/index.rst

@@ -48,10 +48,7 @@ Table of Contents
    setup
    setup
    configuration
    configuration
    development
    development
-   style_guide 
    theming
    theming
    translations
    translations
    troubleshooting
    troubleshooting
    documentation
    documentation
-   builds
-

+ 124 - 0
docs/source/other_frameworks.rst

@@ -0,0 +1,124 @@
+Integrating converse.js into other frameworks
+=============================================
+
+Angular.js
+----------
+
+Angular.js has the concept of a `service <https://docs.angularjs.org/guide/services#!>`_,
+which is a special kind of `provider <https://docs.angularjs.org/guide/providers>`_.
+
+An angular.js service is a constructor or object which provides an API defined by the
+writer of the service. The goal of a service is to organize and share code, so
+that it can be used across an application.
+
+So, if we wanted to properly integrate converse.js into an angular.js
+application, then putting it into a service is a good approach.
+
+This lets us avoid having a global ``converse`` API object (accessible via
+``windows.converse``), and instead we can get hold of the converse API via
+angular.js dependency injection, when we specify it as a dependency for our
+angular components.
+
+Below is an example code that wraps converse.js as an angular.js service.
+
+.. code-block:: javascript
+
+    angular.module('converse', []).service('converse', function() {
+        var deferred = new $.Deferred(),
+            promise = deferred.promise();
+
+        var service = {
+            'load': _.constant(promise),
+            'initialize': function initConverse(options) {
+                this.load().done(_.partial(this.api.initialize, options));
+            }
+        };
+
+        define("converse", [
+            "converse-api",
+            // START: Removable components
+            // --------------------
+            // Any of the following components may be removed if they're not needed.
+            "locales",               // Translations for converse.js. This line can be removed
+                                     // to remove *all* translations, or you can modify the
+                                     // file src/locales.js to include only those
+                                     // translations that you care about.
+
+            "converse-chatview",     // Renders standalone chat boxes for single user chat
+            "converse-controlbox",   // The control box
+            "converse-bookmarks",    // XEP-0048 Bookmarks
+            "converse-mam",          // XEP-0313 Message Archive Management
+            "converse-muc",          // XEP-0045 Multi-user chat
+            "converse-vcard",        // XEP-0054 VCard-temp
+            "converse-otr",          // Off-the-record encryption for one-on-one messages
+            "converse-register",     // XEP-0077 In-band registration
+            "converse-ping",         // XEP-0199 XMPP Ping
+            "converse-notification", // HTML5 Notifications
+            "converse-minimize",     // Allows chat boxes to be minimized
+            "converse-dragresize",   // Allows chat boxes to be resized by dragging them
+            "converse-headline",     // Support for headline messages
+            // END: Removable components
+
+        ], function(converse_api) {
+            service.api = converse_api;
+            return deferred.resolve();
+        });
+        require(["converse"]);
+        return service;
+    });
+
+The above code is a modified version of the file `src/converse.js <https://github.com/jcbrand/converse.js/blob/master/src/converse.js>`_
+which defines the converse AMD module and specifies which plugins will go into
+this build.
+
+You should replace the contents of that file with the above, if you want such a
+service registered. Then, you should run `make build`, to create new build
+files in the `dist` directory, containing your new angular.js service.
+
+The above code registers an angular.js module and service, both named ``converse``.
+
+This module should then be added as a dependency for your own angular.js
+modules, for example:
+
+.. code-block:: javascript
+
+    angular.module('my-module', ['converse']);
+
+Then you can have the converse service dependency injected into
+your components, for example:
+
+.. code-block:: javascript
+
+    angular.module('my-module').provider('my-provider', function(converse) {
+        // Your custom code can come here..
+
+        // Then when you're ready, you can initialize converse.js
+        converse.load().done(function () {
+            converse.initialize({
+                'allow_logout': false,
+                'auto_login': 'true',
+                'auto_reconnect': true,
+                'bosh_service_url': bosh_url,
+                'jid': bare_jid,
+                'keepalive': true,
+                'credentials_url': credentials_url,
+            });
+
+        // More custom code could come here...
+        });
+    });
+
+You might have noticed the ``load()`` method being called on the ``converse``
+service. This is a special method added to the service (see the implementation
+example above) that makes sure that converse.js is loaded and available. It
+returns a jQuery promise which resolves once converse.js is available.
+
+This is necessary because with otherwise you might run into race-conditions
+when your angular application loads more quickly then converse.js.
+
+Lastly, the API of converse is available via the ``.api`` attribute on the service.
+So you can call it like this for example:
+
+.. code-block:: javascript
+
+    converse.api.user.status.set('online');

+ 150 - 0
docs/source/plugin_development.rst

@@ -0,0 +1,150 @@
+Writing a converse.js plugin
+============================
+
+Developers are able to extend and override the objects, functions and the
+Backbone models and views that make up converse.js by means of writing plugins.
+
+Converse.js uses `pluggable.js <https://github.com/jcbrand/pluggable.js/>`_ as
+its plugin architecture.
+
+To understand how this plugin architecture works, please read the
+`pluggable.js documentation <https://jcbrand.github.io/pluggable.js/>`_
+and to grok its inner workins, please refer to the `annotated source code
+<https://jcbrand.github.io/pluggable.js/docs/pluggable.html>`_.
+
+You register a converse.js plugin as follows:
+
+.. code-block:: javascript
+
+    converse.plugins.add('myplugin', {
+        // Your plugin code goes in here
+    });
+
+Security and access to the inner workings
+-----------------------------------------
+
+The globally available ``converse`` object, which exposes the API methods, such
+as ``initialize`` and ``plugins.add``, is a wrapper that encloses and protects
+a sensitive inner object.
+
+This inner object contains all the Backbone models and views, as well as
+various other attributes and functions.
+
+Within a plugin, you will have access to this internal
+`"closured" <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures>`_
+converse object, which is normally not exposed in the global variable scope. The
+hiding of this inner object is due to the fact that it contains sensitive information,
+such as the user's JID and password (if they logged in manually). You should
+therefore make sure NOT to expose this object globally.
+
+An example plugin
+-----------------
+
+.. code-block:: javascript
+
+    (function (root, factory) {
+        if (typeof define === 'function' && define.amd) {
+            // AMD. Register as a module called "myplugin"
+            define("myplugin", ["converse"], factory);
+        } else {
+            // Browser globals. If you're not using a module loader such as require.js,
+            // then this line below executes. Make sure that your plugin's <script> tag
+            // appears after the one from converse.js.
+            factory(converse);
+        }
+    }(this, function (converse_api) {
+
+        // Commonly used utilities and variables can be found under the "env"
+        // namespace of converse_api
+
+        // Strophe methods for building stanzas
+        var Strophe = converse_api.env.Strophe,
+            $iq = converse_api.env.$iq,
+            $msg = converse_api.env.$msg,
+            $pres = converse_api.env.$pres,
+            $build = converse_api.env.$build,
+            b64_sha1 = converse_api.env.b64_sha1;
+
+        // Other frequently used utilities
+        var $ = converse_api.env.jQuery,
+            _ = converse_api.env._,
+            moment = converse_api.env.moment;
+
+
+        // The following line registers your plugin.
+        converse_api.plugins.add('myplugin', {
+
+            initialize: function () {
+                // Converse.js's plugin mechanism will call the initialize
+                // method on any plugin (if it exists) as soon as the plugin has
+                // been loaded.
+
+                // Inside this method, you have access to the protected "inner"
+                // converse object, from which you can get any configuration
+                // options that the user might have passed in via
+                // converse.initialize. These values are stored in the
+                // "user_settings" attribute.
+
+                // Let's assume the user might in a custom setting, like so:
+                // converse.initialize({
+                //      "initialize_message": "My plugin has been initialized"
+                // });
+                //
+                // Then we can alert that message, like so:
+                alert(this.converse.user_settings.initialize_message);
+            },
+
+            myFunction: function () {
+                // This is a function which does not override anything in
+                // converse.js itself, but in which you still have access to
+                // the protected "inner" converse object.
+                var converse = this.converse;
+                // Custom code comes here
+                // ...
+            },
+
+            overrides: {
+                // If you want to override some function or a Backbone model or
+                // view defined inside converse, then you do that under this
+                // "overrides" namespace.
+
+                // For example, the inner protected *converse* object has a
+                // method "onConnected". You can override that method as follows:
+                onConnected: function () {
+                    // Overrides the onConnected method in converse.js
+
+                    // Top-level functions in "overrides" are bound to the
+                    // inner "converse" object.
+                    var converse = this;
+
+                    // Your custom code comes here.
+                    // ...
+
+                    // You can access the original function being overridden
+                    // via the __super__ attribute.
+                    // Make sure to pass on the arguments supplied to this
+                    // function and also to apply the proper "this" object.
+                    this.__super__.onConnected.apply(this, arguments);
+                },
+
+                XMPPStatus: {
+                    // Override converse.js's XMPPStatus Backbone model so that we can override the
+                    // function that sends out the presence stanza.
+                    sendPresence: function (type, status_message, jid) {
+                        // The "converse" object is available via the __super__
+                        // attribute.
+                        var converse = this.__super__.converse;
+
+                        // Custom code can come here
+                        // ...
+
+                        // You can call the original overridden method, by
+                        // accessing it via the __super__ attribute.
+                        // When calling it, you need to apply the proper
+                        // context as reference by the "this" variable.
+                        this.__super__.sendPresence.apply(this, arguments);
+                    }
+                },
+            }
+        });
+    }));