Lightbox extension : copier/coller d'un texte

Publié le 29 avril 2007 par Olivier Duval

Objectif (pourtant simple…)

A partir d’un formulaire, le but est de remplir 2 champs par un “Copier/Coller” à partir d’une modal. Dans notre cas, selon un intitulé (de poste), on propose à l’utilisateur des choix de libellés qui s’en rapprochent. Celui-ci clique alors sur celui qui lui convient, puis a la possibilité de copier les missions/profil de la fiche qu’il a choisie : le but étant de faciliter la recopie de texte.

Formulaire initial avec les 2 champs à remplir automatiquement :

Champs initiaux à remplir

Suite à la saisie d’un libelle (de poste), l’utilisateur peut choisir parmi un ensemble de proposition, lors du clic, une modal s’ouvre avec la fiche afférente au poste :

Sélection d'un libellé

Sur la fiche de poste, l’utilisateur peut cliquer sur copier, ce qui a pour effet de fermer la modal et de recopier les 2 champs Missions/Profil dans les 2 champs du formulaire initial.

Modal de la fiche poste

Champs recopiés

Défaut

Lors de la recopie, on copie les innerHTML des 2 éléments <p> vers les 2 textarea (elt.value). Le contenu peut contenir du HTML qu’il faut enlever pour la textarea destinatrice. Egalement les <br/> contenus dans les innerHTML sont à remplacer par des \r (sinon cela serait illisible).

Constat : IE parait rendre <BR _extension=”true”> au lieu des <br/> contenus dans innerHTML de l’élément.

Explications

J’ai étendu la classe Lightbox (perfectible d’ailleurs au niveau de sa conception) afin de permettre notamment une copie d’un contenu (d’un bloc <p> avec du contenu issu d’une précédente saisie, avec du HTML) vers une <textarea> (ou un <input type=”text”>), ce qui oblige à remplacer les <br/> par des retours chariots (\r) pour une meilleure visibilité.

Lightbox permet d’étendre assez facilement les comportements, en appliquant des handlers (utilisation de l’attribut rel=”fonction” aux éléments <a> marqués par une classe lbAction), j’ai donc utilisé cette possibilité pour simuler un copier/coller.

Le code se traduit par :


var modal = Class.create();
modal.prototype = Object.extend(lightbox.prototype, {    
     initialize: function(ctrl) { 
          this.content = ctrl.href;        
        this.hrefid = ctrl.id;
        Event.observe(ctrl, 'click', this.activate.bindAsEventListener(this), false);
    ctrl.onclick = function(){return false;};
      },    
      copy: function() {        
        var d = document.getElementsByClassName('dCopyContent');
        var s = $('lbContent').getElementsByClassName('sCopyContent');
        for(i = 0; i < s.length; i++) {
           Try.these (
              function() 
              {                                                                                      
                 //sous IE : <BR _extended=""true"">                            
                 d[i].value = s[i].innerHTML.replace(/<(br).*?\/?>/gi,'\r');     
                 // fct prototype bien sympa : stripTags                                   
                 d[i].value = d[i].value.stripTags();
              }
           )
         }
        this.deactivate();
       },
       loadInfo: function() {            
          var myhrefid = this.hrefid;
      var valueParams = Try.these(
        function() {                 
              return $F('paramname'+myhrefid)+'='+$F('paramvalue'+myhrefid);                        
         },
         function() { return ''; });
           var myAjax = new Ajax.Request(
                   this.content,
                   { method: 'post', 
                      parameters: valueParams, 
                      onComplete: this.processInfo.bindAsEventListener(this)} );        
                }
         }
);

et le code (X)HTML (exemple) :

<div id="lightbox" class="done" style="display: block;">
  <div id="lbContent">
    <div style="height: 500px;"><span style="margin: 0pt 10px 0pt 0pt; float: right; background-color: white;">
    <a rel="copy" class="lbAction lienInterne" href="#">Copier</a> <a rel="deactivate" class="lbAction" href="#"><img style="border-style: none; width: 20px; height: 20px; vertical-align: middle;" src="/images/pict_close.gif"/></a></span><br/>

<div style="overflow: auto; height: 350px; background-color: White;" id="container">
  <div style="background-color: White;" id="fichemodele">
    <div id="headeroffre">                
        <span class="intituleposte">Conseiller(e) en entreprise</span>                    
    </div>
    <div id="fiche">    
        <fieldset style="width: 470px;">
            <h2 class="titreParagraphe">Missions</h2>
            <p class="normal sCopyContent">-    Assurer les visites et contacts avec les entreprises et les conseiller dans le domaine d’hygiène, sécurité ; gestion de production<br/>-    Mettre au point et valider les cahiers des charges, réaliser des études & diagnostics et/ou mettre en contact avec un spécialiste<br/>-    Etablir des rapports, suivi, préconisations<br/>-    Mettre sur pied des actions collectives (Plasturgia, Journée Régionale de la Prévention, SMS…)<br/>-    Organiser des réunions à thèmes (sécurité, BTP…)<br/>-    Instruire, monter, réaliser des dossiers d’aides financières<br/></p>
            <h2 class="titreParagraphe">Profil</h2>
            <p class="normal sCopyContent">-    H/F 30 ans et +<br/>-    Formation ingénieur avec connaissances générales en organisation de production, qualité, sécurité, hygiène, gestion<br/>-    Expérience du milieu industriel indispensable<br/>-    Maîtrise des outils bureautiques<br/>-    Rigueur, organisation, sens de l’animation, sens relationnel<br/>-    Très grande disponibilité<br/>-    Permis B et véhicule exigés</p>
        </fieldset>
  </div></div>
   </div>
   </div>
  </div>
</div>

Dans la méthode copy, bien que les tags utilisés soient <br/>, IE me ramenait :

 <BR _extended="true"> 
lors de la lecture du contenu elt-p.innerHTML. Aussi j’ai été obligé de rajouter ce cas dans la Regexp de substitution, qui au lieu de
s[i].innerHTML.replace(/<(br)\/?>/gi,'\r');
devient
s[i].innerHTML.replace(/<(br).*?\/?>/gi,'\r');

Tout ça pour dire que j’ai perdu pas mal d’heures avant de m’apercevoir qu’IE modifiait le contenu du innerHTML, la substitution fonctionnant bien sous FF…bref ;)

Si quelqu’un a une explication rationnelle, je suis preneur.

1 Le principal reproche étant que l’auteur ait intégré la fonction initialize() et son appel dans le même fichier lightbox.js, cela aurait été plus judicieux de l’incorporer dans un autre, cela pour assouplir la possibilité d’extensibilité de la classe.