TLDR: Aller directement au résumé
Il est assez fréquent de devoir charger une feuille CSS, un script Javascript, … dans un plugin Dotclear. C’est faisable en utilisant le mécanisme de chargement en requête <URI>?pf=<ressource>
:
Exemple côté administration pour charger une feuille CSS et un script Javascript en utilisant :
echo '<link rel="stylesheet" type="text/css" href="index.php?pf=<plugin-folder>/[sub-folder/]file.css" />'; echo '<script type="text/javascript" src="index.php?pf=<plugin-folder>/[sub-folder/]file.js"></script>';
Et côté public en utilisant :
echo '<link rel="stylesheet" type="text/css" href="'.$core->blog->getQmarkURL().'pf=<plugin-folder>/[sub-folder/]file.css" />'; echo '<script type="text/javascript" src="'.$core->blog->getQmarkURL().'pf=<plugin-folder>/[sub-folder/]file.js"></script>';
À chaque fois que je mentionne côté administration il s’agit de l’affichage dans une page de l’administration, et idem pour le côté public, il s’agit bien sûr de l’affichage d’une page du blog.
Une autre façon de faire, permettant éventuellement une gestion plus fine du cache des navigateurs en intégrant la version (du plugin ou de Dotclear), est d’utiliser les fonctions dédiées.
Côté administration :
echo dcPage::cssLoad(urldecode(dcPage::getPF('<plugin-folder>/[sub-folder/]file.css'))); echo dcPage::jsLoad(urldecode(dcPage::getPF('<plugin-folder>/[sub-folder/]file.js')));
Et côté public :
echo dcUtils::cssLoad($core->blog->getPF('<plugin-folder>/[sub-folder/]file.css')); echo dcUtils::jsLoad($core->blog->getPF('<plugin-folder>/[sub-folder/]file.js'));
Les fonctions dcPage::jsLoad (côté admin) et dcUtils::jsLoad (côté public) acceptent un paramètre supplémentaire pour définir la version à utiliser.
Pour la première, si ce 2e argument est absent, la version de Dotclear sera ajoutée (ou un identifiant unique dans le cas d’une version de développement), ce qui permet de conserver dans le cache une version à jour du script.
Pour la seconde, utilisée côté public du blog, ce 2e argument, s’il est absent n’impliquera aucun ajout de version.
Voilà par conséquent ce que produiront les appels de fonction jsLoad sans ce 2e argument, côté administration :
<script type="text/javascript" src="index.php?pf=<plugin-folder>/[sub-folder/]file.js?v=2.8"></script>
Et côté public :
<script type="text/javascript" src="<blog-url>?pf=<plugin-folder>/[sub-folder/]file.js"></script>
Pour utiliser la version de votre plugin il suffit de fournir ce 2e argument[1], comme suit, côté administration :
echo dcPage::jsLoad(urldecode(dcPage::getPF('<plugin-folder>/[sub-folder/]file.js')),$core->getVersion('<plugin-id>'));
Et côté public :
echo dcUtils::jsLoad($core->blog->getPF('<plugin-folder>/[sub-folder/]file.js'),$core->getVersion('<plugin-id>'));
Ce qui donnera, côté administration, si on considère que la version du plugin est par exemple 1.2, côté administration :
<script type="text/javascript" src="index.php?pf=<plugin-folder>/[sub-folder/]file.js?v=1.2"></script>
Et côté public :
<script type="text/javascript" src="<blog-url>?pf=<plugin-folder>/[sub-folder/]file.js?v=1.2"></script>
Il existe un même mécanisme pour les fonctions dcPage::cssLoad (côté admin) et dcUtils::cssLoad (côté public) à la différence près que l’indication de la version se trouve en 3e argument puisque le 2e permet de préciser le « média » d’application de la feuille CSS, screen par défaut.
Pour résumer, côté admin, pour charger un fichier Javascript puis une feuille CSS :
echo dcPage::jsLoad(urldecode(dcPage::getPF('<plugin-folder>/[sub-folder/]file.js'))[,$core->getVersion('<plugin-id>')]); echo dcPage::cssLoad(urldecode(dcPage::getPF('<plugin-folder>/[sub-folder/]file.css'))[,'screen',$core->getVersion('<plugin-id>')]);
Et côté public, pour charger un fichier javascript puis une feuille CSS :
echo dcUtils::jsLoad($core->blog->getPF('<plugin-folder>/[sub-folder/]file.js')[,$core->getVersion('<plugin-id>')]); echo dcUtils::cssLoad($core->blog->getPF('<plugin-folder>/[sub-folder/]file.css')[,'screen',$core->getVersion('<plugin-id>')]);
Un petit bonus, qui va souvent de paire avec le chargement de scripts Javascript, est la façon de définir des variables Javascript en PHP, variables qui seront utilisées ensuite par votre script.
Pour insérer l’affectation d’une valeur pour une variable, côté administration, on utilise la fonction dcPage::jsVar, exemple :
echo '<script type="text/javascript">'."\n". "//<![CDATA[\n". dcPage::jsVar('my_first_var',__('My very first variable')). dcPage::jsVar('mY_second_var',0). "\n//]]>\n". "</script>\n";
Qui produira le code suivant, les valeurs sont « échappées » au passage :
<script type="text/javascript"> //<![CDATA[\n my_first_var = "My very first variable"; mY_second_var = "0"; //]]> </script>
Côté public, il existe une fonction un peu équivalente, qui permet la définition de variable javascript, dcUtils::jsVar, et qui différencie les types de valeur (chaîne de caractères ou pas) :
echo dcUtils::jsVar('my_first_var',__('My very first variable')). dcUtils::jsVar('mY_second_var',0).
Donnera, les chaines de caractères sont « échappées » au passage :
<script type="text/javascript"> //<![CDATA[\n var my_first_var = "My very first variable"; //]]> </script> <script type="text/javascript"> //<![CDATA[\n var mY_second_var = 0; //]]> </script>
Notez le mot-clé var en début de ligne, et la différence pour la valeur affectée à la seconde variable (0 au lieu de “0”).
Une fonction supplémentaire dcUtils::jsVars est disponible, toujours côté public, et permet l’insertion d’une liste de variables, transmise via un tableau associatif (nom de variable → valeur). Exemple, avec les deux mêmes variables :
echo dcUtils::jsVars(array( 'my_first_var' => __('My very first variable'), 'mY_second_var' => 0) ));
Donnera cette fois :
<script type="text/javascript"> //<![CDATA[\n var my_first_var = "My very first variable"; var mY_second_var = 0; //]]> </script>
Résumé
Attention, toutes les fonctions citées (dcPage::getPF, dcPage::jsLoad, dcPage::cssLoad, dcPage::jsVar) pour le côté administration sont disponibles à partir de la version 2.8 de Dotclear, et celles pour le côté public ($core->blog->getPF, dcUtils::jsLoad, dcUtils::cssLoad, dcUtils::jsVar et dcUtils::jsVars) ne le seront qu’à partir de la version 2.9 !
Objet | Côté administration | Côté public |
---|---|---|
URL d’une ressource (CSS, Js, …) | urldecode(dcPage::getPF(<chemin-ressource>)) * | $core->blog->getPF(<chemin-ressource>) |
Chargement d’un Js | echo dcPage::jsLoad(<URL de la ressource> [, <version>]) | echo dcUtils::jsLoad(<URL de la ressource> [, <version>]) |
Chargement d’une CSS | echo dcPage::cssLoad(<URL de la ressource> [,’screen’, <version>]) | echo dcUtils::cssLoad(<URL de la ressource> [,’screen’, <version>]) |
Affection d’une variable Js | echo dcPage::jsVar(<variable>,<valeur>) | - |
Définition d’une variable Js | - | echo dcUtils::jsVar(<variable>,<valeur>) |
Définition de plusieurs variables Js | - | echo dcUtils::jsVars(array(<variable> => <valeur>, …)) |
* : l’appel à la fonction urldecode est rendue nécessaire par la gestion des URLs d’administration qui sont fournies encodées.
Notez que tout ce qui concerne le côté public est également valable pour les thèmes, dès lors que c’est utilisé dans le fichier _public.php
(et/ou _prepend.php
), et idem côté administration quand c’est utilisé dans l’optionnelle configuration du thème (fichiers _config.php
, _prepend.php
).
À vos claviers…
Note
[1] Utiliser la version du plugin est commode, mais rien ne vous empêche de préciser n’importe quoi d’autre comme argument (date, …), en fonction de vos besoins.
1 De Philippe -
Et moi qui croyais être passé à côté… jusqu’à ce que je lise ton avertissement sur les versions à la fin du billet.
C’est une chouette amélioration, merci ;)
2 De Philippe -
PS : yapuka compléter la doc :P
3 De biou -
c’est juste ce qu’il me fallait ! Merci Franck ! :)
4 De Franck -
Zizir™ :-)
5 De Philippe -
Juste une question sur un vieux billet, je peux ici ?
Chouette !
Le code suivant ne valide pas en html5, il y a un warning sur l’attribut type qui n’est plus obligatoire
<script type="text/javascript">
Y aurait-il moyen de le supprimer dans la fonction dcUtils::jsLoad ?
Ou alors j’ignore le warning ?
6 De Franck -
Ah mais bien sûr Philippe, je vais faire le nécessaire côté Dotclear pour la 2.15 et dans mes éventuels plugins qui l’utiliseraient.
Merci pour le signalement !
7 De Franck -
Tu as une référence sur ce warning ? Parce que Mozilla a l’air de dire que ça ne devrait pas poser de problème de mettre ce type.
8 De mirovinben -
Ayant effectivement constaté ce warning ainsi que celui lié aux CSS
<style type="text/css">
via l’excellent W3C Markup Validation Service, j’avais commencé à réfléchir à faut-il/peut-on éviter cela ?
Résultat : quid des utilisateurs de thèmes tournant sous xHtml et non Html5 et qui utiliseraient des extensions ainsi “dé-warninguisées” ?
Du coup, j’ai préféré laisser en l’état.
9 De Franck -
Si je m’en réfère à la « norme » du W3C, le type n’est pas interdit, éventuellement optionnel dans certains cas.
Pour la balise
script
, voir ici, pour la balisestyle
, voir là.Don à mon humble avis, ce sont les validateurs qui sont vaguement foireux, dans ce cas, et ce ne serait pas la première fois ;-)
En particulier celui du W3C n’est pas si excellent que ça, en fait.
10 De Philippe -
Pour Mozilla, voir l’exemple donné :
https://developer.mozilla.org/fr/do...
;)
11 De Franck -
Certes, vu que le type “text/javascript” est celui qui est pris par défaut pour cette balise en HTML5 (ce qui est précisé dans la recommandation du W3C), mais du coup je ne comprends pas pourquoi le validateur gueule !