JavaScript¶
Contenu
AMD¶
Les développeurs doivent utiliser le standard AMD (« Asynchronous Module Definition » ou Définition du module asynchrone) pour écrire du code JavaScript dans Elgg.
Ici, nous allons décrire la création et l’exécution de modules AMD. La documentation RequireJS pour définir des modules peut également être utile.
Exécuter un module dans la page en cours¶
Il est aisé d’indiquer à Elgg de charger un module existant dans la page en cours :
<?php
elgg_require_js("myplugin/say_hello");
Du côté client, cela chargera le module de manière asynchrone, chargera toutes les dépendances, et exécutera la fonction de définition du module, s’il en dispose d’une.
Définir le Module¶
Ici, nous définissons un module de base qui modifie la page, en passant une « fonction de définition » à define()
:
// in views/default/myplugin/say_hello.js
define(['jquery', 'elgg'], function($, elgg) {
$('body').append(elgg.echo('hello_world'));
});
Le nom du module est déterminé par le nom de vue, qui est ici myplugin/say_hello.js
. Nous retirons l’extension .js
, pour conserver myplugin/say_hello
.
Avertissement
La fonction de définition doit avoir un argument nommé require
.
Rendre les modules dépendants d’autres modules¶
Ci-dessous nous factorisons un peu de sorte que le module dépende d’un nouveau module monplugin/hello
pour fournir la salutation :
// in views/default/myplugin/hello.js
define(['elgg'], function(elgg) {
return elgg.echo('hello_world');
});
// in views/default/myplugin/say_hello.js
define(['jquery', 'myplugin/hello'], function($, hello) {
$('body').append(hello);
});
Passer des paramètres aux modules¶
Les hooks de plugin elgg.data
¶
Le module elgg
fournit un objet elgg.data
qui est peuplé à partir de deux hooks côté serveur :
elgg.data, site : Ceci filtre un tableau associatif de données spécifiques au site, transmises au client et mises en cache.
elgg.data, page : Ceci filtre un tableau associatif de données non mises en cache, et spécifiques à la page transmise au client.
Passons quelques données au module :
<?php
function myplugin_config_site(\Elgg\Hook $hook) {
$value = $hook->getValue();
// this will be cached client-side
$value['myplugin']['api'] = elgg_get_site_url() . 'myplugin-api';
$value['myplugin']['key'] = 'none';
return $value;
}
function myplugin_config_page(\Elgg\Hook $hook) {
$user = elgg_get_logged_in_user_entity();
if (!$user) {
return;
}
$value = $hook->getValue();
$value['myplugin']['key'] = $user->myplugin_api_key;
return $value;
}
elgg_register_plugin_hook_handler('elgg.data', 'site', 'myplugin_config_site');
elgg_register_plugin_hook_handler('elgg.data', 'page', 'myplugin_config_page');
define(['elgg'], function(elgg) {
var api = elgg.data.myplugin.api;
var key = elgg.data.myplugin.key; // "none" or a user's key
// ...
});
Note
Dans elgg.data
les données de la page remplacent les données du site. Notez également que json_encode()
est utilisé pour copier les données côté client, de sorte que les données doivent être encodables en JSON.
Créer un module de configuration¶
Vous pouvez utiliser un module PHP pour transmettre des valeurs à partir du serveur. Pour créer le module myplugin/settings
, créez le fichier de la vue views/default/myplugin/settings.js.php
(notez la double extension .js.php
).
<?php
// this will be cached client-side
$settings = [
'api' => elgg_get_site_url() . 'myplugin-api',
'key' => null,
];
?>
define(<?php echo json_encode($settings); ?>);
Vous devez également enregistrer manuellement la vue en tant que ressource externe :
<?php
// note the view name does not include ".php"
elgg_register_simplecache_view('myplugin/settings.js');
Note
La vue PHP est mise en cache, vous devez donc traiter la sortie comme statique (la même pour tous les utilisateurs) et éviter toute logique spécifique à la session.
Définir l’URL d’un module¶
Vous pouvez avoir un script AMD en dehors de vos vues que vous souhaitez mettre à disposition en tant que module.
La meilleure façon d’y parvenir est de configurer le chemin d’accès au fichier à l’aide de la section views
du fichier elgg-plugin.php
dans la racine de votre plugin :
<?php // elgg-plugin.php
return [
'views' => [
'default' => [
'underscore.js' => 'vendor/npm-asset/underscore/underscore.min.js',
],
],
];
Si vous avez copié le script directement dans votre plugin au lieu de le gérer avec Composer, vous pouvez utiliser quelque chose comme ceci à la place :
<?php // elgg-plugin.php
return [
'views' => [
'default' => [
'underscore.js' => __DIR__ . '/node_modules/underscore/underscore.min.js',
],
],
];
Voilà ! Elgg chargera maintenant ce fichier chaque fois que le module « underscore » est requis.
Utiliser des bibliothèques JS traditionnelles comme modules¶
Il est possible de prendre en charge les bibliothèques JavaScript qui ne se déclarent pas comme modules AMD (c’est-à-dire qu’elles déclarent plutôt des variables globales) si vous les intégrez via des shims en définissant exports
et deps
dans elgg_define_js
:
// set the path, define its dependencies, and what value it returns
elgg_define_js('jquery.form', [
'deps' => ['jquery'],
'exports' => 'jQuery.fn.ajaxForm',
]);
Lorsque cela est demandé côté client :
Le module jQuery est chargé, car il est marqué comme une dépendance.
https://elgg.example.org/cache/125235034/views/default/jquery.form.js
est chargé et exécuté.La valeur de
window.jQuery.fn.ajaxForm
est renvoyée par le module.
Avertissement
Les appels à elgg_define_js()
doivent être faits dans un gestionnaire d’événement init, system
.
Quelques points à noter¶
N’utilisez plus
elgg.provide()
ni d’autres moyens pour attacher du code àelgg
ou à d’autres objets globaux. Utilisez des modules.Renvoie la valeur du module au lieu de l’ajouter à une variable globale.
Les fichiers statiques (.js, .css, etc.) sont automatiquement minifiés et mis en cache par le système simplecache de Elgg.
La configuration est également mise en cache dans le simplecache et ne doit pas s’appuyer sur des valeurs spécifiques à l’utilisateur comme
get_current_language()
.
Modules fournis avec Elgg¶
Module elgg
¶
elgg.echo()
Traduisez le texte de l’interface
elgg.echo('example:text', ['arg1']);
elgg.system_message()
Affiche un message d’état à l’utilisateur.
elgg.system_message(elgg.echo('success'));
elgg.register_error()
Affiche un message d’erreur à l’utilisateur.
elgg.register_error(elgg.echo('error'));
elgg.normalize_url()
Normalise une URL par rapport à la racine de elgg :
// "http://localhost/elgg/blog"
elgg.normalize_url('/blog');
elgg.forward()
Redirige vers une nouvelle page.
elgg.forward('/blog');
Cette fonction normalise automatiquement l’URL.
elgg.parse_url()
Analyse et découpe une URL en ses composants :
// returns {
// fragment: "fragment",
// host: "community.elgg.org",
// path: "/file.php",
// query: "arg=val"
// }
elgg.parse_url('http://community.elgg.org/file.php?arg=val#fragment');
elgg.get_page_owner_guid()
Récupère le GUID du propriétaire de la page actuelle.
elgg.register_hook_handler()
Enregistre un gestionnaire de hook avec le système d’événements.
elgg.trigger_hook()
Émet un hook d’événement dans le système d’événements.
value = elgg.trigger_hook('my_plugin:filter', 'value', {}, value);
elgg.security.refreshToken()
Force le rafraîchissement de tous les jetons XSRF sur la page.
Par défaut, ceci est automatiquement appelé toutes les 5 minutes.
L’utilisateur sera averti si sa session a expiré.
elgg.security.addToken()
Ajoute un jeton de sécurité à un objet, une URL ou une chaîne de requête :
// returns {
// __elgg_token: "1468dc44c5b437f34423e2d55acfdd87",
// __elgg_ts: 1328143779,
// other: "data"
// }
elgg.security.addToken({'other': 'data'});
// returns: "action/add?__elgg_ts=1328144079&__elgg_token=55fd9c2d7f5075d11e722358afd5fde2"
elgg.security.addToken("action/add");
// returns "?arg=val&__elgg_ts=1328144079&__elgg_token=55fd9c2d7f5075d11e722358afd5fde2"
elgg.security.addToken("?arg=val");
elgg.get_logged_in_user_entity()
Renvoie l’utilisateur connecté sous la forme d’un objet JS ElggUser.
elgg.get_logged_in_user_guid()
Renvoie le GUID de l’utilisateur connecté.
elgg.is_logged_in()
Vrai si l’utilisateur est connecté.
elgg.is_admin_logged_in()
Vrai si l’utilisateur est connecté et est administrateur.
elgg.config.get_language()
Récupère la langue de la page actuelle.
Un certain nombre de valeurs de configuration sont définies dans l’objet elgg :
// The root of the website.
elgg.config.wwwroot;
// The default site language.
elgg.config.language;
// The current page's viewtype
elgg.config.viewtype;
// The Elgg version (YYYYMMDDXX).
elgg.config.version;
// The Elgg release (X.Y.Z).
elgg.config.release;
Module elgg/Ajax
¶
Voir la page Ajax pour plus de détails.
Module elgg/spinner
¶
Le module elgg/spinner
peut être utilisé pour créer un indicateur de chargement fixé en haut de la fenêtre. Cela peut être utilisé pour indiquer aux utilisateurs que le système exécute une tâche plus longue. L’utilisation des fonctionnalités ajax de elgg/Ajax
le fait par défaut. Vous pouvez également l’utiliser dans votre propre code.
define(['elgg/spinner'], function (spinner) {
spinner.start();
// your code
spinner.stop();
});
Module elgg/popup
¶
Le module elgg/popup
peut être utilisé pour afficher une superposition - overlay - placée relativement à son ancre (déclencheur - trigger).
Le module elgg/popup
est chargé par défaut, et lier un module popup à une ancre est aussi simple que d’ajouter l’attribut rel="popup"
et de définir le module cible avec un attribut href
(ou data-href
). Le positionnement du module popup peut être défini avec l’attribut data-position
de l’élément déclencheur.
echo elgg_format_element('div', [
'class' => 'elgg-module-popup hidden',
'id' => 'popup-module',
], 'Popup module content');
// Simple anchor
echo elgg_view('output/url', [
'href' => '#popup-module',
'text' => 'Show popup',
'rel' => 'popup',
]);
// Button with custom positioning of the popup
echo elgg_format_element('button', [
'rel' => 'popup',
'class' => 'elgg-button elgg-button-submit',
'text' => 'Show popup',
'data-href' => '#popup-module',
'data-position' => json_encode([
'my' => 'center bottom',
'at' => 'center top',
]),
]);
Le module elgg/popup
vous permet de créer des éléments d’interface utilisateur/UX plus complexes. Vous pouvez ouvrir et fermer les modules contextuels via le code :
define(['jquery', 'elgg/popup'], function($, popup) {
$(document).on('click', '.elgg-button-popup', function(e) {
e.preventDefault();
var $trigger = $(this);
var $target = $('#my-target');
var $close = $target.find('.close');
popup.open($trigger, $target, {
'collision': 'fit none'
});
$close.on('click', popup.close);
});
});
Vous pouvez utiliser le hook plugin getOptions, ui.popup
pour manipuler la position du popup avant qu’il soit ouvert. Vous pouvez utiliser les événements jQuery open
et close
pour manipuler le module popup après son ouverture ou sa fermeture.
define(['jquery', 'elgg/Ajax'], function($, Ajax) {
$('#my-target').on('open', function() {
var $module = $(this);
var $trigger = $module.data('trigger');
var ajax = new Ajax();
ajax.view('my_module', {
beforeSend: function() {
$trigger.hide();
$module.html('').addClass('elgg-ajax-loader');
},
success: function(output) {
$module.removeClass('elgg-ajax-loader').html(output);
}
});
}).on('close', function() {
var $trigger = $(this).data('trigger');
$trigger.show();
});
});
Les modules popups ouverts contiennent toujours les données suivantes auxquelles il est possible d’accéder via $.data()
:
trigger
- élément jQuery utilisé pour déclencher l’ouverture du module popup
position
- Un objet définissant la position du module popup qui a été passé à$.position()
Par défaut, l’élément target
sera ajouté à $('body')
, modifiant ainsi la hiérarchie DOM. Si vous devez conserver la position DOM du module popup, vous pouvez ajouter la classe .elgg-popup-inline
à votre déclencheur.
Module elgg/widgets
¶
Des plugins qui chargent une mise en page widget via Ajax devraient s’initialiser via ce module :
require(['elgg/widgets'], function (widgets) {
widgets.init();
});
Module elgg/lightbox
¶
Elgg est distribué avec la bibliothèque jQuery Colorbox. Veuillez consulter https://www.jacklmoore.com/colorbox/ pour plus d’informations sur les options de cette lightbox.
Utilisez les classes suivantes pour lier vos éléments d’ancrage à des boîtes surgissantes lightbox :
elgg-lightbox
- charge une ressource HTML
elgg-lightbox-photo
- charge une ressource de type image (devrait être utilisé pour éviter d’afficher les octets d’image bruts au lieu de la baliseimg
)
elgg-lightbox-inline
- affiche un élément HTML en ligne dans une boîte surgissante - lightbox
elgg-lightbox-iframe
- charge une ressource dans uneiframe
Vous pouvez appliquer des options de colorbox à un élément individuel elgg-lightbox
en définissant l’attribut data-colorbox-opts
avec un objet de paramètres JSON.
echo elgg_view('output/url', [
'text' => 'Open lightbox',
'href' => 'ajax/view/my_view',
'class' => 'elgg-lightbox',
'data-colorbox-opts' => json_encode([
'width' => '300px',
])
]);
Utilisez le hook plugin "getOptions", "ui.lightbox"
pour filtrer les options passées à $.colorbox()
chaque fois qu’une lightbox est ouverte.
Le module AMD elgg/lightbox
devrait être utilisé pour ouvrir et fermer la lightbox de manière programmatique :
define(['elgg/lightbox', 'elgg/spinner'], function(lightbox, spinner) {
lightbox.open({
html: '<p>Hello world!</p>',
onClosed: function() {
lightbox.open({
onLoad: spinner.start,
onComplete: spinner.stop,
photo: true,
href: 'https://elgg.org/cache/1457904417/default/community_theme/graphics/logo.png',
});
}
});
});
Pour prendre en charge des ensembles de galerie (via l’attribut rel
), vous devez lier colorbox directement à un sélecteur spécifique (notez que cela ignorera data-colorbox-opts
sur tous les éléments d’un ensemble) :
require(['elgg/lightbox'], function(lightbox) {
var options = {
photo: true,
width: 500
};
lightbox.bind('a[rel="my-gallery"]', options, false); // 3rd attribute ensures binding is done without proxies
});
Vous pouvez également redimensionner la lightbox via le code si nécessaire :
define(['elgg/lightbox'], function(lightbox) {
lightbox.resize({
width: '300px'
});
});
Si vous souhaitez que votre contenu soit chargé par le module AMD elgg/Ajax
, qui charge automatiquement les dépendances JS, vous pouvez passer l’option ajaxLoadWithDependencies
define(['elgg/lightbox'], function(lightbox) {
lightbox.open({
href: 'some/view/with/js/dependencies',
ajaxLoadWithDependencies: true
});
});
Module elgg/ckeditor
¶
Ce module peut être utilisé pour ajouter un éditeur WYSIWYG à un textarea (nécessite que le plugin ckeditor
soit activé). Notez que le WYSIWYG sera automatiquement attaché à toutes les instances de .elgg-input-longtext
.
require(['elgg/ckeditor'], function (elggCKEditor) {
elggCKEditor.bind('#my-text-area');
// Toggle CKEditor
elggCKEditor.toggle('#my-text-area');
// Focus on CKEditor input
elggCKEditor.focus('#my-text-area');
// or
$('#my-text-area').trigger('focus');
// Reset CKEditor input
elggCKEditor.reset('#my-text-area');
// or
$('#my-text-area').trigger('reset');
});
Composant d’onglets en ligne¶
Le composant d’onglets en ligne déclenche un événement open
chaque fois qu’un onglet est ouvert et, en cas d’onglets ajax, une fois le chargement terminé :
// Add custom animation to tab content
require(['jquery'], function($) {
$(document).on('open', '.theme-sandbox-tab-callback', function() {
$(this).find('a').text('Clicked!');
$(this).data('target').hide().show('slide', {
duration: 2000,
direction: 'right',
complete: function() {
alert('Thank you for clicking. We hope you enjoyed the show!');
$(this).css('display', ''); // .show() adds display property
}
});
});
});
Scripts traditionnels¶
Bien que nous recommandions fortement d’utiliser des modules AMD et qu’il n’existe pas d’API Elgg pour le chargement des scripts, vous pouvez enregistrer des scripts dans un gestionnaire de hook pour ajouter des éléments aux liens de l’entête ;
elgg_register_plugin_hook_handler('head', 'page', $callback);
Hooks¶
Le moteur JS dispose d’un système de hooks similaire aux hooks plugin du moteur PHP : des hooks sont déclenchés et des plugins peuvent enregistrer des fonctions pour réagir ou pour modifier l’information. Il n’y a pas de concept d’événement Elgg dans le moteur JS ; tout dans le moteur JS est implémenté sous forme de hook.
Enregistrer des gestionnaires de hook¶
Les fonctions gestionnaires sont enregistrées à l’aide de elgg.register_hook_handler()
. Plusieurs gestionnaires peuvent être enregistrés pour le même hook.
La fonction gestionnaire - handler¶
Le gestionnaire va recevoir 4 arguments :
hook - Le nom du hook
type - Le type de hook
params - Un objet ou un ensemble de paramètres propres au hook
value - La valeur actuelle
La valeur value
passera par chaque hook. Selon le hook, les fonctions de rappel peuvent simplement réagir, ou modifier les données.
Déclencher des hooks personnalisés¶
Les plugins peuvent déclencher leurs propres hooks :
define(['elgg'], function(elgg) {
elgg.trigger_hook('name', 'type', {params}, "value");
});
Hooks disponibles¶
- init, system
Les plugins devraient enregistrer leurs fonctions d’initialisation via ce hook. Il est déclenché après que les JS de Elgg sont chargés, et une fois que tous les modules de démarrage - boot - des plugins sont initialisés.
- getOptions, ui.popup
Ce hook est déclenché pour les affichages surgissants - popups (
"rel"="popup"
) et permet des options de positionnement personnalisées.- getOptions, ui.lightbox
Ce hook peut être utilisé pour filtrer les options transmises à
$.colorbox()
- config, ckeditor
Cela filtre l’objet de configuration CKEditor. Enregistrez un gestionnaire pour ce hook dans le module de démarrage du plugin. Les valeurs par défaut sont visibles dans le module
elgg/ckeditor/config
.- prepare, ckeditor
Ce hook peut être utilisé pour modifier globalement
CKEDITOR
. Vous pouvez utiliser ce hook pour enregistrer de nouveaux plugins CKEditor et ajouter des liaisons d’événements - event bindings.- ajax_request_data, *
Ceci filtre les demandes de données envoyées par le module
elgg/Ajax
. Voir Ajax pour plus de détails. Le hook doit vérifier si les données sont un objet simple ou une instance deFormData
pour récupérer les valeurs à l’aide de la bonne API.- ajax_response_data, *
Ceci filtre les données de réponse retournées aux utilisateurs par le module
elgg/Ajax
. Voir Ajax pour plus de détails.- insert, editor
Ce hook est déclenché par le plugin embed et peut être utilisé pour filtrer le contenu avant qu’il soit inséré dans le textarea. Ce hook peut également être utilisé par les éditeurs WYSIWYG pour insérer du contenu à l’aide de leur propre API (dans ce cas, le gestionnaire devrait renvoyer
false
). Voir le plugin ckeditor pour un exemple.
Actifs tierce-partie - assets¶
Nous vous recommandons de gérer des scripts et des styles tiers avec Composer. Le composer.json de Elgg est configuré pour installer des dépendances à partir des référentiels de packages NPM ou Yarn à l’aide de l’outil de ligne de commande Composer. La configuration de base installe les actifs à partir de Asset Packagist (un référentiel géré par la communauté Yii).
Alternativement, vous pouvez installer fxp/composer-asset-plugin
globalement pour obtenir les mêmes résultats, mais l’installation et la mise à jour prennent beaucoup plus de temps.
Par exemple, pour inclure jQuery, vous pouvez exécuter les commandes composer suivantes :
composer require npm-asset/jquery:~2.0
Si vous utilisez un projet de démarrage - starter-project - ou que vous utilisez Elgg sous forme de dépendance d’un projet composer personnalisé, mettez à jour votre composer.json
avec la configuration suivante :
{
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
],
"config": {
"fxp-asset": {
"enabled": false
}
},
}
Vous pouvez trouver des informations supplémentaires sur le site de Asset Packagist.