window.getSelection() en JavaScript - El suplicio de la selección de Texto

Hablo sobre como estoy implementando una funcionalidad para la selección de texto en JavaScript y poder realizar un resaltado de texto y una nota.

Te voy a explicar una cosita que creo que vas a considerar muy interesante  que cuando el usuario selecciona un texto puedas establecer opciones como la de resaltar el texto y agregar una nota; para esto, existe una función en JS:

window.getSelection();

Para probar el método anterior, abre una ventana de tu navegador, la consola de desarrolladores, selecciona un texto en la página web y luego ejecuta la línea de código anterior y verás ua saluda como la siguiente:

Selection {anchorNode: text, anchorOffset: 9, focusNode: text, focusOffset: 47, isCollapsed: false, …}
anchorNode
: 
text
anchorOffset
: 
9
baseNode
: 
text
baseOffset
: 
9
extentNode
: 
text
extentOffset
: 
47
focusNode
: 
text
focusOffset
: 
47
isCollapsed
: 
false
rangeCount
: 
1
type
: 
"Range"

En el mi caso, lo uso para dibujar una borbuja con la opción de crear un comentario:

const rect = rango.getBoundingClientRect();

posX = rect.left + window.scrollX;
posY = rect.top + window.scrollY - 40;

Problemas con el window.getSelection();

El problema principal con el uso de window.getSelection(); es que si no tenemos un parrafo limpio como el siguiente:

<p id="p_1739646025565_337622">Laravel, al igua<span title="Test" id="_p_1739646025565_337622" class="bg-purple-700 rounded-sm no-set-note text-white">l que otros frame</span>works, puede&nbsp;ejecutarse en diversos entornos tanto en ambiente de producción como de desarrollo:</p>

Si no algo como:

<p id="p_1739646025565_337622">Laravel, al igua<span title="Test" id="_p_1739646025565_337622" class="bg-purple-700 rounded-sm no-set-note text-white">l que otros frame</span>works, <span id="span_1739646025565_102820">puede&nbsp;ejecutarse en diversos entornos tanto en ambiente de producción como de desarrollo:</span></p>

Y si por ejemplo, queremos seleccionar el texto de “iversos entornos tanto en ambien”, es decir, el texto justo al lado del SPAN, el rango definido será a partir del SPAN y no de todo el parrafo, por lo tanto, cualquier operación que queramos hacer, la posición estará vinculada al SPAN y no al párrafo lo cual es un gran problema ya que no es posible al menos de una manera sencilla, poder crear los rangos desde el párrafo.

Recuperar el rango

El rango, debemos de registrarlo si deseamos poder crear el mismo bajo de manda, para ello:

this.$axios
.post(this.$root.urls.bsnCreate + this.section.id, {
  title: this.form.title,
  content: this.form.content,
  json: {
    text: this.bubbleSelectecOptions.selectionText.substring(0, 10),
    id: this.bubbleSelectecOptions.selectionId, // Guarda el ID del elemento padre
    start: this.bubbleSelectecOptions.selectionRangeStart,
    end: this.bubbleSelectecOptions.selectionRangeEnd
  }

Y para construirlo o reconstruirlo:

async addHighlights(id, start, end, noteTitle, noteContent) {
  // const node = document.querySelector("#" + id).firstChild.nodeValue
  if (id.trim() == "")
    return this.$toast.warning(this.$t('large.noteBookRangeNoValid'))

  const node = document.querySelector("#" + id).firstChild
  const rango = document.createRange();

  try {
    rango.setStart(node, start);
    rango.setEnd(node, end);

    const span = document.createElement("span");
    span.title = noteTitle;
    span.id = "_" + id;

    span.onclick = function () {
      this.bubbleSelectecOptions.titleNote = noteTitle
      this.bubbleSelectecOptions.contentNote = noteContent
      this.bubbleSelectecOptions.showModalNoteUser = true
      this.bubbleSelectecOptions.modalKey3 = Date()
    }.bind(this);

    span.className = "bg-purple-700 rounded-sm no-set-note text-white";

    rango.surroundContents(span);
  } catch (error) {
    console.error(error)
  }

},

- Andrés Cruz

In english

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz En Udemy

Acepto recibir anuncios de interes sobre este Blog.