JPlatform 10 - Documentation - Personnalisation de l'éditeur Wysiwyg

Cette fiche décrit les possibilités de personnalisation de l'éditeur wysiwyg (texte riche) de JPlatform 10, par configuration ou développement.

1. Introduction

L'éditeur wysiwyg TinyMCE est utilisé dans tous les champs texte riches de Jalios JPlatform 10.
Cette fiche documente les moyens à votre disposition pour configurer et/ou étendre l'éditeur selon vos besoins.

1.1 Possibilités de personnalisation

JPlatform enrichit les fonctionnalités et capacités techniques disponibles en standard dans l'éditeur TinyMCE.
Plusieurs possibilités sont disponibles pour personnaliser le produit selon vos besoins : 

  • Insertion Unifiée : pour proposer à l'utilisateur l'insertion rapide de différents types de contenus.
  • Configuration de l'éditeur : pour modifier ou enrichir la configuration de l'éditeur TinyMCE (bouton et menu de barre d'outils, menu contextuel, ajout de plugin TinyMCE, etc)
  • JHTML et rendu dynamique : pour modifier le rendu effectué pour certaines balises JHTML et/ou types de contenus (publication, médias, ...)
  • Nettoyage HTML :  pour assouplir ou renforcer les politiques de nettoyage du HTML utilisées pour garantir la sécurité du site

Vous retrouverez dans cette fiche des explications détaillées pour chacun de ces points de personnalisation.

1.2 Cas d'usages

Quelques cas d'usages typiques sont présentés ci-dessous sous forme de tutoriel.
Référez-vous à la documentation détaillée pour plus d'explications sur chacun des points de personnalisation utilisé.

Cette fiche sera systématiquement mise à jour pour référencer tout nouvel exemple ou tutoriel autour de la personnalisation de l'éditeur.

 

2. Insertion Unifiée

2.1 Présentation

La mécanique d'insertion unifiée permet de proposer à l'utilisateur l'insertion rapide de différents types de contenus.

Insertion Unifiée - Menu d'éditeur  

JPlatform 10 fournit en standard l'insertion : 

  • de lien vers publication et contenu,
  • de médias accessible dans l'explorateur de média,
  • de contenus internets tels que des images externes ou vidéos (YouTube, Dailymotion, Viméo).

Certains modules disponibles au catalogue Jalios s'intégrent dans cette mécanique pour proposer d'autres type de contenu : 

  • Module Evernote : insertion du contenu d'une note importer depuis Evernote
  • Module Google Drive : insertion d'un lien vers un document Google Drive
  • Module JGuide : insertion d'un Guide, consultable directement dans le contenu
  • Module WebChat : insertion de gif animé issu de la plateforme Giphy
  • ...

Insertion Unifiée - homepage  

2.2 Ajout d'un nouvel élément

Pour proposer à vos utilisateur l'insertion d'un nouveau type de contenu voici les étapes à suivre.

  1. Choisissez un identifiant alphanumérique unique pour décrire votre contenu.
    (Il s'agit d'un identifiant technique non affiché à l'utilisateur)
  2. Déclarez l'existence de votre nouvelle entrée dans les propriétés (à faire dans plugin.prop)
    1. Chemin du JSP d'insertion, relatif à la racine de la webapp :
      unified-insert.items.{id}.jsp
    2. Icône représentant votre fonctionnalité, à choisir parmis les glyphe icomoon ou glyphicon fourni en standard dans JPlatform.
      unified-insert.items.{id}.icon
    3. (optionnel) Ordre de votre fonctionnalité dans la liste.
      Valeur par défaut : 0
      Sauf si vous souhaitez absolument faire apparaître votre fonctionnalité à un endroit bien précis (premier, dernier ou avant un autre élément déjà ordonné), il est recommandé de ne pas renseigner cette propriété. Un tri lexicographique s'appliquera avec tous les autres éléments de même ordre (dans la langue courante).
      unified-insert.items.{id}.order
    4. (optionnel) Activation de votre fonctionnalité.
      Valeur par défaut : true (activé)
      Cette propriété permet de désactiver un élément non désiré.
      unified-insert.items.{id}.enabled
  3. Déclarez les propriétés de traduction destinées à l'affichage (à faire dans en.propfr.prop, etc)
    • Nom court, affiché dans le menu de la barre d'outil et dans la barre latérale gauche de la popup l'insertion unifiée
      unified-insert.items.{id}
    • Nom long, affiché dans la page d'accueil de la popup d'insertion unifiée lorsque que l'utilisateur n'a pas choisi d'élément précis (clic direct sur le bouton + de la barre d'outil)
      unified-insert.items.{id}.longtitle
    • (optionnel) Sous titre, affiché sous le nom long
      unified-insert.items.{id}.subtitle
     
  4. Développez le JSP qui s'affiche pour proposer l'insertion de votre contenu
    1. Inclusion obligatoire du JS "js/jalios/ux/jalios-unifiedinsert.js"
    2. Pour déclencher l'action d'insertion, 2 possibilités :
      1. Ajout, sur un bouton ou un lien, d'une classe (CSS) permettant de déclencher automatiquement l'action d'insertion voulue
        1. unifiedinsert-link avec attribut data-jalios-source="ID" , pour un lien vers publication
        2. unifiedinsert-media avec attribut data-jalios-source="ID ou URL du média", pour un media
      2. Invoquer en JavaScript les méthodes JavaScript documentées dans jalios-unifiedinsert.js, qui permet notamment d'insérer n'importe quel HTML

 

Exemple[Editeur Texte Riche] Proposer l'insertion d'un modèle de saisie via l'Insertion Unifiée

2.3 Retirer un élément

Si vous souhaitez masquer certains éléments de l'insertion unifiée, vous pouvez agir sur les éléments présentés aux utilisateurs en implémentant la classeUnifiedInsertPolicyFilter.

Exemple : 

Dans l'exemple suivant, l'insertion d'un contenu externe à partir de son URL est réservée aux administrateurs.

public class MyUnifiedInsertPolicyFilter extends BasicUnifiedInsertPolicyFilter {

  @Override
  public Set<MenuItem> updateMenuItemSet(InsertionContext context, Set<MenuItem> items) {
    if (context == null || !context.isAdmin()) {
       items.removeIf(m -> m.getId().equals("url"));
    }
    return items;
  }

}

 

A partir de JPlatform 10 SP2 (évolution JCMS-6586), l'objet InsertionContext permettra également de récupérer l'identifiant de la configuration wysiwyg du champ pour lequel on ajoute le menu d'insertion unifiée.
Cela permet de filtrer les éléments à présenter aux utilisateurs selon ce critère.

Exemple :

Dans l'exemple suivant, l'insertion d'un contenu externe à partir de son URL n'est proposé que dans les champs wysiwyg utilisant la configuration 'default'.

public class MyUnifiedInsertPolicyFilter extends BasicUnifiedInsertPolicyFilter {

  @Override
  public Set<MenuItem> updateMenuItemSet(InsertionContext context, Set<MenuItem> items) {
    if (context != null && !"default".equals(context.getConfigurationId())) {
      items.removeIf(m -> "url".equals(m.getId()));
    }
    return items;
  }

}

3. Configurations de l'éditeur TinyMCE

3.1 Présentation

La configuration d'un éditeur wysiwyg est décrite dans un fichier contenant du JavaScript et représentant la configuration transmise à l'éditeur TinyMCE. Cette configuration peut être enrichie par des syntaxes Jalios apportant une plus grande souplesse et une meilleure gestion des configurations.

Les configurations par défaut se trouvent dans le répertoire /WEB-INF/jalios/wysiwyg/ et sont déclarées par les propriétés suivantes : 

wysiwyg.configuration.default: /WEB-INF/jalios/wysiwyg/configuration-default.conf
wysiwyg.configuration.light: /WEB-INF/jalios/wysiwyg/configuration-light.conf

Chaque configuration wysiwyg est associée à un identifiant unique que l'on indique à 2 endroits : 

  1. dans la propriété permettant de déclarer la configuration et son fichier, sous la forme wysiwyg.configuration.myid: /chemin/vers/le/fichier.conf (où myid est l'identifiant retenu)
  2. dans le fichier de configuration de la forme suivante :
{
  'myid': {
    theme: 'modern',
    schema: "html5",
    entity_encoding : "raw",
    ...
  }
}

 

Par exemple, la configuration ayant pour identifiant default :

  1. est déclarée par la propriété wysiwyg.configuration.default: /WEB-INF/jalios/wysiwyg/configuration-default.conf,
  2. le contenu du fichier de configuration commence comme suit :
{
  'default': {
    theme: 'modern',
    schema: "html5",
    entity_encoding : "raw",
    ...
  }
}

 

Toutes les options de configuration de TinyMCE et des plugins TinyMCE, tels que theme, schema, entity_encodingplugins, toolbarformats, etc..., peuvent être déclarées dans les configuration wysiwyg. Pour savoir quelles options sont disponibles, voir la documentation TinyMCE.

3.2 Créer une nouvelle configuration wysiwyg

  • Déclarer la propriété dans le fichier plugin.prop d'un Module :
    wysiwyg.configuration.myconfig: /WEB-INF/plugins/MyPlugin/wysiwyg/configuration-myconfig.conf​
  • Dans le fichier de configuration configuration-myconfig.conf, définir la configuration associée à l'identifiant :
    {
      'myconfig': {
        theme: 'modern',
        schema: "html5",
        ...
      }
    }​
  • Pour utiliser cette nouvelle configuration sur un champ wysiwyg, il faut utiliser la méthode WysiwygSettings.configurationId(String) avec l'identifiant de la nouvelle configuration :
    <jalios:field name="myField" label="Field with config myconfig" value="<%= content %>">
      <jalios:control settings='<%= new WysiwygSettings().configurationId("myconfig") %>' />
    </jalios:field>​

3.3 Remplacer une configuration existante

Pour remplacer complètement une configuration existante, déclarer dans custom.prop(ou dans le fichier plugin.prop de votre module de site) une propriété de même nom et ayant comme valeur le chemin du nouveau fichier de configuration

Par exemple, si on souhaite remplacer la configuration ayant l'identifiant "light", déclarer dans custom.prop la propriété suivante pointant la nouvelle configuration :

wysiwyg.configuration.light: /WEB-INF/plugins/MyPlugin/wysiwyg/configuration-newlight.conf​

Tous les champs wysiwyg déclarer avec la configuration "light" utiliseront la nouvelle configuration configuration-newlight.conf.

3.4 Surcharger des options d'une configuration existante

Il est possible de remplacer seulement certaines options d'une configuration sans remplacer complètement la configuration d'origine.

Par exemple,

Si on souhaite remplacer les options suivantes de la configuration "default" :

  • L'option theme pour avoir un rendu différent de l'éditeur wysiwyg avec notre thème "mytheme" (par défaut theme: 'modern')
  • L'option  min_height pour avoir une hauteur minimum plus importante de "500px" (par défaut min _height: 300)

Il faut :

  • Déclarer une propriété commençant par wysiwyg.custom.configuration. suivi d'un identifiant unique (par exemple mycustomconfig) :
    wysiwyg.custom.configuration.mycustomconfig: /WEB-INF/plugins/MyPlugin/wysiwyg/configuration-mycustomconfig.conf​
  • Le fichier configuration-mycustomconfig.conf contient le contenu suivant :
    {
      'default': {
        theme: 'mytheme',
        min_height: 500
      }
    }​​

Il est possible d'appliquer cette surcharge sur l'ensemble des configurations existantes sans avoir besoin de déclarer un fichier de configuration par configuration existante. Pour cela, il faut utiliser l'identifiant spécial "@ALL" .

Si on reprend l'exemple précédent, il faut :

  • Déclarer la même propriété que dans l'exemple précédent
    wysiwyg.custom.configuration.mycustomconfig: /WEB-INF/plugins/MyPlugin/wysiwyg/configuration-mycustomconfig.conf​​
  • Le fichier configuration-mycustomconfig.conf contient le contenu suivant :
    {
      '@ALL': {
        theme: 'mytheme',
        min_height: 500
      }
    }​​

 

NOTE : Si on définit une option qui n'est pas présente dans la configuration à surcharger, cette option sera ajoutée.

3.5 Enrichir des options d'une configuration existante 

 Il est possible d'enrichir certaines options d'une configuration en y ajoutant une donnée manquante, sans pour autant les écraser complètement.

Cela est pratique dans le cas où on souhaite ajouter un nouveau plugin (option plugins), ajouter un nouveau bouton dans la toolbar de l'éditeur wysiwyg (option toolbar), ajouter un nouveau CSS utilisé par l'éditeur pour le rendu de son contenu (option content_css).

Dans les cas cités, on ne souhaite pas réécrire toute l'option qui peut être amené à changer lors de nouvelles versions de JPlatform, ou si d'autres plugins viennent s'ajouter également.

Par exemple,

Si on souhaite enrichir les options suivantes de la configuration "default" :

  • L'option plugins pour ajouter un nouveau plugin "myplugin"
  • L'option toolbar pour ajouter un nouveau bouton dans la toolbar provenant par exemple du plugin "myplugin"
  • L'option content_css pour ajouter un nouveau fichier CSS "myplugin.css" nécessaire par exemple au bon rendu du résultat du plugin "myplugin"

Il faut :

  • Déclarer une propriété commençant par wysiwyg.additional.configuration. suivi d'un identifiant unique (par exemple myadditionalconfig) :
    wysiwyg.additional.configuration.myadditionalconfig: /WEB-INF/plugins/MyPlugin/wysiwyg/configuration-myadditionalconfig.conf​
  • Le fichier configuration-myadditionalconfig.conf contient le contenu suivant :
    {
      'default': {
        plugins: '-myplugin', /* Ne pas oublier d'ajouter le '-' pour que TinyMCE ne charge lui même le plugin */
        toolbar: 'myplugin',
        content_css: '/plugins/MyPlugin/wysiwyg/plugins/myplugin/css/myplugin.css'
      }
    }​​

Le résultat est le suivant :

"default": {
  ...

  "content_css": ["css/csspacker.jsp?css=css%2Fjalios%2Fcore%2Ffonts%2Fwebfont-roboto.css&css=css%2Fjalios%2Fcore%2Ffont-icons.css", ... , "/plugins/MyPlugin/wysiwyg/plugins/myplugin/css/myplugin.css"],

  ...

  "plugins": "anchor,autolink,charmap, ... ,-myplugin",

  ...

  "toolbar": ["bullist numlist outdent indent | junifiedinsert | ... | myplugin "]
}

 

Il est possible d'appliquer cette enrichissement sur l'ensemble des configurations existantes sans avoir besoin de déclarer un fichier de configuration par configuration existante. Pour cela, il faut utiliser l'identifiant spécial "@ALL" .

Si on reprend l'exemple précédent, il faut :

  • Déclarer la même propriété que dans l'exemple précédent
    wysiwyg.additional.configuration.mycustomconfig: /WEB-INF/plugins/MyPlugin/wysiwyg/configuration-myadditionalconfig.conf​​
  • Le fichier configuration-mycustomconfig.conf contient le contenu suivant :
    {
      '@ALL': {
        plugins: '-myplugin', /* Ne pas oublier d'ajouter le '-' pour que TinyMCE ne charge lui même le plugin */
        toolbar: 'myplugin',
        content_css: '/plugins/MyPlugin/wysiwyg/plugins/myplugin/css/myplugin.css'
      }
    }​​

 

NOTE : Si on définit une option qui n'est pas présente dans la configuration à enrichir, cette option sera ajoutée.

3.6 Étendre une configuration 

Il est possible de créer une configuration wysiwyg qui étend une configuration existante.

Cela peut être utile quand on souhaite avoir une configuration assez similaire à une autre mais qui diffère seulement sur certains points. On ne souhaite pas modifier la configuration existante mais bien en avoir une nouvelle pour certains champs wysiwyg.

Si la configuration parente évolue, l'héritage permet de bénéficier automatiquement des changements dans la configuration qui l'étend.

  • Si une propriété existe dans la configuration parente et qu'elle existe aussi dans la configuration qui l'étend, la valeur finale sera celle définie dans la configuration qui étend
  • Si une propriété existe dans la configuration parente mais pas dans la configuration qui l'étend, la valeur finale sera celle définie dans la configuration parente
  • Si une propriété n'existe pas dans la configuration parente mais existe dans la configuration qui l'étend, la valeur finale sera celle définie dans la configuration qui étend

Imaginons le fichier de configuration parent suivant :

{
  'parent': {
    theme: 'inlite',
    height: 200,
    plugins: 'pluginparent',
    menubar: true
  }
}

Voici un autre fichier de configuration qui étend la configuration précédente :

{
  'config1::extends{"id": "parent"}': {
    document_base_url : "@raw{JcmsJsContext.getBaseUrl()}",
    height: 250,
    plugins: 'autoresize,contextmenu,code,image,link,media,table',
    all_prop1_custom: false,
    all_prop2_custom: "value 1",
    all_prop3_additional: false,
    all_prop4_additional: "value 1"
  }
}

Ceci serait équivalent à avoir une configuration contenant ce qui suit :

{
  'config1': {
    theme: 'inlite',
    height: 250,
    menubar: true,
    document_base_url : "@raw{JcmsJsContext.getBaseUrl()}",
    plugins: 'autoresize,contextmenu,code,image,link,media,table',
    all_prop1_custom: false,
    all_prop2_custom: "value 1",
    all_prop3_additional: false,
    all_prop4_additional: "value 1"
  }
}

 

A partir de JPlatform 10 SP2 (évolution JCMS-6582), il est possible d'utiliser le mot clé @super qui va permettre de récupérer la valeur de la configuration parente et d'y ajouter/concaténer une donnée supplémentaire.

En reprenant l'exemple précédent, avec la même configuration parent, et la configuration suivante (@super pour l'option plugins) : 

{
  'config1::extends{"id": "parent"}': {
    document_base_url : "@raw{JcmsJsContext.getBaseUrl()}",
    height: 250,
    plugins: '@super,autoresize,contextmenu,code,image,link,media,table',
    all_prop1_custom: false,
    all_prop2_custom: "value 1",
    all_prop3_additional: false,
    all_prop4_additional: "value 1"
  }
}

On obtient le résultat suivant (option plugins avec la valeur de la configuration parent concaténée avec la nouvelle valeur : 

{
  'config1': {
    theme: 'inlite',
    height: 250,
    menubar: true,
    document_base_url : "@raw{JcmsJsContext.getBaseUrl()}",
    plugins: 'pluginparent,autoresize,contextmenu,code,image,link,media,table',
    all_prop1_custom: false,
    all_prop2_custom: "value 1",
    all_prop3_additional: false,
    all_prop4_additional: "value 1"
  }
}

3.7 Inclure un fragment de configuration

Il est possible de créer des fragments de configuration de manière à rendre commun une partie de la configuration.

Par exemple, JPlatform possède un fragment de configuration pour l'utilisation des mentions utilisateurs. Au lieu de remettre le même contenu dans l'ensemble des configurations, un fichier est créé et inclue dans chaque configuration existante.

Ainsi, si la configuration sur les mentions était amené à changer, il n'y aura pas besoin de modifier les configurations existantes, mais seulement le fragment qui est inclut.

Pour définir un fragment :

  • Définir une propriété commençant par wysiwyg.fragment.configuration. suivi d'un identifiant unique (par exemple "mention") :
    wysiwyg.fragment.configuration.mention: /WEB-INF/jalios/wysiwyg/fragments/configuration-mention.conf​
  • Le fichier configuration-mention.conf contient le contenu suivant :
    mentions: {
      queryBy: 'fullName',
      insert: function(mbr) {
        if(mbr.fullname) {
          mbr.fullName = mbr.fullname;
        }
      }
    }​
  • Inclure ce fragment de configuration en utilisant la syntaxe ::include{'property': 'MY_PROPERTY_KEY'}MY_PROPERTY_KEY est la clé de propriété définissant le chemin de fichier de fragment de configuration
    {
      'default': {
        theme: 'modern',
        
        ...
        
        ::include{'property': 'wysiwyg.fragment.configuration.mention'},
    
        ...
      }
    }​

3.8 Inclure un contenu non interprété par le générateur de configuration wysiwyg

Il est possible d'inclure une information qu'on ne veut pas que le générateur de configuration wysiwyg essaie d'interpréter sous risque d'une erreur.

Par exemple, si on souhaite appeler une fonction JavaScript présent dans une autre librairie et que cette fonction doit être la valeur d'une des options :

{
  'default': {
    document_base_url: JcmsJsContext.getBaseUrl(),
  }
}

Ceci ne fonctionnera pas car JcmsJsContext.getBaseUrl() n'est pas accepté comme syntaxe valide JSON.

Si on met document_base_url: "JcmsJsContext.getBaseUrl()", ceci n'est pas bon non plus car la valeur est alors une String, la fonction n'est donc pas appelé.

Il est donc nécessaire d'utiliser la syntaxe @raw{...} qui va permettre d'inclure l'information de manière brut, sans aucune modification du générateur.

{
  'default': {
    document_base_url: "@raw{JcmsJsContext.getBaseUrl()}",
  }
}

Le résultat sera donc bien celui qu'on attend :

"default": {
   ...
   "document_base_url": JcmsJsContext.getBaseUrl(),
   ...
}

3.9 Inclure la valeur d'une propriété

Il est possible d'inclure la valeur d'une propriété. Pour cela, il faut inclure la clé de propriété qui sera évaluée avec la syntaxe ${...}.

{
  'default': {
    theme: "${jcms.wysiwyg.editor.theme}",
    ...
  }
}

Si la propriété jcms.wysiwyg.editor.theme est définie avec la valeur modern (déclarationjcms.wysiwyg.editor.theme: modern), on obtient le résultat suivant :

"default": {
  "theme": "modern",
}

 

Il est possible de combiner la syntaxe @raw{...} avec la syntaxe ${...} de manière à inclure la valeur d'une propriété qui ne doit pas être interprétée :

{
  'default': {
    ...
    height: "${jcms.wysiwyg.editor.height}",
    ...
  }
}

Si la propriété jcms.wysiwyg.editor.height est définie avec la valeur 300 (déclarationjcms.wysiwyg.editor.height: 300), on obtient le résultat suivant :

"default": {
  "height": 300,
}

3.10 Manipuler la configuration programmatiquement

Il est possible de modifier la configuration wysiwyg en implémentant com.jalios.jcms.policy.WysiwygPolicyFilter.updateWysiwygConfiguration(String).

Cela permet de réaliser des modifications sans avoir à définir de nouveau fichier de configuration et de traiter des cas qui ne sont pas réalisables quand on utilise la méthode avec la déclaration de propriété.

Principes : 

  • La méthode updateWysiwygConfiguration(String) reçoit en paramètre l'identifiant de la configuration que l'on peut modifier. Elle retourne une liste de mise à jour à effectuer déclarer sous la forme d'objet com.jalios.jcms.wysiwyg.WysiwygConfigurationUpdate.
  • Chaque objet WysiwygConfigurationUpdate définit une mise à jour à faire sur la configuration passée en paramètre.

Création d'une mise à jour :

  • Les objets WysiwygConfigurationUpdate s'instancient grâce à la méthode WysiwygConfigurationUpdate.newInstance(UpdateAction) qui reçoit en paramètre un objet WysiwygConfigurationUpdate.UpdateAction précisant la nature de la mise à jour.
  • Selon la nature de la mise à jour, il peut être nécessaire de passer d'autres données supplémentaires. Pour cela, on utilise la méthode WysiwygConfigurationUpdate.setData(String, Object) sur l'instance précédemment créée.

ExempleWysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_TOOLBAR).setData("index", 1)

Actions de mise à jour possibles :

Voici la liste des actions possibles de WysiwygConfigurationUpdate.UpdateAction avec les "Data key" (méthode setData(key, value) à transmettre) :

  • INSERT_PLUGIN : Insérer un nouveau plugin.
    • Data à définir : "plugin"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_PLUGIN).setData("plugin", "myplugin")
  • INSERT_TOOLBAR : Insérer une nouvelle barre d'outil
    • Data à définir : "index", "toolbar"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR).setData("index", "1").setData("toolbar", "undo redo copy")
  • INSERT_TOOLBAR_GROUP : Insérer un groupe d'élément dans une barre d'outil
    • Data à définir : "index", "toolbar-index", "group"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR_GROUP).setData("index", 0).setData("toolbar-index", 0).setData("group", "undo redo copy")
  • INSERT_TOOLBAR_ITEM_AFTER : Insérer un élément de barre d'outil après un autre
    • Data à définir : "item", "item-after"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR_ITEM_AFTER).setData("item", "redo").setData("item-after", "undo")
  • INSERT_TOOLBAR_ITEM_BEFORE : Insérer un élément de barre d'outil avant un autre
    • Data à définir : "item", "item-before"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR_ITEM_BEFORE).setData("item", "undo").setData("item-before", "redo")
  • REMOVE_PLUGIN : Supprimer le plugin spécifié.
    • Data à définir : "plugin"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_PLUGIN).setData("plugin", "myplugin")
  • REMOVE_TOOLBAR : Supprimer une barre d'outil
    • Data à définir : "index"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_TOOLBAR).setData("index", "1")
  • REMOVE_TOOLBAR_GROUP : Supprimer un groupe d'élément dans une barre d'outil
    • Data à définir : "index" (index du groupe), "toolbar-index" (index de la barre d'outil)
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_TOOLBAR_GROUP).setData("index", 1).setData("toolbar-index", 0)
  • REMOVE_TOOLBAR_ITEM : Supprimer un élément de barre d'outil
    • Data à définir : "item"
    • Usage : WysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_TOOLBAR_ITEM).setData("item", "aligncenter")

Voici un exemple d'implémentation faisant un certains nombre de mise à jour sur la configuration 'default' :

public class MyBasicWysiwygPolicyFilter extends BasicWysiwygPolicyFilter {
   @Override
   public List<WysiwygConfigurationUpdate> updateWysiwygConfiguration(String configId) {
     if (!"default".equals(configId)) {
       return null;
     }

     List<WysiwygConfigurationUpdate> list = new ArrayList<WysiwygConfigurationUpdate>();
     
     // Add a new toolbar item before the item 'undo'
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR_ITEM_BEFORE)
                                         .setData("item", "itembefore1").setData("item-before", "undo"));
     
     // Add a new toolbar item after the item 'undo'
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR_ITEM_AFTER)
                                         .setData("item", "itemafter1").setData("item-after", "undo"));
     
     if("config1".equals(configId)) {
       // Remove the item 'aligncenter' from the toolbar
       list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_TOOLBAR_ITEM).setData("item", "aligncenter"));
     }
     
     // Add a new toolbar at first
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR).setData("index", 0).setData("toolbar", "item1 item2 item3"));
     // Add a new toolbar at last
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR).setData("index", -1).setData("toolbar", "item7 item8 item9"));
     
     // Remove the second toolbar
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_TOOLBAR).setData("index", 1));
     
     // Add new item group in the first toolbar at the beginning
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR_GROUP)
                                         .setData("index", 0).setData("toolbar-index", 0).setData("group", "newitem1 newitem2"));
     // Add new item group in the second toolbar at the index 2 (3rd position)
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.INSERT_TOOLBAR_GROUP)
                                         .setData("index", 2).setData("toolbar-index", 1).setData("group", "newitem3 newitem4"));
     
     // Remove the first item group from the first toolbar
     list.add(WysiwygConfigurationUpdate.newInstance(UpdateAction.REMOVE_TOOLBAR_GROUP).setData("index", 0).setData("toolbar-index", 0));
     
     return list;
   }
 }

4. JHTML et rendu dynamique

4.1 Présentation

A partir de JPlatform 10, le format de stockage des champs texte riche est le JHTML : format HTML classique enrichi de balises techniques Jalios.

Avantages fonctionnels et techniques du JHTML

  • garantie d'un rendu dynamique et homogène dans l'espace (sur tout le site) :
    le rendu est effectuée à l'affichage (et non pas stocké dans le HTML) en utilisant les gabarits de la plateforme
  • garantie d'un rendu homogène dans le temps :
    • les contenus (document, image, media, publication, ...) sont toujours référencés à partir d'informations techniques constantes (id) plutôt que changeantes (filename)
    • le rendu utilise toujours les derniers gabarits ou rendus proposés sur la plateforme

Caractéristiques techniques du JHTML :

  • entièrement compatible avec le format HTML 5
    peut être parsé avec des API Java (comme JSoup) ou JavaScript 
  • Les tags JHTML utilisent la syntaxe suivante:
    • pour le nom des tags : jalios:tagname,
    • pour les attributs des tags : préfixés par data-jalios-
  • Le format utilisé par les champs texte (wiki ou wysiwyg),
  • Le balisage n'est jamais affiché à l'utilisateur (ni à l'édition, ni à l'affichage)

4.2 Balises JHTML standard

JPlatform 10 fournit en standard plusieurs balises JHTML pour assurer le rendu de certains éléments fréquemment utilisés

4.2.1 Lien vers données (Data, Publication, Contenu, Membre) - <jalios:link>

Permet l'affichage d'un lien vers une donnée quelconque du site.

  • Utilise toujours le titre/nom le plus récent si aucun titre n'est spécifié
  • Permet l'affichage des ttcard au survol du lien

Attributs supportés : 

  • data-jalios-id (requis) : identifiant de la donnée liée
  • data-jalios-title : texte à utiliser comme balise title sur le lien rendu
  • data-jalios-style : style CSS repris sur le lien lors de l'affichage

Exemple

<p>
Consultez l'article <jalios:link data-jalios-id="c_42"/> 
et téléchargez <jalios:link data-jalios-id="1234_DBFileDocument">ce <strong>super</strong> document</jalios:link>.
</p>

Consultez l'article JPlatform 10 : les principales nouveautés et téléchargez JPlatform 10 - Manuel d'installation et d'exploitation ce super manuel .

4.2.2 Affichage d'un média ou d'une publication - <jalios:media>

Permet l'affichage en ligne d'un média de la plateforme  (contenu, image, vidéo, ...) ou externe (à partir d'une URL).
Tous les médias et URL supportés par la mécanique des gabarits de media peuvent être affichés de cette façon. Par exemple, le module JGuide fournir un gabarit de rendu des guides permettant l'affichage de ceux-ci en ligne dans un contenu wysiwyg.

Attributs supportés : 

  • data-jalios-source (requis) : identifiant ou URL du média/contenu à afficher
  • data-jalios-width : largeur d'affichage
  • data-jalios-height : hauteur d'affichage
  • data-jalios-title :  texte à utiliser comme balise title lors du rendu pour les éléments qui le support (par exemple les images)
  • data-jalios-style : style CSS repris sur l'élément lors de l'affichage

Exemple : 

<p>Regardez cette vidéo ! <br/>
<jalios:media data-jalios-source="https://www.youtube.com/watch?v=dQw4w9WgXcQ"/></p>

Regardez cette vidéo !

 

4.2.3 Mention utilisateur - <jalios:mention>

Permet de mentionner un utilisateur.

  • Déclenche l'envoi d'une alerte de mention à l'utilisateur lors de la publication du contenu
  • Utilise toujours le nom le plus récent de l'utilisateur
  • Permet l'affichage des ttcard au survol du lien du membre

Attributs supportés : 

  • data-jalios-id(requis) : identifiant du membre mentionné

Exemple : 

<p>Qu'en penses tu <jalios:mention data-jalios-id="j_2"/> ?</p>

Qu'en penses tu  @Olivier Jaquemet ?

4.2.4 Affichage d'un message - <jalios:msg>

Permet l'affichage d'une zone de message

Attributs supportés : 

  • data-jalios-level (optionnel) : niveau de priorité du message. Les valeur supportées : 
    • danger
    • warning
    • info  (valeur par défaut)
    • success

Exemple : 

<jalios:msg data-jalios-level="success">Bravo pour cette belle réalisation !</jalios:msg>

4.2.5 Résumé d'un contenu - <jalios:abstract>

Permet la présentation d'un texte comme l'élément clé, résumé d'un contenu.
Le texte (HTML) de cette zone peut être extrait avec la méthode JHTMLUtils.getAbstract(String).
Principalement exploité par le module Wiki : la présence d'une zone résumé dans une fiche Wiki permet automatiquement la récupération du HTML de cette zone par tous les utilisateurs des APIs Publication.getAbstract(...), notamment pour l'affichage dans les gabarits de recherches.

Attributs supportés : aucun

Exemple : 

<jalios:abstract>Documentation des configurations et développements spécifiques possibles autour du Wysiwyg.</jalios:abstract>

Documentation des configurations et développements spécifiques possibles autour du Wysiwyg.

4.2.6 Table des matières - <jalios:toc>

Permet l'affichage, lors du rendu, d'une table des matières exploitant les en-tête (balises h1, h2, ... h6) du contenu.

Attributs supportés : 

  • data-jalios-level (optionnel, valeur par défaut: 6) :
    profondeur de la table des matières à générer (1 pour extraire les h1, 2 pour les h1 et h2, ...)
  • data-jalios-autonumber (optionnel, valeur par défaut : true)
    une numérotation automatique des en-têtes (1., 1.1, 1.2, 2.1, etc) doit-elle être générée ?

Exemple :

<jalios:toc data-jalios-level="3" data-jalios-autonumber="false"/>

4.2.7 Inclusion dynamique de gabarits d'affichage divers (galerie Web, liste de résultat, ...) - <jalios:include>

Permet l'affichage d'une zone rendu dynamiquement en Ajax en utilisant la mécanique de déclaration des includes wysiwyg décrite ci-dessous.

Attributs supportés : 

  • data-jalios-type (requis) :  type de l'inclusion à effectuer
    Les valeurs supportées sont tous les identifiants déclarés par les propriétés wysiwyg.include.{id}.jsp
    En standard :
    • query : pour l'affichage d'une liste de résultat
    • gallery : pour l'affichage d'une galerie d'image
  • data-jalios-params (généralement requis) : paramètres utilisés pour l'inclusion (sous forme de querystring)
    Dépend du type d'inclusion, en standard : 
    • pour l'inclusion de type query (liste de résultat) :
      • params : requête de recherche des contenus à lister (valeur retournée par QueryHandler.getQueryString())
      • max : nombre maximum de contenu à affiché
      • sort : tri à utilisé :
      • class : classe CSS à utiliser sur la balise li englobant les résultats
      • style : styles CSS à utiliser sur la balise li englobant les résultats
    • pour l'inclusion de type gallery (galerie d'image) :
      • query : requête de recherche des images à afficher (valeur retournée par QueryHandler.getQueryString())
      • cids : identifiants de catégories permettant d'affiner la requête de recherches des images
      • width / height : dimensions d'affichage des images

Exemple : 

<jalios:include  data-jalios-type="query" data-jalios-params="&amp;params=cids%3Djn1_261485&amp;sort=cdate&amp;max=50" />

 

Pour introduire votre propre type d'inclusion : 

  1. Choisissez un identifiant unique (exemple : pubInclude)
  2. Créez un nouveau type d'include JHTML en le déclarant en propriétés
    wysiwyg.include.{id}.enabled: true
    wysiwyg.include.{id}.jsp: path/to/rendering.jsp​
    Exemple
    wysiwyg.include.pubInclude.enabled: true
    wysiwyg.include.pubInclude.jsp: jcore/wysiwyg/wysiwygPubInclude.jsp​
  3. Créez votre JSP pour faire le rendu attendu.
    Pour notre exemple jcore/wysiwyg/wysiwygPubInclude.jsp est un copier/coller du fichier jcore/wiki/wikiInclude.jsp qui permettait, pour les champs wiki, d'inclure une publication avec son gabarit d'affichage standard.

4.3 Ajouter une balise JHTML

Pour bénéficier des avantages apportés par l'utilisation d'une balise JHTML ; rendu dynamique, homogène et constant dans le temps et l'espace, il vous est possible d'ajouter votre propre balise.

  • Client side : support à l'édition, (aspect le plus complexe du développement)
    l'insertion du contenu est proposé à l'utilisateur dans dans l'éditeur wysiwyg,
    le tag JHTML est conservé à l'édition
    • création d'un plugin TinyMCE dédié,
    • déclaration de ce plugin dans la configuration JPlatform
      wysiwyg.additional.configuration.mytinymceplugin: /WEB-INF/plugins/MyJPlatformPlugin/wysiwyg/configuration-mytinymceplugin.conf
      wysiwyg.plugins.mytinymceplugin: plugins/MyJPlatformPlugin/wysiwyg/plugins/mytinymceplugin/plugin.js​
    • dans le plugin TinyMCE (en simplifiant énormément les concepts de TinyMCE) : 
      c'est ici que le développement peut s'avérer complexe, il peut être utile de reprendre le code des plugins existants pour complétude,
      • au chargement (événement TinyMCE BeforeSetContent) : transformation du JHTML en HTML éditable présenté à l'utilisateur
      • à l'enregistrement (événement TinyMCE PostProcess) : transformation du HTML présenté en version JHTML
  • Server side :
    • à l'enregistrement : 
      déclarer des propriétés pour conserver le nouveau tag (et ses attributs supportés) lors du nettoyage HTML
      wysiwyg.sanitize-html.whitelist.mytag.enabled: true
      wysiwyg.sanitize-html.whitelist.mytag.tags: jalios:mytag[data-jalios-id|data-jalios-myattribute]
    • rendu à l'affichage
      • Création d'une WysiwygPolicyFilter implémentant  com.jalios.jcms.policy.WysiwygPolicyFilter.processJHTML(Document, Locale, WysiwygRenderingHints)
      • Extraction des tags et conversion sous une autre forme,
        Exemple fictif d'implémentation de processJHTML pour remplacer tous le tags jalios:mytag par une div :
        for (Element someElement :  JHTMLUtils.selectJHTML(document, "mytag")) {
          List<Node> childNodes = someElement .childNodes();
          if (childNodes == null || childNodes.isEmpty()) {
            abstractElement.remove();
            continue;
          }
          
          Element replacementDiv = document.createElement("div");
          someElement .replaceWith(replacementDiv );
        }

5. Configuration du Nettoyage HTML

Pour assurer la sécurité, JPlatform effectue un nettoyage du HTML soumis par les utilisateurs.
Certaines balises ou attributs HTML sont interdits et supprimés du contenu à l'enregistrement.

Si vous autorisez vos contributeurs à insérer des contenus utilisant du HTML avancé, (balises iframe, identifiants, classes ou styles avancés), vous devrez adapter les paramétrages de nettoyage pour vos usages. 

Plus d'information à ce sujet :