Seleccionar un texto en una página y luego hacer clic en un botón conserva la selección de texto en prácticamente cualquier navegador que no sea Safari (al menos en su versión móvil).
¿Hay alguna forma de hacer que Safari se comporte como todo lo demás?
JsFiddle simple que demuestra el problema, donde seleccionar texto y hacer clic en el botón no informa el texto seleccionado en Safari (se elimina la selección y window.getSelection() no devuelve nada): https://jsfiddle.net/u5b3awhd/
<span>here's some text to select</span> <button onclick="showSelection()">click me</button> <div id="message"></div> function showSelection() { document.getElementById("message").innerText = "selected " + window.getSelection(); } Intenté agregar user-select: none y estilos similares al botón, pero no ayudó.
También encontré algunas recomendaciones para obtener texto seleccionado en algunos otros eventos de entrada (eventos del mouse, etc.), pero hay 2 razones principales por las que estoy buscando una mejor solución:
selectionchange podría resolver parcialmente este problema, todavía hay otro problema #2...Entonces, ¿cómo resuelven todos esto en 2022?
Tengo una solución para ti, tal vez, se siente asqueroso porque ciertamente estamos compensando la rareza de iOS Safari. Realmente depende de lo que estés haciendo con la selección. Específico para su código de prueba anterior:
var documentFragment; var ancestorNode; // listen to touchy on the element you want to select from document.querySelector("span").addEventListener("touchend", (e) => { let selection = document.getSelection(); if (!selection || selection.rangeCount === 0 || selection.getRangeAt(0).length === 0) return; let range = selection.getRangeAt(0); ancestorNode = range.commonAncestorContainer; // if you need it documentFragment = range.CloneContents(); // because you'll never get the selection }); document.querySelector("button").addEventListener("click", (e) => { if (!documentFragment) { // nothing there from a 'touchend' event, check now from other means. // do all the things above, but you know, refactor it so it's DRY. } if (documentFragment) { // do all the things with the fragment, like... let div = document.createElement("div"); div.appendChild(documentFragment); } }); Aunque se borre la selección, lo que era ahora está contenido en ese objeto. Puede ser más elegante y funcional si escuchas touchend y mouseup , pero no he tenido la oportunidad de validarlo. Entonces no tendría que tener su flujo alternativo como lo hice arriba. La otra cosa que puse allí opcionalmente es obtener el commonAncestorContainer del rango, en caso de que necesite mirar eso o sus padres para ver si está contenido en una id de elemento determinada o algo así. Lo necesitaba para validar que la selección era del marcado que el usuario podía marcar.