web-dev-qa-db-fra.com

Sélectionner du texte dans un élément (ce qui revient à surligner avec votre souris)

Je voudrais que les utilisateurs cliquent sur un lien, puis il sélectionne le texte HTML dans un autre élément (not une entrée).

Par "sélectionner", j'entends de la même manière que vous sélectionnez du texte en faisant glisser votre souris dessus. Cela a été un ours à la recherche parce que tout le monde parle de "sélectionner" ou "mettre en évidence" en d'autres termes.

Est-ce possible? Mon code jusqu'ici:

HTML:

<a href="javascript:" onclick="SelectText('xhtml-code')">Select Code</a>
<code id="xhtml-code">Some Code here </code>

JS:

function SelectText(element) {
    $("#" + element).select();
}

Me manque-t-il quelque chose de flagrant?

404
Jason

Javascript simple

function selectText(node) {
    node = document.getElementById(node);

    if (document.body.createTextRange) {
        const range = document.body.createTextRange();
        range.moveToElementText(node);
        range.select();
    } else if (window.getSelection) {
        const selection = window.getSelection();
        const range = document.createRange();
        range.selectNodeContents(node);
        selection.removeAllRanges();
        selection.addRange(range);
    } else {
        console.warn("Could not select text in node: Unsupported browser.");
    }
}

const clickable = document.querySelector('.click-me');
clickable.addEventListener('click', () => selectText('target'));
<div id="target"><p>Some text goes here!</p><p>Moar text!</p></div>
<p class="click-me">Click me!</p>

Voici un démo de travail . Pour ceux qui recherchent un plugin jQuery, j’ai fait n de ceux-là aussi .


jQuery (réponse originale)

J'ai trouvé une solution pour cela dans ce fil . J'ai été capable de modifier les informations données et de les mélanger avec un peu de jQuery pour créer une fonction totalement géniale permettant de sélectionner le texte dans n'importe quel élément, quel que soit le navigateur:

function SelectText(element) {
    var text = document.getElementById(element);
    if ($.browser.msie) {
        var range = document.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = window.getSelection();
        var range = document.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = window.getSelection();
        selection.setBaseAndExtent(text, 0, text, 1);
    }
}
584
Jason

Voici une version sans navigateur, ni utilisation de jQuery:

function selectElementText(el, win) {
    win = win || window;
    var doc = win.document, sel, range;
    if (win.getSelection && doc.createRange) {
        sel = win.getSelection();
        range = doc.createRange();
        range.selectNodeContents(el);
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (doc.body.createTextRange) {
        range = doc.body.createTextRange();
        range.moveToElementText(el);
        range.select();
    }
}

selectElementText(document.getElementById("someElement"));
selectElementText(elementInIframe, iframe.contentWindow);
123
Tim Down

Le code de Jason ne peut pas être utilisé pour des éléments à l'intérieur d'une iframe (la portée étant différente de la fenêtre et du document). J'ai corrigé ce problème et je l'ai modifié pour pouvoir être utilisé comme n'importe quel autre plugin jQuery (chaînable):

Exemple 1: Sélection de tout le texte à l'intérieur des balises <code> en un seul clic et ajout de la classe "sélectionnée":

$(function() {
    $("code").click(function() {
        $(this).selText().addClass("selected");
    });
});

Exemple 2: Lorsque vous cliquez sur un bouton, sélectionnez un élément dans une iframe:

$(function() {
    $("button").click(function() {
        $("iframe").contents().find("#selectme").selText();
    });
});

Remarque: rappelez-vous que la source iframe doit résider dans le même domaine pour éviter les erreurs de sécurité.

plugin jQuery:

jQuery.fn.selText = function() {
    var obj = this[0];
    if ($.browser.msie) {
        var range = obj.offsetParent.createTextRange();
        range.moveToElementText(obj);
        range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        var range = obj.ownerDocument.createRange();
        range.selectNodeContents(obj);
        selection.removeAllRanges();
        selection.addRange(range);
    } else if ($.browser.safari) {
        var selection = obj.ownerDocument.defaultView.getSelection();
        selection.setBaseAndExtent(obj, 0, obj, 1);
    }
    return this;
}

Je l'ai testé sous IE8, Firefox, Opera, Safari, Chrome (versions actuelles). Je ne suis pas sûr que cela fonctionne dans les anciennes versions IE (sincèrement, je m'en fiche).

19
lepe

Ce fil contient des trucs vraiment merveilleux. Mais je ne suis pas en mesure de le faire directement sur cette page avec FF 3.5b99 + FireBug en raison de "Erreur de sécurité".

Yipee !! J'ai pu sélectionner la barre entière à droite avec ce code en espérant que cela vous aide:

    var r = document.createRange();
    var w=document.getElementById("sidebar");  
    r.selectNodeContents(w);  
    var sel=window.getSelection(); 
    sel.removeAllRanges(); 
    sel.addRange(r); 

PS: - Je n’ai pas pu utiliser les objets renvoyés par les sélecteurs jQuery comme

   var w=$("div.welovestackoverflow",$("div.sidebar"));

   //this throws **security exception**

   r.selectNodeContents(w);
16
TheVillageIdiot

Je cherchais la même chose, ma solution était la suivante:

$('#el-id').focus().select();
7
Auston

Vous pouvez utiliser la fonction suivante pour sélectionner le contenu d'un élément:

jQuery.fn.selectText = function(){
    this.find('input').each(function() {
        if($(this).prev().length == 0 || !$(this).prev().hasClass('p_copy')) { 
            $('<p class="p_copy" style="position: absolute; z-index: -1;"></p>').insertBefore($(this));
        }
        $(this).prev().html($(this).val());
    });
    var doc = document;
    var element = this[0];
    console.log(this, element);
    if (doc.body.createTextRange) {
        var range = document.body.createTextRange();
        range.moveToElementText(element);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();        
        var range = document.createRange();
        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);
    }
};

Cette fonction peut être appelée comme suit:

$('#selectme').selectText();
6
Wolfack

J'ai aimé la réponse de Lepe à l'exception de quelques petites choses:

  1. La détection de navigateur, jQuery ou non n'est pas optimale
  2. DRY
  3. Ne fonctionne pas dans IE8 si le parent d'obj ne supporte pas createTextRange
  4. La capacité de Chrome à utiliser setBaseAndExtent doit être utilisée (IMO)
  5. Ne sélectionnera pas le texte couvrant plusieurs éléments du DOM (éléments de l'élément "sélectionné"). En d’autres termes, si vous appelez selText sur un div contenant plusieurs éléments d’étendue, le texte ne sera pas sélectionné par chacun de ces éléments. éléments. Cela a été une rupture pour moi, YMMV.

Voici ce que je propose, avec un clin d'œil à la réponse d'inspiration de Lepe. Je suis sûr que je serai ridiculisé car c'est peut-être un peu dur (et pourrait en fait être plus, mais je m'éloigne du sujet). Mais cela fonctionne et évite les renifleurs de navigateur et , voilà le problème .

selectText:function(){

    var range,
        selection,
        obj = this[0],
        type = {
            func:'function',
            obj:'object'
        },
        // Convenience
        is = function(type, o){
            return typeof o === type;
        };

    if(is(type.obj, obj.ownerDocument)
        && is(type.obj, obj.ownerDocument.defaultView)
        && is(type.func, obj.ownerDocument.defaultView.getSelection)){

        selection = obj.ownerDocument.defaultView.getSelection();

        if(is(type.func, selection.setBaseAndExtent)){
            // Chrome, Safari - Nice and easy
            selection.setBaseAndExtent(obj, 0, obj, $(obj).contents().size());
        }
        else if(is(type.func, obj.ownerDocument.createRange)){

            range = obj.ownerDocument.createRange();

            if(is(type.func, range.selectNodeContents)
                && is(type.func, selection.removeAllRanges)
                && is(type.func, selection.addRange)){
                // Mozilla
                range.selectNodeContents(obj);
                selection.removeAllRanges();
                selection.addRange(range);
            }
        }
    }
    else if(is(type.obj, document.body) && is(type.obj, document.body.createTextRange)) {

        range = document.body.createTextRange();

        if(is(type.obj, range.moveToElementText) && is(type.obj, range.select)){
            // IE most likely
            range.moveToElementText(obj);
            range.select();
        }
    }

    // Chainable
    return this;
}

C'est ça. Une partie de ce que vous voyez est la lisibilité et/ou la commodité. Testé sur Mac dans les dernières versions d'Opera, Safari, Chrome, Firefox et IE. Également testé dans IE8. En outre, je ne déclare généralement que des variables si/lorsque cela est nécessaire à l'intérieur de blocs de code, mais jslint a suggéré qu'elles soient toutes déclarées en haut. Ok jslint.

Edit J'ai oublié d'inclure comment lier cela au code de l'op:

function SelectText(element) {
    $("#" + element).selectText();
}

À votre santé

5
Madbreaks

Une version mise à jour qui fonctionne en chrome:

function SelectText(element) {
    var doc = document;
    var text = doc.getElementById(element);    
    if (doc.body.createTextRange) { // ms
        var range = doc.body.createTextRange();
        range.moveToElementText(text);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();
        var range = doc.createRange();
        range.selectNodeContents(text);
        selection.removeAllRanges();
        selection.addRange(range);

    }
}

$(function() {
    $('p').click(function() {
        SelectText("selectme");

    });
});

http://jsfiddle.net/KcX6A/326/

5
Kimtho6

lepe - Cela fonctionne très bien pour moi merci! J'ai mis votre code dans un fichier de plug-in, puis je l'ai utilisé conjointement avec une instruction de sorte que vous puissiez avoir plusieurs balises de pré et plusieurs liens "Tout sélectionner" sur une seule page et il sélectionne le pré approprié à mettre en évidence:

<script type="text/javascript" src="../js/jquery.selecttext.js"></script>
<script type="text/javascript">
  $(document).ready(function() { 
        $(".selectText").each(function(indx) {
                $(this).click(function() {                 
                    $('pre').eq(indx).selText().addClass("selected");
                        return false;               
                    });
        });
  });
3
DaveR

Pour toute balise, vous pouvez sélectionner tout le texte à l'intérieur de cette balise à l'aide de ce code court et simple. Il mettra en évidence toute la zone de tag avec la couleur jaune et sélectionnera le texte à l'intérieur en un seul clic.

document.onclick = function(event) {
    var range, selection;
event.target.style.backgroundColor = 'yellow';
        selection = window.getSelection();
        range = document.createRange();
        range.selectNodeContents(event.target);
        selection.removeAllRanges();
        selection.addRange(range);
};
3
knjhaveri

Examinez les objet Selection (moteur Gecko) et les objet TextRange (moteur Trident.). Je ne connais aucun framework JavaScript prenant en charge plusieurs navigateurs. ceci est implémenté, mais je ne l'ai jamais cherché non plus, il est donc possible que même jQuery l'ait.

2
Blixt

La méthode de Tim fonctionne parfaitement dans mon cas: sélectionner le texte dans un div pour IE et FF après avoir remplacé l'instruction suivante:

range.moveToElementText(text);

avec ce qui suit:

range.moveToElementText(el);

Le texte du div est sélectionné en cliquant dessus avec la fonction jQuery suivante:

$(function () {
    $("#divFoo").click(function () {
        selectElementText(document.getElementById("divFoo"));
    })
});
1
Hong

voici une autre solution simple pour obtenir le texte sélectionné sous forme de chaîne, vous pouvez facilement utiliser cette chaîne pour ajouter un enfant d'élément div dans votre code:

var text = '';

if (window.getSelection) {
    text = window.getSelection();

} else if (document.getSelection) {
    text = document.getSelection();

} else if (document.selection) {
    text = document.selection.createRange().text;
}

text = text.toString();
1
Nadeem Yasin

Mon cas d'utilisation particulier consistait à sélectionner une plage de texte dans un élément de portée modifiable, ce qui, autant que je sache, n'est décrit dans aucune des réponses fournies ici.

La principale différence est que vous devez passer un noeud de type Text à l'objet Range, comme décrit dans la documentation de Range.setStart () :

Si startNode est un Node de type Texte, Commentaire ou CDATASection , alors startOffset est le nombre de caractères à partir du début de startNode. Pour les autres types Node, startOffset est le nombre de noeuds enfant entre le début du startNode.

Le nœud Text est le premier nœud enfant d'un élément span. Pour l'obtenir, accédez à childNodes[0] de l'élément span. Le reste est le même que dans la plupart des autres réponses.

Voici un exemple de code:

var startIndex = 1;
var endIndex = 5;
var element = document.getElementById("spanId");
var textNode = element.childNodes[0];

var range = document.createRange();
range.setStart(textNode, startIndex);
range.setEnd(textNode, endIndex);

var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);

Autre documentation pertinente:
Plage
Sélection
Document.createRange ()
Window.getSelection ()

0
Domysee

Selon la documentation jQuery de select():

Déclenche l'événement select de chaque élément correspondant. Cela entraîne l'exécution de toutes les fonctions liées à cet événement de sélection et appelle l'action de sélection par défaut du navigateur sur le ou les éléments correspondants.

Vous expliquez pourquoi jQuery select() ne fonctionne pas dans ce cas.

0
Kees de Kooter