Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
310c193672
@ -35,7 +35,7 @@ and to understand its inner workins, please refer to the `annotated source code
|
||||
Because Converse.js consists only of JavaScript, HTML and CSS (with no backend
|
||||
code required like PHP, Python or Ruby) it runs fine in JSFiddle.
|
||||
|
||||
Here's a Fiddle with a Converse.js plugin that calls `alert` once it gets
|
||||
Here's a Fiddle with a Converse.js plugin that calls ``alert`` once it gets
|
||||
initialized and also when a chat message gets rendered: https://jsfiddle.net/4drfaok0/15/
|
||||
|
||||
|
||||
@ -254,162 +254,226 @@ Generally, your plugin will then also be responsible for making sure these
|
||||
promises are resolved. You do this by calling ``_converse.api.emit``, which not
|
||||
only resolves the plugin but will also emit an event with the same name.
|
||||
|
||||
A full example plugin
|
||||
---------------------
|
||||
Dealing with asynchronicity
|
||||
---------------------------
|
||||
|
||||
Due to the asynchronous nature of XMPP, many subroutines in Converse.js execute
|
||||
at different times and not necessarily in the same order.
|
||||
|
||||
In many cases, when you want to execute a piece of code in a plugin, you first
|
||||
want to make sure that the supporting data-structures that your code might rely
|
||||
on have been created and populated with data.
|
||||
|
||||
There are two ways of waiting for the right time before executing your code.
|
||||
You can either listen for certain events, or you can wait for promises to
|
||||
resolve.
|
||||
|
||||
For example, in the ``Bookmarks`` plugin (in
|
||||
`src/converse-bookmarks.js <https://github.com/jcbrand/converse.js/blob/6c3aa34c23d97d679823a64376418cd0f40a8b94/src/converse-bookmarks.js#L528>`_),
|
||||
before bookmarks can be fetched and shown to the user, we first have to wait until
|
||||
the `"Rooms"` panel of the ``ControlBox`` has been rendered and inserted into
|
||||
the DOM. Otherwise we have no place to show the bookmarks yet.
|
||||
|
||||
Therefore, there are the following lines of code in the ``initialize`` method of
|
||||
`converse-bookmarks.js <https://github.com/jcbrand/converse.js/blob/6c3aa34c23d97d679823a64376418cd0f40a8b94/src/converse-bookmarks.js#L528>`_:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as a module called "myplugin"
|
||||
define("<%= name %>", ["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) {
|
||||
Promise.all([
|
||||
_converse.api.waitUntil('chatBoxesFetched'),
|
||||
_converse.api.waitUntil('roomsPanelRendered')
|
||||
]).then(initBookmarks);
|
||||
|
||||
// Commonly used utilities and variables can be found under the "env"
|
||||
// namespace of the "converse" global.
|
||||
var Strophe = converse.env.Strophe,
|
||||
$iq = converse.env.$iq,
|
||||
$msg = converse.env.$msg,
|
||||
$pres = converse.env.$pres,
|
||||
$build = converse.env.$build,
|
||||
b64_sha1 = converse.env.b64_sha1;
|
||||
$ = converse.env.jQuery,
|
||||
_ = converse.env._,
|
||||
moment = converse.env.moment;
|
||||
What this means, is that the plugin will wait until the ``chatBoxesFetched``
|
||||
and ``roomsPanelRendered`` promises have been resolved before it calls the
|
||||
``initBookmarks`` method (which is defined inside the plugin).
|
||||
|
||||
// The following line registers your plugin.
|
||||
converse.plugins.add("<%= name %>", {
|
||||
This way, we know that we have everything in place and set up correctly before
|
||||
fetching the bookmarks.
|
||||
|
||||
/* Optional dependencies are other plugins which might be
|
||||
* overridden or relied upon, and therefore need to be loaded before
|
||||
* this plugin. They are called "optional" because they might not be
|
||||
* available, in which case any overrides applicable to them will be
|
||||
* ignored.
|
||||
*
|
||||
* NB: These plugins need to have already been loaded via require.js.
|
||||
*
|
||||
* It's possible to make optional dependencies non-optional.
|
||||
* If the setting "strict_plugin_dependencies" is set to true,
|
||||
* an error will be raised if the plugin is not found.
|
||||
*/
|
||||
'optional_dependencies': [],
|
||||
As another example, there is also the following code in the ``initialize``
|
||||
method of the plugin:
|
||||
|
||||
/* Converse.js's plugin mechanism will call the initialize
|
||||
* method on any plugin (if it exists) as soon as the plugin has
|
||||
* been loaded.
|
||||
*/
|
||||
'initialize': function () {
|
||||
/* Inside this method, you have access to the private
|
||||
* `_converse` object.
|
||||
*/
|
||||
var _converse = this._converse;
|
||||
_converse.log("The <%= name %> plugin is being initialized");
|
||||
.. code-block:: javascript
|
||||
|
||||
/* From the `_converse` object 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.
|
||||
*
|
||||
* You can also specify new configuration settings for this
|
||||
* plugin, or override the default values of existing
|
||||
* configuration settings. This is done like so:
|
||||
*/
|
||||
_converse.api.settings.update({
|
||||
'initialize_message': 'Initializing <%= name %>!'
|
||||
});
|
||||
_converse.on('chatBoxOpened', function renderMinimizeButton (view) {
|
||||
// Inserts a "minimize" button in the chatview's header
|
||||
|
||||
/* The user can then pass in values for the configuration
|
||||
* settings when `converse.initialize` gets called.
|
||||
* For example:
|
||||
*
|
||||
* converse.initialize({
|
||||
* "initialize_message": "My plugin has been initialized"
|
||||
* });
|
||||
*
|
||||
* And the configuration setting is then available via the
|
||||
* `user_settings` attribute:
|
||||
*/
|
||||
alert(this._converse.user_settings.initialize_message);
|
||||
// Implementation code removed for brevity
|
||||
// ...
|
||||
});
|
||||
|
||||
/* Besides `_converse.api.settings.update`, there is also a
|
||||
* `_converse.api.promises.add` method, which allows you to
|
||||
* add new promises that your plugin is obligated to fulfill.
|
||||
*
|
||||
* This method takes a string or a list of strings which
|
||||
* represent the promise names:
|
||||
*
|
||||
* _converse.api.promises.add('myPromise');
|
||||
*
|
||||
* Your plugin should then, when appropriate, resolve the
|
||||
* promise by calling `_converse.api.emit`, which will also
|
||||
* emit an event with the same name as the promise.
|
||||
* For example:
|
||||
*
|
||||
* _converse.api.emit('operationCompleted');
|
||||
*
|
||||
* Other plugins can then either listen for the event
|
||||
* `operationCompleted` like so:
|
||||
*
|
||||
* _converse.api.listen.on('operationCompleted', function { ... });
|
||||
*
|
||||
* or they can wait for the promise to be fulfilled like so:
|
||||
*
|
||||
* _converse.api.waitUntil('operationCompleted', function { ... });
|
||||
*/
|
||||
},
|
||||
In this case, the plugin waits for the ``chatBoxOpened`` event, before it then
|
||||
calls ``renderMinimizeButton``, which adds a new button to the chat box (which
|
||||
enables you to minimize it).
|
||||
|
||||
/* If you want to override some function or a Backbone model or
|
||||
* view defined elsewhere in converse.js, then you do that under
|
||||
* the "overrides" namespace.
|
||||
*/
|
||||
'overrides': {
|
||||
/* For example, the private *_converse* object has a
|
||||
* method "onConnected". You can override that method as follows:
|
||||
*/
|
||||
'onConnected': function () {
|
||||
// Overrides the onConnected method in converse.js
|
||||
Finding the right promises and/or events to listen to, can be a bit
|
||||
challenging, and sometimes it might be necessary to create new events or
|
||||
promises.
|
||||
|
||||
// Top-level functions in "overrides" are bound to the
|
||||
// inner "_converse" object.
|
||||
var _converse = this;
|
||||
Please refer to the :ref:`events-API` section of the documentation for an
|
||||
overview of what's available to you. If you need new events or promises, then
|
||||
`please open an issue or make a pull request on Github <https://github.com/jcbrand/converse.js>`_
|
||||
|
||||
// Your custom code can come here ...
|
||||
A full example plugin
|
||||
---------------------
|
||||
|
||||
// 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.
|
||||
_converse.__super__.onConnected.apply(this, arguments);
|
||||
Below follows a documented example of a plugin. This is the same code that gets
|
||||
generated by `generator-conversejs <https://github.com/jcbrand/generator-conversejs>`_.
|
||||
|
||||
// Your custom code can come here ...
|
||||
},
|
||||
.. code-block:: javascript
|
||||
|
||||
/* Override converse.js's XMPPStatus Backbone model so that we can override the
|
||||
* function that sends out the presence stanza.
|
||||
*/
|
||||
'XMPPStatus': {
|
||||
'sendPresence': function (type, status_message, jid) {
|
||||
// The "_converse" object is available via the __super__
|
||||
// attribute.
|
||||
var _converse = this.__super__._converse;
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as a module called "myplugin"
|
||||
define("<%= name %>", ["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) {
|
||||
|
||||
// Custom code can come here ...
|
||||
// Commonly used utilities and variables can be found under the "env"
|
||||
// namespace of the "converse" global.
|
||||
var Strophe = converse.env.Strophe,
|
||||
$iq = converse.env.$iq,
|
||||
$msg = converse.env.$msg,
|
||||
$pres = converse.env.$pres,
|
||||
$build = converse.env.$build,
|
||||
b64_sha1 = converse.env.b64_sha1;
|
||||
$ = converse.env.jQuery,
|
||||
_ = converse.env._,
|
||||
moment = converse.env.moment;
|
||||
|
||||
// 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);
|
||||
// The following line registers your plugin.
|
||||
converse.plugins.add("<%= name %>", {
|
||||
|
||||
// Custom code can come here ...
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
/* Optional dependencies are other plugins which might be
|
||||
* overridden or relied upon, and therefore need to be loaded before
|
||||
* this plugin. They are called "optional" because they might not be
|
||||
* available, in which case any overrides applicable to them will be
|
||||
* ignored.
|
||||
*
|
||||
* NB: These plugins need to have already been loaded via require.js.
|
||||
*
|
||||
* It's possible to make optional dependencies non-optional.
|
||||
* If the setting "strict_plugin_dependencies" is set to true,
|
||||
* an error will be raised if the plugin is not found.
|
||||
*/
|
||||
'optional_dependencies': [],
|
||||
|
||||
/* Converse.js's plugin mechanism will call the initialize
|
||||
* method on any plugin (if it exists) as soon as the plugin has
|
||||
* been loaded.
|
||||
*/
|
||||
'initialize': function () {
|
||||
/* Inside this method, you have access to the private
|
||||
* `_converse` object.
|
||||
*/
|
||||
var _converse = this._converse;
|
||||
_converse.log("The <%= name %> plugin is being initialized");
|
||||
|
||||
/* From the `_converse` object 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.
|
||||
*
|
||||
* You can also specify new configuration settings for this
|
||||
* plugin, or override the default values of existing
|
||||
* configuration settings. This is done like so:
|
||||
*/
|
||||
_converse.api.settings.update({
|
||||
'initialize_message': 'Initializing <%= name %>!'
|
||||
});
|
||||
|
||||
/* The user can then pass in values for the configuration
|
||||
* settings when `converse.initialize` gets called.
|
||||
* For example:
|
||||
*
|
||||
* converse.initialize({
|
||||
* "initialize_message": "My plugin has been initialized"
|
||||
* });
|
||||
*
|
||||
* And the configuration setting is then available via the
|
||||
* `user_settings` attribute:
|
||||
*/
|
||||
alert(this._converse.user_settings.initialize_message);
|
||||
|
||||
/* Besides `_converse.api.settings.update`, there is also a
|
||||
* `_converse.api.promises.add` method, which allows you to
|
||||
* add new promises that your plugin is obligated to fulfill.
|
||||
*
|
||||
* This method takes a string or a list of strings which
|
||||
* represent the promise names:
|
||||
*
|
||||
* _converse.api.promises.add('myPromise');
|
||||
*
|
||||
* Your plugin should then, when appropriate, resolve the
|
||||
* promise by calling `_converse.api.emit`, which will also
|
||||
* emit an event with the same name as the promise.
|
||||
* For example:
|
||||
*
|
||||
* _converse.api.emit('operationCompleted');
|
||||
*
|
||||
* Other plugins can then either listen for the event
|
||||
* `operationCompleted` like so:
|
||||
*
|
||||
* _converse.api.listen.on('operationCompleted', function { ... });
|
||||
*
|
||||
* or they can wait for the promise to be fulfilled like so:
|
||||
*
|
||||
* _converse.api.waitUntil('operationCompleted', function { ... });
|
||||
*/
|
||||
},
|
||||
|
||||
/* If you want to override some function or a Backbone model or
|
||||
* view defined elsewhere in converse.js, then you do that under
|
||||
* the "overrides" namespace.
|
||||
*/
|
||||
'overrides': {
|
||||
/* For example, the private *_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 can come 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.
|
||||
_converse.__super__.onConnected.apply(this, arguments);
|
||||
|
||||
// Your custom code can come here ...
|
||||
},
|
||||
|
||||
/* Override converse.js's XMPPStatus Backbone model so that we can override the
|
||||
* function that sends out the presence stanza.
|
||||
*/
|
||||
'XMPPStatus': {
|
||||
'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);
|
||||
|
||||
// Custom code can come here ...
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user