Les crayons

Un plugin pour une édition directe sur le site public

Ce plugin permet d’éditer les contenus sur les pages publiques du site, sans passer par l’espace privé de SPIP.

Le paramétrage côté squelettes est des plus simples : il repose sur la classe #EDIT{...} adjointe aux éléments qu’on veut rendre modifiables.

Résumé

Après l’activation du plugin, les contenus peuvent être directement édités « en place » sur les pages publiques du site, par les personnes autorisées.

Cela demande de préparer vos squelettes pour les rendre compatibles avec ce plugin (à noter : c’est le cas de la plupart des squelettes distribués sur SPIP-Contrib). Le principe est simple : un bloc est éditable s’il contient la classe crayon objet-champ-id. Une balise #EDIT{} facilite encore l’écriture. En fait, pour permettre d’éditer le titre d’un article, il suffit de remplacer dans le squelette de la page article.html, la ligne (par exemple) :

<h1>#TITRE</h1>

par :

<h1 class="crayon article-titre-#ID_ARTICLE">#TITRE</h1>

ou encore, plus simplement :

<h1 class="#EDIT{titre}">#TITRE</h1>

Autre exemple, pour rendre « crayonnable » le texte d’un article, transformer :

[<div class="texte">(#TEXTE|image_reduire{520,0})</div>]

en :

[<div class="#EDIT{texte} texte">(#TEXTE|image_reduire{520,0})</div>]

Les pages concernées doivent obligatoirement comporter une balise </head>, écrit précisément de cette façon (lettres minuscules).

Fonctionnement

Fabrication de la page côté serveur

Lors du chargement d’une page, le plugin agit dans le pipeline affichage_final.

Il vérifie alors :

  • si l’utilisateur est identifié
  • si la page contient au moins une chaîne de caractères “crayon xxxx­-yyyy-nn”,
  • et si l’utilisateur possède des droits sur au moins un des éléments ainsi marqués

Le cas échéant, il insère dans le <head> de la page le script externe crayons.js ainsi que des données de configuration ; le script s’exécute à la fin du chargement de la page, et vérifie à intervalles réguliers si de nouveaux crayons sont disponibles, de façon à les activer en cas de besoin.


Chargement par le navigateur

Lorsque la page finit de se charger (et si le visiteur a des droits d’édition sur les crayons présents dans la page), le script crayons.js sélectionne tous les éléments possédant la classe crayon type­-champ-id, et si ils sont autorisés pour l’utilisateur inscrit, leur adjoint une image clicable (un crayon) et leur ajoute la classe crayon-autorise pour indiquer qu’ils sont « éditables ».

Un clic sur cette image, mais aussi un double-clic sur l’élément lui-même, provoquent l’activation du formulaire d’édition.


Activation du crayon

Un click sur le « crayon » (ou un double-clic sur l’élément) déclenche une requête vers le serveur, qui renvoie le formulaire de modification qui va « remplacer » l’élément affiché.

La requête spécifie au serveur le « type », le « champ » et l’« id » pour lesquels le formulaire est demandé.

Après vérification de l’existence des données et des droits sur celles-ci, le serveur renvoie le formulaire (sous forme de données javascript, au format JSON). Le type et les dimensions du champs sont déterminés d’après sa nature et la place réservée à l’élément. Il contient le source brut du texte, comme lorsque on édite depuis l’espace privé ; la police, la taille et la couleur des caractères sont préservées.

crayon.js associe ce formulaire à l’élément puis "cache" ce dernier.

L’utilisateur peut maintenant modifier les données.

Attention : l’affichage final ne peut être réalisé que par le serveur, un click en dehors de la zone d’entrée après des modifications affichera à nouveau le contenu originel.
Dans ce cas, une roue dentée vous signale que vous avez introduit une modification. Click sur le bouton ou double-click sur l’élément vous y ramène, elles ne sont pas perdues.
Si vous abandonnez cependant la page, un dernier rappel vous propose de sauvegarder.


Sauvegarde

Le formulaire possède une série de boutons/touches associées :

  • OK (ainsi que la touche Entrée [1]) permet de sauvegarder,
  • Annuler (ainsi que la touche Escape) abandonne toute mise à jour,
  • Un clic en dehors des zones de saisie cache ces zones et revient à l’affichage initial.

Il contient aussi des identificateurs et des clés associés aux données.

Le formulaire est soumis en POST par ajaxForm donc asynchrone. Sur réception, le serveur :

  • analyse les données soumises, leur cohérence et leur actualité (afin d’annuler l’envoi si les données ont été entre-temps modifiées par ailleurs).
  • vérifie une nouvelle fois les droits d’édition.
  • appelle les procédures internes de SPIP pour mettre à jour les données.
  • renvoie une vue des données modifiées, et déclenche les comportements javascript précisés par la fonction onAjaxLoad de SPIP.

Le système alimente notamment l’historique des modifications, de la même façon que l’espace privé.

Configuration

Le plugin propose plusieurs options, activables via le plugin CFG ; notamment :
-  un message si on confirme OK mais que rien n’est changé ;
-  une alerte permettant de sauvegarder les modifications si on abandonne la page alors qu’un texte est en cours d’édition ;
-  l’activation de la barre typographique ;
-  des couleurs permettant de mieux repérer les zones modifiables.

À noter : si le plugin est absent ou désactivé, la balise #EDIT{...} renvoie une chaîne vide ; cela permet donc de « crayonner » des squelettes même si l’on décide finalement de ne pas utiliser le plugin

Utilisation étendue

Toutes les tables standard de SPIP (articles, brèves, rubriques, etc.) sont gérées, y compris les forums et les signatures de pétition (mais, pour ces deux dernières, il faut utiliser le plugin Autorité pour permettre des modifications) ; pour chacune de ces tables, tous les champs de type « ligne » (titre, soustitre etc), ou « texte » (texte, chapo, descriptif...) sont crayonnables.

On peut également éditer les logos avec le crayon #EDIT{logo} ; un réglage permet de redimensionner ces logos à la volée lors de l’upload.

Les documents sont modifiables avec le crayon #EDIT{fichier} : le nouveau document vient remplacer l’ancien et sa taille, hauteur et largeur sont mises à jour. (NB : pas encore compatible documents distants).

Enfin, à partir de spip 2, on peut éditer les champs extra.

À noter :

  • Les crayons fonctionnent avec n’importe quelle table — à condition que cette table possède une clé primaire (numérique) qui s’appelle id_xxx, où le nom de la table est spip_xxxs.
  • pour la table spip_meta qui ne propose pas ce type d’index numérique, il faut utiliser la balise #EDIT d’une manière un peu différente en préfixant le champs à éditer par meta-, par exemple [2] :
    #EDIT{meta-descriptif_site}
    
  • pour éditer une valeur de configuration de plugin, on utilise la même syntaxe en ajoutant « meta » ; Par exemple pour éditer un champs de configuration adresse pour un plugin dont le préfixe est croque :
    [<div class="inner #EDIT{meta-croque/adresse}">(#CONFIG{croque/adresse})</div>]
    
  • Si un texte « crayonnable » est un champ MySQL MEDIUMTEXT ou plus long, les crayons affichent un TEXTAREA, et sinon, un INPUT.
  • Seuls les admins complets peuvent ainsi crayonner des textes provenant d’une table non-SPIP.

Editions simultanées de plusieurs champs

L’obtention du formulaire d’édition (« contrôleurs ») ainsi que la vue obtenue en retour sont surchargeables, par de simples squelettes (voir les exemples dans les répertoires controleurs/ et vues/ du plugin).

Ces formulaires peuvent travailler en parallèle sur plusieurs champs d’un enregistrement (article), voire plusieurs enregistrements d’une même table ou de tables différentes [3] : il y a là de quoi faire des interfaces d’édition spécialisées et très efficaces.

Comme toujours, contributrices et contributeurs sont bienvenus !

Notes

[1Ainsi que, sur Mac, la touche ctrl-S, et sur PC les touches alt-S ou F8, ou encore la combinaison MAJ-entrée.

[2Ceci est valable depuis la version 1.6.1 du plugin. Pour les versions précédentes la syntaxe est différente. Il faut insérer manuellement la class dans le code suivant la syntaxe meta-valeur-XXX où XXX représente le nom de la propriété à modifier. Par exemple pour modifier le nom du site (propriété : nom_site) on pourrait faire :

<h1 class="crayon meta-valeur-nom_site">#NOM_SITE_SPIP</h1>

[3Par exemple pour ouvrir en édition l’ensemble des champs descriptifs d’une adresse postale.

Debug : Les crayons ont un mode de débug activable en mettant dans mes_options.php la ligne suivante :

define('_DEBUG_CRAYONS', true);

Ce code ralentit un peu le fonctionnement, puisque le script est rechargé à chaque fois, mais facilite le repérage de bugs et le développement de nouvelles fonctionnalités.

Voir aussi : Doc complémentaire

Discussion

303 discussions

  • 1

    Bonjour

    Je viens de mettre à jour le CRAYON et je vois que les jolis pictogrammes d’avant ont été remplacé par des boutons textuels. Qui du coup prennent plus de place.

    J’utilise le CRAYON dans un tableau construit à partir d’une table en bdd. Cela me permet à jour la table directement à partir de l’espace public. Mais mes cellules étant assez petites, les boutons du crayons recouvrent tout l’input (dont la largeur est fixe à 170px). Avec les picto cela passait.

    1) Est-il possible de revenir sur les pictos ?

    2) Est-il possible de changer le css ? Par exemple, si je met un « top:30px » sur la class crayon-boutons, cela descent les 2 boutons du crayon sous l’input qui devient alors éditable.

    • Yep, même chose chez moi... C’est une optimisation pour tactile qui « dégage » sur mon tableau crayonnable :-p.

      La modif en question est celle-ci : http://zone.spip.org/trac/spip-zone.... Tu peux récupérer le look ancien en mettant les lignes 8 à 10 supprimées dans squelettes/css/perso.css par exemple.

      .crayon-boutons button { width: 40px; height: 20px; border: 0; text-indent: -3000em; cursor: pointer;display:block;float:left; } 
      .crayon-boutons .crayon-submit { background: transparent url(images/ok.png) right top no-repeat; float:right;padding:0;} 
      .crayon-boutons .crayon-cancel { background: transparent url(images/cancel.png) center top no-repeat;padding:0;margin-right:10px;} 

    Répondre à ce message

  • sur SPIP 3 avec les URLs arbos, le crayon se casse
    le chargement http://tld.com/sous-repertoire-spip/fr/test/article/spip.php?page=crayons.js&callback=startCrayons provoque une 404

    j’ai corrigé le problème en éditant crayons_fonctions.php ligne 90
            $jsFile = generer_url_public('crayons.js);
    par
            $jsFile = generer_url_public('crayons.js','',false,false);

    Répondre à ce message

  • 1
    PasKalou

    Bonjour, retour de bug

    après une mise à jour (via SVN), tout à planté.

    PHP Fatal error : Cannot redeclare balise_edit_config_dist() (previously declared in /.../plugins/auto/cfg/cfg_fonctions.php:86) in /.../plugins/Crayons/crayons_fonctions.php on line 297

    À la vue du SVN LOG, il semble que le bug a été introduit par la version 69369.

    Un retour à la version r67517 a tout corrigé.

    Bonne journée,
    Pascal

    Répondre à ce message

  • 5

    Bonjour,

    J’essaie d’installer le plugin crayon 1.14.0 sur un spip 3.0.5 mais j’obtiens à chaque fois une erreur :

    Fatal error : Cannot redeclare balise_edit_config_dist() (previously declared in /journal/plugins/auto/cfg/cfg_fonctions.php:86) in /journal/plugins/auto/crayons/v1.14.0/crayons_fonctions.php on line 297

    Si je supprime par FTP le dossier crayons j’ai de nouveau accès à mon site.
    D’où vient le problème ?

    Merci.

    • Bon je l’ai réinstallé aujourd’hui et ça refonctionne.

      Bizarre.

    • Bonjour,

      j’ai le même souci sur SPIP 2.1.19. Cela fait 3 ou 4 fois que j’installe et désinstalle le plugin, à chaque fois que j’active le plugin j’ai l’erreur :

      Fatal error : Cannot redeclare balise_edit_config_dist() (previously declared in (...)/spip/plugins/crayons/crayons_fonctions.php:276) in (...)/spip/plugins/cfg/cfg_fonctions.php on line 94

      J’ai désactivé tous mes plugins, puis réactivé le plugin Crayons, aucun souci. Mais en réactivant le plugin CFG, j’ai à nouveau le bug.

      Y aurait-il une incompatibilité entre Crayons et CFG ?

    • Réponse obtenus sur la liste...

      Mon plugin CFG n’était pas à jour... J’avais la version 1.16.0, or la dernière version de CFG (à ce jour) est 1.16.1, elle corrige ce problème.

    • Bonjour,

      Pour moi, le problème persiste, malgré la mise à jour du plugin CFG (SPIP 1.9.2p : je sais, c’est une vieillerie...) : manifestement, « crayons/crayons_fonctions.php » est lu APRÈS « cfg/cfg_fonctions.php ». Or si « cfg » vérifie bien que balise_EDIT_CONFIG_dist($p) n’existe pas pour déclarer la fonction, « crayons » ne prend pas cette précaution !

      La fonction est donc déclarée par « cfg » (puisqu’elle n’existe pas encore) et elle est RE-déclarée par « crayons », qui ne teste pas son existence... D’où l’erreur...

    • PasKalou

      Regarde mon commentaire (j’aurai du le soumettre ici en fait) :
      http://contrib.spip.net/Les-crayons#forum465832

      ++
      Pascal

    Répondre à ce message

  • 1

    Bonjour

    Lorsque j’édite au crayon le titre d’un forum, il y a bien les boutons OK et X qui sont affichés, mais il n’y a pas d’input.

    Au début, je pensais à un bête problème de CSS. Mais j’ai regardé le source généré. Il y a bien des inputs, mais tous en hidden. Et aucun ne correspond au titre.

    Pourtant, le texte du forum est éditable correctement lui.

    Ci-dessous, un bout du squelette :

    <BOUCLE_forums(FORUMS) {id_rubrique ?}{id_article ?}{id_breve ?}{id_syndic ?}{par date}{inverse}{pagination 10}>
        <li class="forum-fil">
            <div class="forum-message">
                <div class="forum-chapo" id="forum#ID_FORUM-header">
                    [(#REM) Infos Auteur
                    --------------------]
                    <BOUCLE_TESTAUTEUR1(CONDITION) {si #ID_AUTEUR|>{0}}>
                        [(#REM) Auteur enregistré]
                       <BOUCLE_AUTEUR1(AUTEURS){id_auteur=#ID_AUTEUR}{tout}>
                           [...]
    
                           <h2 class="forum-titre"><a class="#EDIT{titre}" href="#forum#ID_FORUM" name="forum#ID_FORUM" id="forum#ID_FORUM">#TITRE</a></h2>

    On voit que le #EDITtitre se trouve à deux niveaux de boucle plus loin. Peut-être une explication ?

    Répondre à ce message

  • Fady Pierre-Philippe

    Bonjour,

    je rencontre une difficulté avec mes controleurs de saisie date.

    le format date MySql est aaaa-mm-jj hh:mm:ss
    et j’aimerais pouvoir rentrer une date au format jj/mm/aaaa

    Je pensais pouvoir m’en sortir avec un composant jQuery datePicker, mais impossible de le mettre en place. Il semblerait que le javascript ne soit pas accepté dans les controleurs ?

    auriez vous une solution à me proposer ?

    d’avance merci,

    Pierre-Philippe

    Répondre à ce message

  • juste une remarque : le logo ici ne correspond pas à celui sur http://plugin.spip.net/crayons.

    Quel est l’officiel ?

    Répondre à ce message

  • Juste un retour d’expérience qui m’a grignoté 3 bonnes heures ce matin et au moins une de plus avec Marcimat (que je remercie encore ici) :

    Je n’avais plus de crayons accessible malgré des balises correctement placées dans mon squelette, je vous livre donc le début du code (juste le head, c’est suffisant) et la solution :

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="#LANG" lang="#LANG" dir="#LANG_DIR">
    <head>
    [(#SEO_META_TAGS)]
    [(#SEO_GWT)]
    <!--[(#SEO_URL)]-->
    
    <INCLURE{fond=inclure/head_sommaire_orange} />
    </head>

    En fait, les crayons étaient mis « en commentaire », il faut pour que cela fonctionne ne PAS mettre de commentaire au premier lien (balise html <link...> au sein du <head>.

    SOLUTION : il faut enlever les commentaires de [(#SEO_URL)]... ce qui donnera :

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="#LANG" lang="#LANG" dir="#LANG_DIR">
    <head>
    [(#SEO_META_TAGS)]
    [(#SEO_GWT)]
    [(#SEO_URL)]
    
    <INCLURE{fond=inclure/head_sommaire_orange} />
    </head>

    Et hop, réapparition des crayons au recalcul :)

    En résumé : si le premier <link> est commenté, crayon plante - A savoir !
    Pour en savoir plus voir le code du plugin : http://zone.spip.org/trac/spip-zone...

    Répondre à ce message

  • 2

    Bonjour,

    J’ai installé le plugin crayons sur un spip 3.01[19436]

    il ne fonctionne pas, j’ai ce message d’erreur dans la console de Safari :


    TypeError : ’undefined’ is not a function (evaluating ’$(’.crayon:not(.crayon-init)’)
    .live(’mouseover’,function()
    $(this)
    .addClass(’crayon-init’)
    .filter(configCrayons.droits)
    .initcrayon()
    .trigger(’mouseover’)
    )’)


    Quelqu’un aurait une idée ?

    • Petites précisions, le plugin fonctionne normalement avec les squelettes-dist
      Donc je dois avoir quelquechose au niveau de mes css ( je pense) qui coince, mais quoi ?
      Apparemment pas de conflit JS....

    • Problème résolu !
      Conflit Jquery :
      J’avais un jquery.js qui trainait dans le repertoire js de mes squelettes.
      je l’ai supprimé et tout fonctionne....!

    Répondre à ce message

  • 2

    Bonjour,

    J’ai une erreur dans l’utilisation des crayons avec Internet Explorer 8.
    Un site en 2.0.19, avec uniquement le plugin « crayons » activé, quand je modifie un titre d’article depuis le site public avec les crayons et que je valide la modification, le bloc passe en opacité et reste bloqué dans cet état. Si je regarde les messages d’erreur d’IE, il m’indique

    '$invalides' a la valeur Null ou n'est pas un objet.
    URI spip.php?page=crayons.js&callback=startCrayons

    Ce souci n’existe pas avec IE9, Firefox ou Chrome.
    Je ne parviens pas à résoudre l’erreur. Merci par avance

    • J’ai trouvé le problème, cela vient de l’insertion du JS au début de l’entête.

      Si je modifie le code suivant

        // js inline avant la premiere css, ou sinon avant la fin du head
      	$pos_link = strpos($page, '<link ');
        if (!$pos_link)
      	  $pos_link = $pos_head;
        $page = substr_replace($page, $incJS, $pos_link, 0);

      en forçant l’insertion avant la fin du head alors cela fonctionne correctement.

        // js inline avant la premiere css, ou sinon avant la fin du head
      	//$pos_link = strpos($page, '<link ');
        //if (!$pos_link)
      	  $pos_link = $pos_head;
        $page = substr_replace($page, $incJS, $pos_link, 0);
    • mtcocktail

      Humm j’ai un peu prêt la même erreur. C’était sur quel fichier que vous avez réalisé cette modification ? :)

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom