IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Suivre la sélection de texte dans un élément sans pouvoir le changer


Sujet :

JavaScript

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Par défaut Suivre la sélection de texte dans un élément sans pouvoir le changer
    Bonjour à tous,
    J'ai besoin d'un élément (textarea, div, pre...) qui réponde aux critères suivants :
    1. Possibilité de suivre la sélection de texte réalisé à la souris (un onclick marche pour la plupart des types d'élément)
    2. Idem mais pour de la sélection de texte au clavier (un onkeyup m'irait bien).
    3. Ne pas pouvoir supprimer/modifier le texte en lui-même
    4. Trouver les limites de la zone sélectionnée : j'ai un javascript qui fait le job lancé par les évènements des points 1 et 2
    5. Le but ultime étant de surligner la zone sélectionée afin qu'elle reste visible en perdant le focus (en général le surlignage bleu disparait dès qu'on sort du champ). Un onblur pourrait lancer la manip


    Le problème est que si l'élément contenant le texte n'est pas éditable, les keyevents ne fonctionnent pas. Si il est éditable, on peut supprimer/modifier le texte !
    Merci pour vos idées lumineuses

    Voici le code
    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <pre id="text" style="height: 200px;width: 500px;border: 1px solid black;white-space: normal;overflow-x: scroll" onclick="showPosition()" onkeyup="showPosition()" onblur="highlight()" contenteditable="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus cursus lacus non ligula pellentesque rutrum. Proin vestibulum cursus nisi ac egestas. Morbi fermentum nisl justo, luctus laoreet tortor cursus egestas. Nam volutpat est nunc, vitae rutrum turpis sollicitudin id. Duis id fermentum lectus, a finibus massa. Donec condimentum porttitor vehicula. Pellentesque interdum, lacus eget sodales iaculis, eros neque luctus metus, non varius felis nisi vel leo. Nam leo purus, mattis a convallis eget, mattis ac ex. Etiam feugiat metus eget feugiat consectetur. Nunc id mattis urna. Ut non justo ut tellus pharetra ultricies a at tellus. Nulla tincidunt eros sit amet semper pharetra. Aliquam erat volutpat. Vivamus in semper felis. Nunc vel dolor varius, tincidunt magna sit amet, semper augue. Etiam cursus imperdiet viverra. </pre>
    <br>Start: <span id="start"></span>
    <br>End: <span id="end"></span>
    <br>Length: <span id="length"></span>
     
    <script>
            function getSelectionOffsetsWithin(elementId) {
                    var start = 0, end = 0;
                    var range, priorRange;
                    if (typeof window.getSelection != "undefined") {
                            range = window.getSelection().getRangeAt(0);
                            priorRange = range.cloneRange();
                            priorRange.selectNodeContents(document.getElementById(elementId));
                            priorRange.setEnd(range.startContainer, range.startOffset);
                            start = priorRange.toString().length;
                            end = start + range.toString().length;
                            if (range.toString().length > 0) end--;
                    }
                    return {
                            start: start,
                            end: end
                    };
            }
            function showPosition() {
                    var positions = getSelectionOffsetsWithin('text');
                    positions.start++;
                    positions.end++;
                    $('#start').text(positions.start);
                    $('#end').text(positions.end);
                    $('#length').text(positions.end - positions.start + 1);
            }
            function highlight() {
                    /* a partir de start et end, encadrer la selection avec un tag <mark> par exemple */
            }
    </script>

  2. #2
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Par défaut
    J'ai pu avancer sur la question et je vous donne ma solution, même s'il reste un petit problème.

    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <!DOCTYPE html>
    <html lang='fr'>
    	<head>
    		<meta charset="utf-8">
    		<title>TITLEPAGE</title>
    		<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    	</head>
    	<body>
    		<pre id="text" style="height: 200px;width:600px;border:1px solid black;white-space:normal;overflow-x:scroll" onmouseup="showPosition(event)" onkeypress="return showPosition(event)" onblur="highlight()" contenteditable="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus cursus lacus non ligula pellentesque rutrum. Proin vestibulum cursus nisi ac egestas. Morbi fermentum nisl justo, luctus laoreet tortor cursus egestas. Nam volutpat est nunc, vitae rutrum turpis sollicitudin id. Duis id fermentum lectus, a finibus massa. Donec condimentum porttitor vehicula. Pellentesque interdum, lacus eget sodales iaculis, eros neque luctus metus, non varius felis nisi vel leo. Nam leo purus, mattis a convallis eget, mattis ac ex. Etiam feugiat metus eget feugiat consectetur. Nunc id mattis urna. Ut non justo ut tellus pharetra ultricies a at tellus. Nulla tincidunt eros sit amet semper pharetra. Aliquam erat volutpat. Vivamus in semper felis. Nunc vel dolor varius, tincidunt magna sit amet, semper augue. Etiam cursus imperdiet viverra. </pre>
    		<br>Start: <span id="start"></span>
    		<br>End: <span id="end"></span>
    		<br>Length: <span id="length"></span>
    		<script>
                            function getSelectionOffsetsWithin(elementId) {
                                    var start = 0, end = 0, length = 0;
                                    var range, priorRange;
                                    if (typeof window.getSelection != "undefined") {
                                            range = window.getSelection().getRangeAt(0);
                                            priorRange = range.cloneRange();
                                            priorRange.selectNodeContents(document.getElementById(elementId));
                                            priorRange.setEnd(range.startContainer, range.startOffset);
                                            start = priorRange.toString().length;
                                            end = start + range.toString().length;
                                            length = range.toString().length;
                                            if (length > 0) end--;
                                    }
                                    return {
                                            start: start,
                                            end: end,
                                            length: length
                                    };
                            }
                            function showPosition(event) {
                                    var keyCode = event.which ? event.which : event.keyCode;
                                    if ($.inArray(keyCode, [1, 35, 36, 37, 38, 39, 40]) < 0) {
                                            return false;
                                    }
                                    var positions = getSelectionOffsetsWithin('text');
                                    console.log(positions);
                                    positions.start++;
                                    positions.end++;
                                    $('#start').text(positions.start);
                                    $('#end').text(positions.end);
                                    $('#length').text(positions.length);
                                    return true;
                            }
                            function highlight() {
                                    /* a partir de start et end, encadrer la selection avec un tag <mark> par exemple */
                            }
                    </script>
    	</body>
    </html>
    Les différences :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    <pre ... onmouseup="showPosition(event)" onkeypress="return showPosition(event)">
    pour mieux gérer les évènements, avec le return très important pour empêcher la modification du texte
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function showPosition(event) {
    	var keyCode = event.which ? event.which : event.keyCode;
    	if ($.inArray(keyCode, [1, 35, 36, 37, 38, 39, 40]) < 0) {
    		return false;
    	}
    	...
    	return true;
    ...}
    pour que les seules touches clavier permettant de bouger les curseur soient admises.
    Maintenant j'ai un problème : si j'utilise les touches "début" et "fin" pour sélectionner une ligne entière, ou bien si je descend ou monte avec les flèches haut/bas, ça calcul mal les offsets des curseurs !
    Par exemple en se mettant au milieu de la première phrase et en faisant MAJ+FLECHE BAS, on a start = end au lieu que end soit environ 70 caractères plus loin. Si on ajoute un MAJ+FLECHE DROITE ça met bien à jour comme attendu. Je ne comprends pas la différence de fonctionnement.
    Merci d'avance...

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Salut,

    Il y a beaucoup de choses à voir...

    1- Pour ce qui est de l'usage de event.keyCode et event.which regarde ce fil : Quelles sont les bonnes manières de détecter les touches du clavier ?... Il est conseillé d'utiliser event.key... D'ailleurs tu m'as fait découvrir (cf. ci-après) un inconvénient concernant event.keyCode et event.which...

    2-
    Citation Envoyé par Titum Voir le message
    pour que les seules touches clavier permettant de bouger les curseur soient admises.
    Je suppose que le but de cela est d’éviter qu'on puisse modifier la zone éditable, c'est ton point 3 : "Ne pas pouvoir supprimer/modifier le texte en lui-même" mais ça marche pas avec Chrome (mais c'est ok avec FF apparemment) :...

    En effet il y a plusieurs touches qui passent comme par exemple les touches de suppression : Delete et Backspace.

    Ensuite un piège que tu m'as fait découvrir : pour une même touche clavier event.keyCode/event.which renvoi un code différent selon que tu utilises onkeypress ou onkeydown...

    Cela pose un problème car tu utilises onkeypress or celui-ci te donne par exemple pour la flèche "ArrowDown" le code "40" or tu autorises ce code mais il se trouve que la touche parenthèse "(" a aussi ce code du coup on peut modifier le texte de la zone éditable avec cette touche... Or je ne sais pas si tu veux aussi éviter cela ?

    Par contre onkeydown te donne deux codes différents...

    Et si tu utilises event.key, les deux (onkeypress et onkeydown) te renvoi "(" pour la parenthèse et pour la flèche "ArrowDown" onkeydown renvoi la chaine "ArrowDown" et onkeypress n'est pas déclenché pour cette touche...

    Ca c'est avec Chrome, sur FF curieusement c'est différent onkeypress est déclenché même pour les flèches, les touches de suppression : Delete et Backspace... Mais il n'est pas déclenché pour la touche Shift !!!

    Et c'est je pense cela qui t'a trompé...


    Citation Envoyé par Titum Voir le message
    Maintenant j'ai un problème : si j'utilise les touches "début" et "fin" pour sélectionner une ligne entière, ou bien si je descend ou monte avec les flèches haut/bas, ça calcul mal les offsets des curseurs !
    Par exemple en se mettant au milieu de la première phrase et en faisant MAJ+FLECHE BAS, on a start = end au lieu que end soit environ 70 caractères plus loin. Si on ajoute un MAJ+FLECHE DROITE ça met bien à jour comme attendu. Je ne comprends pas la différence de fonctionnement.
    Oui je constate aussi cette différence avec FF mais sur Chrome cela ne marche pas du tout car encore une fois onkeypress n'est pas déclenché pour les flèches...

    Avec FF on est trompé car onkeypress est déclenché pour les flèches mais pas pour la touche Shift !!! Or par "MAJ" je suppose que c'est la touche Shift que tu veux désigner...

    -->> Pour détecter cette touche tu dois donc utiliser onkeydown (ou plutôt onkeyup si tu veux éviter un décalage de 1 dans la position) et son code est "16" tu dois donc l'ajouter dans ton code (ton tableau) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if ($.inArray(keyCode, [1, 35, 36, 37, 38, 39, 40]) < 0) {
                    return false;
                }
    PS : Le code "1" correspond à quelle touche ? EDIT = Ah oui c'est le bouton gauche de la souris...
    -------------------



    J'ai testé cela en modifiant et en ajoutant quelques petites choses à ton code : http://jsbin.com/diruvurore/edit?html,output ... J'ai utilisé onkeyup pour éviter un décalage dans la position du curseur et du coup il faut aussi traité onkeydown pour empêcher l'action de certaines touches (pour éviter la modification de la zone éditable).

    On pourrait cependant permettre les touches : "PageUp" et "PageDown" qui permettent aussi de déplacer le curseur (et donc de sélectionner une certaine potion du texte)...

    A+...

  4. #4
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Par défaut
    Salut,
    Merci beaucoup pour cette réponse.
    En effet, il faut dissocier keydown et keyup. Et en effet les keycodes ne sont pas les mêmes !
    La solution sur laquelle je me suis arrêté utilise keypress parce que keydown boucle tant qu'on a le doigt sur le clavier, ça ne me convient pas.
    Pour permettre de copier le texte sélectionné, j'autorise la touche "c" si Ctrl est enclenché. Attention, en keydown le keyCode renvoi le numéro de la touche (67 pour "c") mais en keypress ça renvoi le code ascii (99) de la lettre
    Et pour que l'affaire soit complète jai ajouté le corps de la fonction highlight, rien qui casse des briques mais c'est là.

    Voilà un exemple de code final que je vais pouvoir intégrer maintenant :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    <!DOCTYPE html>
    <html lang='fr'>
    	<head>
    		<meta charset="utf-8">
    		<title>TITLE</title>
    		<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    	</head>
    	<body>
    		<p>Texte avant</p>
    		<pre id="text" style="height: 200px;width:600px;border:1px solid black;white-space:normal;overflow-x:scroll" contenteditable="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit. <mark>Phasellus cursus</mark> lacus non ligula pellentesque rutrum. Proin vestibulum cursus nisi ac egestas. Morbi fermentum nisl justo, luctus laoreet tortor cursus egestas. Nam volutpat est nunc, vitae rutrum turpis sollicitudin id. Duis id fermentum lectus, a finibus massa. Donec condimentum porttitor vehicula. Pellentesque interdum, lacus eget sodales iaculis, eros neque luctus metus, non varius felis nisi vel leo. Nam leo purus, mattis a convallis eget, mattis ac ex. Etiam feugiat metus eget feugiat consectetur. Nunc id mattis urna. Ut non justo ut tellus pharetra ultricies a at tellus. Nulla tincidunt eros sit amet semper pharetra. Aliquam erat volutpat. Vivamus in semper felis. Nunc vel dolor varius, tincidunt magna sit amet, semper augue. Etiam cursus imperdiet viverra. </pre>
    		<br>Start: <span id="start"></span>
    		<br>End: <span id="end"></span>
    		<br>Length: <span id="length"></span>
    		<script>
                            $('#text')
                                    .keypress(function (event) {
                                            return checkEventAllowed(event);
                                    })
                                    .keyup(function () {
                                            showPosition();
                                    })
                                    .mouseup(function () {
                                            showPosition();
                                    })
                                    .blur(function () {
                                            highlight();
                                    });
                            function getSelectionOffsetsWithin(elementId) {
                                    var start = 0, end = 0, length = 0;
                                    var range, priorRange;
                                    if (typeof window.getSelection != "undefined") {
                                            range = window.getSelection().getRangeAt(0);
                                            priorRange = range.cloneRange();
                                            priorRange.selectNodeContents(document.getElementById(elementId));
                                            priorRange.setEnd(range.startContainer, range.startOffset);
                                            start = priorRange.toString().length;
                                            end = start + range.toString().length;
                                            length = range.toString().length;
                                            if (!range.collapsed) end--;
                                    }
                                    return {
                                            start: start,
                                            end: end,
                                            length: length
                                    };
                            }
                            function checkEventAllowed(event) {
                                    var keyCode = event.which ? event.which : event.keyCode;
                                    // Allow copy
                                    if (event.ctrlKey && keyCode === 99) return true;
                                    // Allow only cursor moving
                                    if ($.inArray(keyCode, [1, 35, 36, 37, 38, 39, 40]) < 0) {
                                            return false;
                                    }
                                    return true;
                            }
                            function showPosition() {
                                    var positions = getSelectionOffsetsWithin('text');
                                    $('#start').text(positions.start);
                                    $('#end').text(positions.end);
                                    $('#length').text(positions.length);
                            }
                            function highlight() {
                                    var from = parseInt($('#start').text());
                                    var to = parseInt($('#end').text());
                                    var text = $('#text').text();
                                    console.log(from + ' ' + to);
                                    var html = text.substring(0, from) + "<mark>" + text.substring(from, to + 1) + "</mark>" + text.substring(to + 1, text.length);
                                    $('#text').html(html);
                            }
                    </script>
    	</body>
    </html>

    J'aurai aimé simplifier la fonction getSelectionOffsetsWithin() pour éviter de cloner le Range, mais dans mes tests ça ne marche pas à partir du moment où je sélectionne une partie du texte surligné puisqu'il se trouve dans un node enfant.
    Et l'idéal aurait été d'empêcher qu'on sélectionne par inadvertance du texte en dehors du cadre <pre> comme le paragraphe "Texte avant" mais tout ça c'est du confort pas nécessaire à ce stade.

    Merci encore Beginner.

  5. #5
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 101
    Par défaut
    Bonjour !
    Attention à la différence d’intention entre keydown et keypress.
    Les deux ont le même fonctionnement d’un point de vue « scénaristique » : l’évènement est émis à répétition, aussi longtemps qu’une touche du clavier est pressée.

    La différence c’est que keypress a été conçu pour donner uniquement de l’information sur les touches qui correspondent à un caractère. Les touches modificatrices comme Ctrl et Maj n’émettent pas d’évènement keypress. Historiquement, keypress porte l’information dans charCode alors que keydown utilise keyCode.

    La propriété which représente tantôt keyCode, tantôt charCode suivant le type d’évènement. Je recommande de ne pas l’utiliser en JS « vanilla » (sans framework), car elle ne fait qu’apporter de la confusion. En revanche, si tu utilises jQuery, c’est ironiquement le nom which qui a été choisi pour porter l’information des évènements clavier…

    Comme tu as pu le voir, il y a un autre problème : la notion de « qu’est-ce qui est un caractère » est très floue. Par exemple, les touches fléchées ne produisent pas de texte, et pourtant elles émettent un keypress. Ajoute les différences de mise en œuvre dans les anciennes versions des navigateurs (la légende raconte que même jQuery a renoncé) et tu as sans doute la raison pour laquelle les propriétés keyCode, charCode et which ont été dépréciées.

    Les remplacements actuellement proposés sont insuffisants à mon avis, mais je me suis déjà exprimé à ce sujet, je ne vais pas me répéter.


    … Et sinon j’ai une question : tu as pensé à l’attribut readonly ?
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  6. #6
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Salut,

    Citation Envoyé par Titum Voir le message
    La solution sur laquelle je me suis arrêté utilise keypress parce que keydown boucle tant qu'on a le doigt sur le clavier, ça ne me convient pas.
    Euh je viens de tester et il y a répétition dans les deux cas... Et Watilin confirme si j'ai bien compris....

    Sinon je t'ai indiqué plusieurs problèmes avec onKeyPress, en effet tu souhaites empêcher la modification de la zone éditable mais ça marche pas :

    1 - Avec Chrome et FF :

    - onkeypress te donne par exemple pour la flèche "ArrowDown" le code "40" or tu autorises ce code mais il se trouve que la touche parenthèse "(" a aussi ce code du coup on peut modifier le texte de la zone éditable avec cette touche...

    Ce n'est pas le seul cas par exemple, l'apostrophe "'" : eh bien avec onkeypress elle a le même code (39) que la touche "ArrowRight" que tu autorises.

    C'est which (et aussi charCode) qui donne ces codes on peut donc je pense éviter ce problème en utilisant keycode ou mieux comme déjà dit key (cf. le fil indiqué).

    2- Avec Chrome :

    Il y a plusieurs touches qui passent (car onKeyPress n'est pas déclenché pour ce touches) comme par exemple les touches de suppression : Delete et Backspace.

    Citation Envoyé par Titum Voir le message
    Et l'idéal aurait été d'empêcher qu'on sélectionne par inadvertance du texte en dehors du cadre <pre> comme le paragraphe "Texte avant" mais tout ça c'est du confort pas nécessaire à ce stade.
    J'ai déjà fait ça avec de CSS... Si cela t’intéresse je peux essayer de retrouver...


    Citation Envoyé par Watilin Voir le message
    Comme tu as pu le voir, il y a un autre problème : la notion de « qu’est-ce qui est un caractère » est très floue. Par exemple, les touches fléchées ne produisent pas de texte, et pourtant elles émettent un keypress.
    Salut,

    Merci, oui comme je disais j'ai découvert cela mais c'est le cas avec FF et non avec Chrome apparemment...

    Autre chose que j'ai remarquée : sur Chrome (et pas sur FF) onKeyPress n'est pas déclenché pour les touches de suppression : Delete et Backspace.

    Citation Envoyé par Watilin Voir le message
    … Et sinon j’ai une question : tu as pensé à l’attribut readonly ?
    C'est pour textarea seulement, non ? Titum utilise une zone éditable je suppose parce qu'il veut pouvoir mettre en surbrillance le texte sélectionné ???

  7. #7
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 101
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    C'est pour textarea seulement, non ? Titum utilise une zone éditable je suppose parce qu'il veut pouvoir mettre en surbrillance le texte sélectionné ???
    Ah voui, effectivement c’est un problème. Je crois qu’on en est rendus à faire du bricolage.

    Il me semble que prévenir les keypress qui n’ont pas de charCode mâche déjà une bonne partie du travail.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    … .addEventListener("keypress", function (event) {
      if (!event.charCode) {
        event.preventDefault();
      }
    });
    Mais je ne peux pas affirmer à 100 % que ça ne fait pas de faux positifs.

    Et ça ne règle pas le cas des touches del et backspace sous Chrome. Pour ce cas spécifique il faudrait en plus un écouteur sur keydown.

    Il y a aussi le cas des keypress qui ont un charCode mais qui sont en fait des commandes, par exemple Ctrl+X. On peut prévenir les évènements cut et paste, mais rien ne garantit qu’il n’existe pas d’autres commandes permettant de modifier le texte. Si l’utilisatrice ou l’utilisateur a configuré des raccourcis personnalisés, elle ou il n’a pas envie qu’on les lui annule. On est sur une pente glissante.

    En dernier recours il y a une solution « guérir faute d’avoir pu prévenir » mentionnée dans cette discussion sur Stackoverflow :
    Citation Envoyé par Салман
    Then I could only think of storing initial html in h and return ((this.innerHTML != h) && (this.innerHTML = h)) in an onkeyup. That's a shame.
    Dans ce cas je peux seulement penser à stocker le html initial dans h et return ((this.innerHTML != h) && (this.innerHTML = h)) dans un onkeyup. C’est une honte.
    Sinon il y a la solution « éducative » qui consiste à laisser tomber le contenteditable et informer les utilisatrices et utilisateurs que la touche F7 permet de sélectionner du texte au clavier. Mais combien le feront ?
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  8. #8
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Par défaut
    Salut Watilin, merci pour ta participation !
    Je n'uilise pas readonly car mon élément PRE ne répond plus aux touches du clavier (ne déclenche pas mouseup).

    Comme le dit Beginner, il me faut en effet autre chose qu'un textarea pour pouvoir colorer. Un div ou pre ou autre block peut faire l'affaire. Mais pour que ça réponde au clavier, là encore, il faut mettre en contenteditable... donc gérer ensuite les permissions comme pour un textarea.

    Utiliser keydown semble en effet donner moins de flottements sur les codes récupérés. Il faut alors autoriser ctrl+67 pour copier. Visiblement on ne peut entrer aucun autre caractère que ceux du tableau de codes autorisés, sans que ces nombres correspondent à 2 entités..
    Dans ce cas il me semble que sous Chrome et FF which et keyCode donnent la même chose.

  9. #9
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Merci. Ah ça m’intéressait car ça permet l'affichage du curseur...


    Citation Envoyé par Titum Voir le message
    J'aurai aimé simplifier la fonction getSelectionOffsetsWithin() pour éviter de cloner le Range,...
    Pour éviter de cloner le range tu peux remplacer priorRange = range.cloneRange(); par priorRange = document.createRange();, c'est peut-être plus rapide et moins gourmand en mémoire ?

    Je remplacerais aussi ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    end = start + range.toString().length;
    length = range.toString().length;
    ...par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    length = range.toString().length;
    end = start + length;

  10. #10
    Membre confirmé
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Par défaut
    Ah oui, F7 c'est bien pratique ! Mais je n'arrive pas à l'utiliser sous Chrome.

    Merci pour le fil Stackoverflow. Des éléments semblent tout à fait pertinents !

    Je ne pensais pas que ce serait à ce point tordu mon histoire
    Bref, voilà ce que j'ai au final, qui semble bien tourner sous Chrome et FF et même IE11 http://jsbin.com/fovupulagu/edit?html,output

    Je n'ai pas vérifié si cloneRange()permettait de conserver des infos de range qui disparaitrait avec createRange(), ce qui m'embêtait est que c'est verbeux par rapport à la possibilité de récupérer toutes les infos de range lui-même.

    Franchement Merci à vous, et s'il reste des soucis dans le jsbin n'hésitez pas à me prévenir

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB.NET] Sélection de texte dans un textbox
    Par olbi dans le forum Windows Forms
    Réponses: 5
    Dernier message: 25/08/2014, 10h26
  2. Sélection de texte dans un formulaire textarea
    Par zakuli dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 18/07/2009, 19h37
  3. Sélection du texte dans divers controles lors du focus
    Par oftheball dans le forum Windows Forms
    Réponses: 0
    Dernier message: 19/02/2009, 15h53
  4. Changer le mode de sélection de texte dans un éditeur
    Par orl132 dans le forum SWT/JFace
    Réponses: 7
    Dernier message: 05/07/2008, 12h00
  5. Sélection de texte dans un GtkTextView
    Par bit_o dans le forum GTK+ avec C & C++
    Réponses: 1
    Dernier message: 25/12/2007, 20h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo