2009-03-18 5 views
0

Est-il possible de changer le contenu des éléments quand ils ou une partie du texte est sélectionné, puis de les annuler quand ils sont désélectionnés? Le but étant que lorsqu'ils sont copiés dans le presse-papier, la valeur alternative est copiée.Existe-t-il un moyen de modifier le contenu des éléments lorsqu'ils sont sélectionnés?

Le html recherche quelque chose comme ceci:

<p>Today is the <span class="date" value="18/03/2009">18th of March</span>.</p> 
+0

Que voulez-vous dire par sélectionné? – SeanDowney

+0

Un utilisateur positionne la souris à gauche de "Aujourd'hui" puis appuie sur le bouton gauche de la souris en faisant glisser la souris jusqu'à la fin de "Mars". À ce stade, il est sélectionné bien qu'il existe d'autres moyens de sélectionner des choses comme double ou triple cliquant sur un mot. – Annan

+0

Pourquoi voulez-vous changer le texte qu'ils copient? Cela ressemble à un problème de conception d'interface. – strager

Répondre

0

Une solution que je suis venu avec est la suivante.

HTML:

<p>Semper mi vitae tellus <span class="date" title="19/03/09" data="19th of March">19th of March</span> quis, augue.</p> 

CSS:

.date { 
    display:inline-block; 
    text-align:center; 
} 

Cela empêche le texte de sautiller lorsque le contenu est remplacé.

Javascript:

var travel = function(node, noChildren){ 
    if (node.firstChild && !noChildren) { 
     return node.firstChild; 
    } 
    if (node.nextSibling) { 
     return node.nextSibling; 
    } 
    return travel(node.parentNode, true); 
}; 

var onMouseDown = function(event){ 
    var spans = document.getElementsByClassName(revertClass); 
    var i = spans.length; 
    while (i) { 
     i--; 
     spans[i].innerHTML = spans[i].getAttribute('data'); 
     spans[i].className = window.baseClass; 
    } 

    var selection = window.getSelection(); 
    if (selection.rangeCount && event.button === 2){ 
     var n = selection.rangeCount; 
     var k = n; 
     do { 
      var i = k-n; 
      var range = selection.getRangeAt(i); 

      var element = range.startContainer; 
      var endContainer = range.endContainer; 
      do { 
       if (element.className === window.baseClass){ 
        element.style.width = element.offsetWidth; 
        element.innerHTML = element.title; 
        element.className += ' ' + window.revertClass; 
       } 
       if (element == endContainer){ 
        break; 
       } 
      } 
      while (element = travel(element)); 

      var newRange = document.createRange(); 
      newRange.setStart(range.startContainer, range.startOffset); 
      newRange.setEnd(range.endContainer, range.endOffset); 

      selection.removeRange(range); 
      selection.addRange(newRange); 
     } 
     while (--n); 
    } 
}; 

var onKeyDown = function(event){ 
    //Ctrl + C 
    if (event.keyCode === 67 && event.ctrlKey){ 
     event.button = 2; 
     onMouseDown(event); 
    } 
    //Tab to deselect 
    else if (event.keyCode === 9){ 
     onMouseDown(event); 
    } 
}; 

window.baseClass = 'date'; 
window.revertClass = 'date_revert'; 
window.addEventListener ('mousedown', onMouseDown, false); 
window.addEventListener ('keydown', onKeyDown, false); 

Je n'ai pas utilisé à dessein jquery que je prévois sur l'utilisation dans un script Greasemonkey et le charger sur chaque page ralentirait les choses (je pense?). Je l'ai eu avec le changement automatique sur la sélection en liant mousemove après le mousedown, mais il a fini par être très lent, donc j'ai décidé qu'il était préférable de se concentrer sur mon objectif de changer ce qui a été copié.

A propos de l'utilisation des attributs non standard, je n'ai jamais trouvé que cela soit un problème? J'utilise le titre afin que les gens puissent voir le format alternatif sans le copier et les données parce que cela semblait logique.

1

MISE À JOUR: en utilisant vol stationnaire au lieu (par Scott E. commentaire)

J'aime et JQUERY ci-dessous est un moyen, mais pas parfait, mais devrait se vous avez commencé le chemin. La raison pour laquelle ce n'est pas parfait, c'est parce qu'il y a un "battement" si vous passez la souris sur et sur le côté droit (intéressant) de la durée.

Notez que ceci est entièrement fonctionnel, mais vous devriez obtenir la version locale de JQUERY js. Aussi, après l'avoir posté la première fois, j'ai découvert que I/E ne se comporte pas comme prévu.

Voir http://docs.jquery.com/Events et http://docs.jquery.com/Core

<html> 
    <body> 
    <p>Today is the <span class="date"/></p> 
    </body> 
</html> 



<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script> 
<script type="text/javascript"> 

    $(document).ready(function(){ 

    // use data object of <span> element with class 'date'. 
    // Do this instead of using "value" attribute in <span> 
    // which is not normal part of <span> element 
    // instead of putting the value directly in <span> above, I'm assigning it here 

    $(".date").data("mydates", { selected : "18/03/2009", normal: "18th of March" }); 

    // assign the normal value on startup 
    $(".date").html($(".date").data("mydates").normal); 

    // first function is executed on mouseover 
    // second function is executed on mouseout 
    $(".date").hover(
     function() { 
      $(".date").html($(".date").data("mydates").selected); 
     }, 
     function() { 
      $(".date").html($(".date").data("mydates").normal); 
     } 
    ); 

    }); 
</script> 
+0

Juste un FYI- la double liaison de mouseenter et de mouseleave est plus facilement gérée par la fonction hover() de jquery –

+0

Merci Scott, autre chose que j'ai découvert était que c'est flunky sur IE. –

+0

Solution intéressante, je suis sur le point de poster ma solution que je suis venu avec. Le problème avec votre réponse est que si vous sélectionnez la date avec un autre texte et que vous la copiez, vous finissez par copier la date 'normale'. C'est un bon moyen de permettre aux gens de visionner un autre format, mais un titre pourrait être mieux adapté. – Annan