JavaScript

JavaScript Modules

Developers should use the browser native ECMAScript modules for writing JavaScript code in Elgg.

Here we’ll describe making and importing these modules in Elgg.

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_import_esm('myplugin/say_hello');

On the client-side, this will asynchronously load the module, load any dependencies, and execute the module’s code, if it has any.

Définir le Module

Files with the extension « .mjs » are automatically added to an importmap so they can be imported based on their view name.

For example if we have a file in « views/default/myplugin/say_hello.mjs » we can import from php with elgg_import_esm('myplugin/say_hello') or from javascript using the import statement import 'myplugin/say_hello'; or on demand with the import() function.

If your modules do not have an « .mjs » extension, for example when they come from a dependency, you might need to register it to the importmap. After registration they can be imported under their registered name.

<?php
elgg_register_esm('myplugin/say_hello', elgg_get_simplecache_url('external/dependency/modulename.js'));

Passer des paramètres aux modules

Les événements elgg.data

Le module elgg fournit un objet elgg.data qui est renseigné à partir de deux événements côté serveur :

  • elgg.data, page: This filters an associative array of data passed to the client.

Passons quelques données au module :

<?php

function myplugin_config_page(\Elgg\Event $event) {
    $value = $event->getValue();
    $value['myplugin']['api'] = elgg_get_site_url() . 'myplugin-api';
    $value['myplugin']['key'] = 'none';

    $user = elgg_get_logged_in_user_entity();
    if ($user) {
            $value['myplugin']['key'] = $user->myplugin_api_key;
    }

    return $value;
}

elgg_register_event_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

    // ...
});

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.

Modules fournis avec Elgg

Module elgg

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_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.

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 Elgg release (X.Y.Z).
elgg.config.release;

Module elgg/Ajax

Voir la page Ajax pour plus de détails.

Module elgg/hooks

Le module elgg/hooks peut être utilisé pour faire interagir les plugins entre eux.

Traduisez le texte de l’interface

define(['elgg/hooks'], function (hooks) {
    hooks.register('my_plugin:filter', 'value', handler, priority);

    var result = hooks.trigger('my_plugin:filter', 'value', {}, 'default');

Module elgg/i18n

Le module elgg/i18n peut être utilisé pour utiliser les traductions.

Traduisez le texte de l’interface

define(['elgg/i18n'], function (i18n) {
    i18n.echo('example:text', ['arg1']);
});

Module elgg/system_messages

Le module elgg/system_messages peut être utilisé pour afficher les messages système à l’utilisateur.

define(['elgg/system_messages'], function (system_messages) {
    system_messages.success('Your success message');

    system_messages.error('Your error message');

    system_messages.clear();
});

Module elgg/security

Le module elgg/security peut être utilisés pour ajouter un jeton de sécurité à un objet, une URL, ou une chaîne de requête :

     define(['elgg/security'], function (security) {
    // returns {
        //   __elgg_token: "1468dc44c5b437f34423e2d55acfdd87",
        //   __elgg_ts: 1328143779,
        //   other: "data"
        // }
        security.addToken({'other': 'data'});

        // returns: "action/add?__elgg_ts=1328144079&__elgg_token=55fd9c2d7f5075d11e722358afd5fde2"
        security.addToken("action/add");

        // returns "?arg=val&__elgg_ts=1328144079&__elgg_token=55fd9c2d7f5075d11e722358afd5fde2"
        security.addToken("?arg=val");
});

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 automatiquement chargé pour le contenu dessiné en utilisant output/url avec l’attribut class='elgg-popup' et en définissant le module cible avec un attribut href (ou data-href). Le positionnement du module contextuel 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',
   'class' => 'elgg-popup',
]);

// Button with custom positioning of the popup
elgg_import_esm('elgg/popup');
echo elgg_format_element('button', [
   'class' => 'elgg-button elgg-button-submit elgg-popup',
   '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 :

import('elgg/widgets').then((widgets) => {
    widgets.default.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 balise img)

  • elgg-lightbox-inline - affiche un élément HTML en ligne dans une boîte surgissante - lightbox

  • elgg-lightbox-iframe - charge une ressource dans une iframe

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) :

import('elgg/lightbox').then((lightbox) => {
   var options = {
      photo: true,
      width: 500
   };
   lightbox.default.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.

import('elgg/ckeditor').then((elggCKEditor) => {
   elggCKEditor.default.bind('#my-text-area');

   // Toggle CKEditor
   elggCKEditor.default.toggle('#my-text-area');

   // Focus on CKEditor input
   elggCKEditor.default.focus('#my-text-area');
   // or
   $('#my-text-area').trigger('focus');

   // Reset CKEditor input
   elggCKEditor.default.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
$(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 recommandons fortement d’utiliser les modules AMD et qu’il n’y ait pas d’API Elgg pour charger les scripts, vous pouvez enregistrer des scripts dans un gestionnaire d’événements pour ajouter des éléments aux liens principaux ;

elgg_register_event_handler('head', 'page', $callback);

Hooks

Le moteur JS dispose d’un système de hooks similaire aux événements du moteur PHP : les hooks sont déclenchés et les plugins peuvent enregistrer des fonctions pour réagir ou modifier des informations.

Enregistrer des gestionnaires de hook

Les fonctions du gestionnaire sont enregistrées en utilisant hooks.register(). Plusieurs gestionnaires peuvent être enregistrés pour le même hook.

define(['elgg/hooks'], function(hooks) {
    hooks.register('name', 'type', {handler}, {priority});
});

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/hooks'], function(hooks) {
    hooks.trigger('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 de FormData 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.

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.