Update plugin example with code from the yeoman generator

Also improve the introductory text.
This commit is contained in:
JC Brand 2017-09-03 22:10:45 +02:00
parent 4104dec89b
commit f668f2981a

View File

@ -14,24 +14,36 @@ Writing a plugin
Introduction Introduction
------------ ------------
Developers are able to extend and override the objects, functions and the Converse.js is exposes a plugin architecture which allows developers to modify
Backbone models and views that make up converse.js by means of writing plugins. and extend its functionality.
Specifically, plugins enable developers to extend and override existing objects,
functions and `Backbone <http://backbonejs.org/>`_ models and views that make up
Converse.js, and also give them the ability to write new models and views.
Various core features of Converse.js, such as
`Message Archive Management <https://xmpp.org/extensions/xep-0313.html>`_ and
`Group chats <https://xmpp.org/extensions/xep-0045.html>`_ are implemented
as plugins, thereby showing their power and flexibility.
Converse.js uses `pluggable.js <https://github.com/jcbrand/pluggable.js/>`_ as Converse.js uses `pluggable.js <https://github.com/jcbrand/pluggable.js/>`_ as
its plugin architecture. its plugin architecture.
To understand how this plugin architecture works, please read the To more deeply understand how this plugin architecture works, please read the
`pluggable.js documentation <https://jcbrand.github.io/pluggable.js/>`_ `pluggable.js documentation <https://jcbrand.github.io/pluggable.js/>`_
and to understand its inner workins, please refer to the `annotated source code and to understand its inner workins, please refer to the `annotated source code
<https://jcbrand.github.io/pluggable.js/docs/pluggable.html>`_. <https://jcbrand.github.io/pluggable.js/docs/pluggable.html>`_.
Below you'll find an example plugin. Because convers.js is only Javascript, Playing with a Converse.js plugin in JSFiddle
HTML and CSS (with no backend code required like PHP, Python or Ruby) it runs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fine in JSFiddle.
Here's an Fiddle with a plugin that calls `alert` when the plugin gets Because Converse.js consists only of JavaScript, HTML and CSS (with no backend
initialized and when a message gets rendered: https://jsfiddle.net/4drfaok0/15/ code required like PHP, Python or Ruby) it runs fine in JSFiddle.
Here's an 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/
Registering a plugin Registering a plugin
-------------------- --------------------
@ -231,148 +243,157 @@ A full example plugin
.. code-block:: javascript .. code-block:: javascript
(function (root, factory) { (function (root, factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
// AMD. Register as a module called "myplugin" // AMD. Register as a module called "myplugin"
define("myplugin", ["converse"], factory); define("<%= name %>", ["converse"], factory);
} else { } else {
// Browser globals. If you're not using a module loader such as require.js, // 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 // then this line below executes. Make sure that your plugin's <script> tag
// appears after the one from converse.js. // appears after the one from converse.js.
factory(converse); factory(converse);
} }
}(this, function (converse) { }(this, function (converse) {
// Commonly used utilities and variables can be found under the "env" // Commonly used utilities and variables can be found under the "env"
// namespace of the "converse" global. // namespace of the "converse" global.
var Strophe = converse.env.Strophe, var Strophe = converse.env.Strophe,
$iq = converse.env.$iq, $iq = converse.env.$iq,
$msg = converse.env.$msg, $msg = converse.env.$msg,
$pres = converse.env.$pres, $pres = converse.env.$pres,
$build = converse.env.$build, $build = converse.env.$build,
b64_sha1 = converse.env.b64_sha1; b64_sha1 = converse.env.b64_sha1;
$ = converse.env.jQuery, $ = converse.env.jQuery,
_ = converse.env._, _ = converse.env._,
moment = converse.env.moment; moment = converse.env.moment;
// The following line registers your plugin. // The following line registers your plugin.
converse.plugins.add('myplugin', { converse.plugins.add("<%= name %>", {
initialize: function () { /* Optional dependencies are other plugins which might be
// Converse.js's plugin mechanism will call the initialize * overridden or relied upon, and therefore need to be loaded before
// method on any plugin (if it exists) as soon as the plugin has * this plugin. They are called "optional" because they might not be
// been loaded. * 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': [],
var _converse = this._converse; /* 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");
// Inside this method, you have access to the closured /* From the `_converse` object you can get any configuration
// _converse object, from which you can get any configuration * options that the user might have passed in via
// options that the user might have passed in via * `converse.initialize`. These values are stored in the
// converse.initialize. These values are stored in the * "user_settings" attribute.
// "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 %>!'
});
// We can also specify new configuration settings for this /* The user can then pass in values for the configuration
// plugin, or override the default values of existing * settings when `converse.initialize` gets called.
// configuration settings. This is done like so: * 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);
_converse.api.settings.update({ /* Besides `_converse.api.settings.update`, there is also a
'initialize_message': 'Initialized', // New configuration setting * `_converse.api.promises.add` method, which allows you to
'auto_subscribe': true, // New default value for an * add new promises that your plugin is obligated to fulfill.
// existing "core" configuration setting *
}); * 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 { ... });
*/
},
// The user can then pass in values for the configuration /* If you want to override some function or a Backbone model or
// settings when `converse.initialize` gets called. * view defined elsewhere in converse.js, then you do that under
// For example: * the "overrides" namespace.
// */
// converse.initialize({ 'overrides': {
// "initialize_message": "My plugin has been initialized" /* For example, the private *_converse* object has a
// }); * method "onConnected". You can override that method as follows:
// */
// And the configuration setting is then available via the 'onConnected': function () {
// `user_settings` attribute: // Overrides the onConnected method in converse.js
// alert(this._converse.user_settings.initialize_message); // Top-level functions in "overrides" are bound to the
// inner "_converse" object.
var _converse = this;
// Besides `_converse.api.settings.update`, there is also a // Your custom code can come here ...
// `_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 // You can access the original function being overridden
// represent the promise names. // 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);
_converse.api.promises.add('operationCompleted'); // Your custom code can come here ...
},
// Your plugin should then, when appropriate, resolve the /* Override converse.js's XMPPStatus Backbone model so that we can override the
// promise by calling `_converse.api.emit`, which will also * function that sends out the presence stanza.
// emit an event with the same name as the promise. */
// For example: 'XMPPStatus': {
// _converse.api.emit('operationCompleted'); 'sendPresence': function (type, status_message, jid) {
// // The "_converse" object is available via the __super__
// Other plugins can then either listen for the event // attribute.
// `operationCompleted` like so: var _converse = this.__super__._converse;
// `_converse.api.listen.on('operationCompleted', function { ... });`
//
// or they can wait for the promise to be fulfilled like so:
// `_converse.api.waitUntil('operationCompleted', function { ... });`
},
// Optional dependencies are other plugins which might be // Custom code can come here ...
// 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.
// It's possible however to make optional dependencies non-optional. // You can call the original overridden method, by
// If the setting "strict_plugin_dependencies" is set to true, // accessing it via the __super__ attribute.
// an error will be raised if the plugin is not found. // When calling it, you need to apply the proper
// // context as reference by the "this" variable.
// NB: These plugins need to have already been loaded via require.js. this.__super__.sendPresence.apply(this, arguments);
optional_dependencies: [], // Custom code can come here ...
}
overrides: { }
// If you want to override some function or a Backbone model or }
// view defined elsewhere in converse.js, 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.
_converse.__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);
}
}
}
});
}));