¿Cómo obtener los puntos de inicio y finalización de la selección en el área de texto?

4 minutos de lectura

avatar de usuario
Nayana Adassuriya

Quiero obtener la posición inicial y final del cursor de un rango seleccionado en un campo de texto o área de texto.

Probé muchas funciones en varios foros, pero cuando el último carácter de la selección es un carácter de nueva línea, JavaScript lo ignora en IE6.

¿Cómo obtengo los puntos inicial y final de la selección?

Respuesta revisada, 5 de septiembre de 2010

Tener en cuenta los saltos de línea finales es complicado en IE, y no he visto ninguna solución que haga esto. Sin embargo, es posible. La siguiente es una nueva versión de lo que publiqué anteriormente aquí.

Tenga en cuenta que el área de texto debe tener foco para que esta función funcione correctamente en IE. En caso de duda, llame al textarea’s focus() método primero.

function getInputSelection(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();

        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;

                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }

    return {
        start: start,
        end: end
    };
}

  • muchas gracias Tim Down, ya probé este hilo. pero el problema es que cuando el último carácter de la selección es un carácter de nueva línea, JavaScript lo ignora en IE. de lo contrario, esas funciones funcionan bien

    – Nayana Adassuriya

    16 de junio de 2010 a las 15:03

  • Respuesta ahora completamente reescrita.

    – Tim Abajo

    17 de junio de 2010 a las 10:55

  • muchas gracias Tim Down, este método funciona bien. para la posición simple del cursor. pero si seleccionamos un rango de texto para obtener la posición de inicio del texto seleccionado. ese texto seleccionado se elimina automáticamente. Entonces, ¿cómo puedo corregir esto? De todos modos, este es un buen truco y haces un invento gr8.

    – Nayana Adassuriya

    17 de junio de 2010 a las 12:14

  • Sí, ese es el mismo problema que detecté. Lo he arreglado ahora.

    – Tim Abajo

    17 de junio de 2010 a las 13:26

  • ¡Ohooo gr8 está funcionando bien! muchas gracias Tim Down, y otra ayuda para mi!!. quiero precisar el punto final de la selección también en la misma función. ¿Cómo puedo implementar ese requisito?

    – Nayana Adassuriya

    18 de junio de 2010 a las 4:39


avatar de usuario
Derek 朕會功夫

Utilizar el Rangy api y todos tus problemas son ido gone ido ido

usándolo

Lea la documentacióno simplemente use el siguiente.
Muy sencillo,

var selection = rangy.getSelection(),  // Whole lot of information, supports
                                       // multi-selections too.
    start   = selection.anchorOffset,  // Start position
    end     = selection.focusOffset;   // End position

Espero que esta API te ayude porque es De Verdad útil en el manejo multi-navegador ranges.

  • Rangy es genial, pero no parece funcionar para áreas de texto y entradas de texto. Para eso hay rangyinputs (un complemento de jQuery): code.google.com/p/rangyinputs

    – habitante de Nueva Inglaterra

    17 de junio de 2014 a las 10:20

  • Oye, ¿hay alguna forma de usar Rangy sin instalar node, luego npm, Bower y luego Rangy? ¿Puedo simplemente incluir un archivo js minimizado en mi sitio web?

    –Edward Newell

    27 de marzo de 2015 a las 17:07

  • @EdwardNewell Creo que puedes. Intenta usar el archivo central aquí y ver si funciona. IIRC así es como lo usé antes de que se moviera a github. Para características adicionales solo aplica los diferentes módulos.

    – Derek 朕會功夫

    27 de marzo de 2015 a las 18:14

Necesitaba hacer algo muy similar y se me ocurrió esto:

function getSelection(target) {
    var s = {start: 0, end:0};
    if (typeof target.selectionStart == "number"
        && typeof target.selectionEnd == "number") {
        // Firefox (and others)
        s.start = target.selectionStart;
        s.end = target.selectionEnd;
    } else if (document.selection) {
        // IE
        var bookmark = document.selection.createRange().getBookmark();
        var sel = target.createTextRange();
        var bfr = sel.duplicate();
        sel.moveToBookmark(bookmark);
        bfr.setEndPoint("EndToStart", sel);
        s.start = bfr.text.length;
        s.end = s.start + sel.text.length;
    }
    return s;
}

Notas:

  • Él sel el rango debe ser creado por
    target en lugar de usar el rango devuelto por document.selectionde lo contrario bfr.setEndPoint se quejará de un argumento inválido. Esta “característica” (descubierta en IE8) no parece estar documentada en el Especificaciones.
  • target debe tener un foco de entrada para que esta función funcione.
  • Solo probado con <textarea>podría funcionar con <input> así como.

  • +1: No es la solución, pero sel.moveToBookmark(bookmark); ayudó MUCHO.

    – Stefan Steiger

    19 de febrero de 2018 a las 10:57


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad