Premiers pas

Au chapitre précédent, nous avons établi les fondations de notre extension en définissant ses options et en donnant la possibilité à nos utilisateurs de les modifier au gré de leurs envies du moment.

Il est maintenant temps de nous attaquer à l’interface que nous allons leur proposer pour ajuster au sein de l’éditeur de WordPress les paramètres propres à une image.

Mais avant cela, pour ceux qui l’ignoreraient encore, il est bon de préciser que ledit éditeur comporte deux modes d’écriture :

  • Le premier, dit Visuel, repose sur tinyMCE. Il dispose d’une barre d’outils censés simplifier la mise en forme et tente autant que faire se peut de se rapprocher du principe WYSIWYG en dissimulant soigneusement au rédacteur le coté abscons et les contraintes habituelles du codage HTML. C’est avec lui que nous allons tenter de coopérer…
  • Le second, dit Texte, est autrement plus spartiate et l’écriture s’y effectue peu ou prou sous la forme d’un code HTML traditionnel.

À noter en passant qu’il n’est pas rare (et c’est une litote !) que le basculement en brute d’un mode à l’autre de l’éditeur génère une palanquée de problèmes et une désorganisation radicale de la mise en page… Nous veillerons à ne pas tomber dans ce piège.

Bref, en ce qui nous concerne et puisque notre extension est destinée à rendre la vie de nos utilisateurs plus rieuse en s’intégrant harmonieusement au mode Visuel de l’éditeur, il nous faut parvenir à la faire dialoguer avec tinyMCE, autrement dit, construire un plugin tinyMCE au cœur d’un plugin WordPress.

TinyMCE, c’est du javascript. Et donc, cela ne vous étonnera point, un plugin tinyMCE, c’est… du javascript aussi. Forcément !

Rendons-nous donc dans le répertoire admin/js pour y créer un fichier text-floating-image-tinyMCE.js réduit à sa plus simple expression :


Ceci fait et vite fait, il nous faut signaler à WordPress l’existence de notre plugin.

Comme d’habitude, l’opération s’effectue en deux temps : tout d’abord, une fonction add_tinymce_plugin() est définie dans la classe dédiée admin/class-text-floating-image-admin.php. Elle a la redoutable charge d’expliquer à WordPress que « hello ! coucou ! y’a un nouveau super plugin pour ton éditeur à toi que t’as que je t’invite à rencontrer là maintenant pas plus tard que tout de suite ».


Elle est ensuite accrochée (ben vi ! hook = crochet) à l’évènement mce_external_plugins dans la fonction define_admin_hooks() de notre classe dirigeante includes/class-text-floating-image.php.


Si vous vous rendez maintenant dans l’éditeur visuel de votre installation WordPress, vous devriez voir surgir à l’initialisation une joyeuse et pimpante boite de dialogue telle que nous l’avons définie dans admin/js/text-floating-image-tinyMCE.js.

Ajout d’un bouton dans la barre d’outils de tinyMCE

IconTextFloatingImageBig

Pour offrir un accès à notre future fenêtre de paramétrage, nous devons bien évidemment nous coltiner l’ajout d’un bouton dans la barre d’outils de tinyMCE.

Qui dit bouton, dit icône…

Et qui dit icône, dit image…

Et qui dit mieux ne dit pas moins…

Enfin bref ! Voici celle que j’ai construite de mes petites mains à moi par l’entremise d’un programme de dessin vectoriel d’une société d’édition plutôt connue…

Bon ! Mes proches sont d’ores et déjà au courant et vous l’êtes désormais vous aussi : je n’ai aucun talent graphique et un gout de chiottes (n’empêche que ce serait charitable à vous que d’en finir avec ce sourire sardonique que je devine sur votre visage moqueur malgré les écrans qui nous séparent).

Nonobstant, la chose réduite à quelques 20 pixels devrait malgré tout faire l’affaire pour une bête icone (téléchargeable ici pour celles et ceusses qui ne sont pas dégoûtés).

Le boilerplate sur lequel nous avons choisi de nous reposer ne prévoit pas de tiroir où ranger les images. Rien ne nous empêche cependant de suppléer cette absence comme des grandes personnes que nous sommes. Glissons donc sans plus de retenue cette foutue icône dans un dossier img que nous créons à la racine du répertoire admin.

À première vue, il semblerait qu’un petit tour dans l’austère documentation de tinyMCE suffise à nous donner la marche à suivre quant à l’insertion de notre bouton dans la barre d’outils. Selon cette source, nous pourrions nous contenter pour atteindre notre but de quelque chose du genre :


Vous constaterez par vous même avec la déception qui va avec qu’on dirait bien que cela ne suffit pas franchement. On a beau cherché, écarquillé les mirettes, sonder, creuser, fouiner, fouiller, fourrager et tout et tout, aucune trace de notre bouton chéri à nous nulle part.

Faut dire que WordPress est parfois du genre pointilleux rond-de-cuir et n’apprécie pas forcément qu’on tente comme ça d’introduire dans son dos des trucs qu’il n’aurait pas validé de par lui-même. Le fait est que, tout à la fois pour le satisfaire et parvenir à nos fins, il nous faut encore une fois passer par la voie hook. En même temps, au point où nous en sommes, nous n’allons pas rechigner pour si peu d’autant que la procédure n’a (presque) plus de secret pour nous.

Et d’un rapide petit insert dans la fonction define_admin_hooks() de includes/class-text-floating-image.php :


Et d’un autre dans admin/class-text-floating-image-admin.php :


Eh ben voilà ! On l’a notre bouton !

Euh… Je ne voudrais pas froidement doucher votre enthousiasme mais, maintenant qu’il est là et bien là, il ne nous reste plus qu’à l’améliorer : nous nous sommes en effet interdit de rendre notre plugin accessible aux images qui ne respectent pas les quatre règles édictées ici. Face à ce genre de situation, il sera donc judicieux de désactiver notre bouton. Par ailleurs, puisque les boutons de la barre d’outils sont dotés d’un état dit active (ils sont alors agrémentés d’une fine bordure grise), nous en profiterons pour attribuer cet état à notre bouton dès lors qu’une image d’ores et déjà traitée par notre extension sera sélectionnée. Dans ce cas précis, nous prendrons soin par ailleurs de désactiver les boutons qui gèrent l’alignement.

Les moins attentifs d’entre vous ne manqueront pas de se demander comment on pourrait deviner qu’une image est ou n’est pas affectée par notre plugin. Ceux qui suivent leur expliqueront doctement que, comme évoqué ici-même, dès lors que notre extension est appliquée à une image, ladite image se trouve pourvue d’un attribut data-text_floating_image porteur d’un identifiant unique. Et que donc réciproquement, si une image porte l’attribut data-text_floating_image, c’est qu’elle est prise en charge par notre plugin.

Pour mener à bien notre présente et délicate mission, nous utiliserons l’événement onPostRender, qui tel le cri d’effroi poussé par le nouveau né lorsqu’il découvre notre monde, est éructé par notre bouton lui-même aussitôt qu’il en a fini d’apparaître. Cet événement va nous permettre d’obtenir une référence audit bouton via this, référence que nous nous empresserons d’affecter à une variable que nous pourrons invoquer tout à loisir et à tout moment par ailleurs. Et tout particulièrement dans notre réponse à l’événement NodeChange de l’éditeur, lequel se produit à chaque nouvelle sélection. Oui, c’est totalement tordu mais c’est aussi le seul moyen que j’ai pu trouver pour réaliser la chose et autant dire que je ne l’ai pas déniché tout seul (voir par exemple ici et ou bien encore ).

Retour donc dans admin/js/text-floating-image-tinyMCE.js :


Je vous laisse étudier, tester et re-tester l’ensemble jusqu’à plus soif…

Récupération des options enregistrées

Si nous nous sommes échinés à proposer des options modifiables à nos utilisateurs, ce n’est pas pour les laisser pourrir dans leur coin. Et s’il y a bien un endroit où elles vont pouvoir se rendre utiles, c’est dans la fenêtre de paramétrage que nous n’allons pas tarder à construire.

Le petit problème, c’est que ces options sont proprement rangées dans la base de données de maître WordPress et que pour pouvoir y accéder, il nous faut causer php. Or, pas de chance, nous œuvrons actuellement dans un fichier javascript

Il nous faut donc vaillamment construire de nos petites mains agiles un pont entre ces deux mondes.

La technique généralement utilisée dans ce genre de problématique consiste à s’appuyer sur le hook admin_head-post.php (en bref, une extension du hook admin_head qui ne se déclenche que lorsque l’on édite une page ou un article) pour écrire un bout de javascript dans l’en-tête de la page d’édition. Le petit souci de ce hook, c’est qu’il demeure désespérément au rang des grands absents si on crée un nouveau post. Dans ce cas précis, c’est sur son petit cousin admin_head-post-new.php qu’il faut se reposer.

Quoi qu’il en soit, la pratique devrait vous éclairer bien mieux que de plus longs et verbeux discours. Dans la classe admin/class-text-floating-image-admin.php, nous créons la fonction pass_options_to_tinyMCE() que voici :


Et nous revenons une fois de plus au sein de la fonction define_admin_hooks() de notre classe dirigeante includes/class-text-floating-image.php :


Si vous ouvrez votre backend de manière à créer ou modifier une page ou un article et que vous fouillez un peu les entrailles de la bête dans l’inspecteur de votre navigateur favori, vous devriez désormais voir figurer notre nouveau script dans l’en-tête. Vous constaterez par ailleurs en naviguant dans les diverses autres sections du tableau de bord que ce même script en est absent. À croire que nous sommes effectivement parvenus à nos fins !

Création de la fenêtre de paramétrage

Plus rien ne semble plus nous retenir de nous attaquer à la construction de notre fenêtre de paramétrage.

Nous l’avons vu, celle-ci sera affichée suite au clic sur notre bouton judicieusement inséré dans la barre d’outils de tinyMCE. Cependant, si l’image est incluse dans un bloc comprenant du texte, on demande au préalable l’autorisation de procéder à son isolation dans un bloc indépendant. Si l’utilisateur nous oppose son refus, on arrête là tout en restant bons amis. S’il accepte notre proposition même pas malhonnête, on lance la procédure soigneusement empaquetée dans une fonction main() qui comme son nom l’indique se charge du gros du boulot. Si d’aventure l’image réside d’ores et déjà en solitaire dans un bloc à elle seule dédiée, on passe à la fonction main() sans autre forme de procès.

textfloatingimagepopup

Notre fenêtre comportera les options suivantes :

  • Un champ pour la largeur de l’image en pourcentage.
  • Une case à cocher pour spécifier son alignement.
  • Un champ pour sa marge à gauche.
  • Un autre pour sa marge à droite.
  • Un champ supplémentaire que la pratique m’a incité à ajouter afin de pouvoir spécifier l’espace à ménager après l’ensemble image/texte : le fait est que si nous faisons se succéder deux blocs d’alignement et que, pour chacun d’eux, le texte entoure l’image,  le résultat apparaît comme un seul gros bloc continu d’aspect potentiellement indigeste. Ce nouveau paramètre permet de redonner un peu d’air à l’ensemble en insérant un espace entre les deux blocs. Concrètement, la valeur spécifiée dans ce champs définira la hauteur de l’élément stylé en clear:both que nous introduirons à la suite du dernier bloc de texte pour clore notre effet.
  • Un bouton Reset pour rendre aux champs définis ci-dessus leur valeur par défaut.
  • Un bouton permettant le cas échéant de réduire d’un bloc la sélection de texte.
  • Un bouton + qui assure au contraire et quand c’est possible l’augmentation de la sélection de texte d’un bloc.
  • Un bouton OK pour valider le tout.
  • Un bouton Annuler pour… euh… pour quoi faire ?, hein !, à votre avis ?

La largeur, l’alignement et les marges définies par notre utilisateur seront stockées comme prévu dans un attribut data-text_floating_image-style porté par l’image. Pour des raisons de commodités de codage, la valeur de l’espace à ménager après notre ensemble sera elle enregistrée dans un attribut dédié, data-text_floating_image-after, lui aussi porté par l’image.

Que voici donc le code abondamment commenté issu de mes cogitations :


Le tableau serait incomplet sans les quelques lignes que nous rajoutons à notre feuille de style :


 

Bon, j’avoue : voilà qui fait encore un gros pavé à digérer !

En même temps, au vu des mentions TODO, vous vous doutez que nous ne sommes pas au bout de nos peines.

Nous allons néanmoins nous arrêter là pour aujourd’hui, respirer un bon bol d’air, nous aérer la tête et le reste avant de songer à la suite et de nous rapprocher petits pas à petits pas du but que nous nous sommes fixés…