diff --git a/2-ui/99-ui-misc/02-selection-range/article.md b/2-ui/99-ui-misc/02-selection-range/article.md index 6f4d6814b..8cc96a972 100644 --- a/2-ui/99-ui-misc/02-selection-range/article.md +++ b/2-ui/99-ui-misc/02-selection-range/article.md @@ -4,37 +4,37 @@ libs: --- -# Selection and Range +# Selection y Range -In this chapter we'll cover selection in the document, as well as selection in form fields, such as ``. +En este capítulo cubriremos la selección en el documento, así como la selección en campos de formulario, como ``. -JavaScript can get the existing selection, select/deselect both as a whole or partially, remove the selected part from the document, wrap it into a tag, and so on. +JavaScript puede obtener la selección existente, seleccionar/deseleccionar tanto en su totalidad como parcialmente, eliminar la parte seleccionada del documento, envolverla en una etiqueta, etc. -You can get ready to use recipes at the end, in "Summary" section. But you'll get much more if you read the whole chapter. The underlying `Range` and `Selection` objects are easy to grasp, and then you'll need no recipes to make them do what you want. +Tu podrías usar ahora mismo las recetas que hay al final, En la sección "Resumen". Pero será mucho más beneficioso para ti si lees todo el capítulo. Los objetos subyacentes `Range` y `Selection` son fáciles de captar y, por lo tanto, no necesitará recetas para que hagan lo que deseas. ## Range -The basic concept of selection is [Range](https://dom.spec.whatwg.org/#ranges): basically, a pair of "boundary points": range start and range end. +El concepto básico de selección [Range](https://dom.spec.whatwg.org/#ranges), es básicamente un par de "puntos límite": inicio y fin del rango. -Each point represented as a parent DOM node with the relative offset from its start. If the parent node is an element node, then the offset is a child number, for a text node it's the position in the text. Examples to follow. +Cada punto es representado como un nodo DOM principal con el desplazamiento relativo desde su inicio. Si el nodo principal es un nodo de elemento, entonces el desplazamiento es un número secundario, para un nodo de texto es la posición en el texto. Ejemplos a continuación. -Let's select something. +Seleccionemos algo. -First, we can create a range (the constructor has no parameters): +Primero, podemos crear un rango (el constructor no tiene parámetros): ```js let range = new Range(); ``` -Then we can set the selection boundaries using `range.setStart(node, offset)` and `range.setEnd(node, offset)`. +Entonces podemos establecer los límites de selección usando `range.setStart(node, offset)` y `range.setEnd(node, offset)`. -For example, consider this fragment of HTML: +Por ejemplo, considere este fragmento de HTML: ```html

Example: italic and bold

``` -Here's its DOM structure, note that here text nodes are important for us: +Aquí está su estructura DOM, tenga en cuenta que aquí los nodos de texto son importantes para nosotros:
@@ -72,7 +72,7 @@ let selectPDomtree = { drawHtmlTree(selectPDomtree, 'div.select-p-domtree', 690, 320); -Let's select `"Example: italic"`. That's two first children of `

` (counting text nodes): +Seleccionamos `"Example: italic"`. Son los dos primeros hijos de `

` (contando nodos de texto): ![](range-example-p-0-1.svg) @@ -87,18 +87,18 @@ Let's select `"Example: italic"`. That's two first children of `

` (cou range.setEnd(p, 2); */!* - // toString of a range returns its content as text (without tags) - alert(range); // Example: italic + // toString de un rango devuelve su contenido como texto (sin etiquetas) + alert(range); // Ejemplo: italic - // apply this range for document selection (explained later) + // aplicar este rango para la selección de documentos (explicado más adelante) document.getSelection().addRange(range); ``` -- `range.setStart(p, 0)` -- sets the start at the 0th child of `

` (that's the text node `"Example: "`). -- `range.setEnd(p, 2)` -- spans the range up to (but not including) 2nd child of `

` (that's the text node `" and "`, but as the end is not included, so the last selected node is ``). +- `range.setStart(p, 0)` -- establece el comienzo en el hijo 0 de `

` (ese es el nodo de texto `"Example: "`). +- `range.setEnd(p, 2)` -- abarca el rango hasta (pero sin incluir) el segundo hijo de `

` (ese es el nodo de texto `" and "`, pero como el final no está incluido, el último nodo seleccionado es ``). -Here's a more flexible test stand where you try more variants: +Aquí hay un banco de pruebas más flexible en el que probar más variantes: ```html run autorun

Example: italic and bold

@@ -114,30 +114,30 @@ From – To ample: ") -- ends at the position 3 in `` first child (taking first three letters of "bold", but no more): +Necesitamos crear un rango, que: +- comienza desde la posición 2 en `

` primer hijo (tomando todas menos dos primeras letras de "Example:") +- termina en la posición 3 de `` primer hijo (tomando las primeras tres letras de "bold", pero no más): ```html run

Example: italic and bold

@@ -148,64 +148,64 @@ We need to create a range, that: range.setStart(p.firstChild, 2); range.setEnd(p.querySelector('b').firstChild, 3); - alert(range); // ample: italic and bol + alert(range); // amplio: italic and bol - // use this range for selection (explained later) + // use este rango para la selección (explicado más adelante) window.getSelection().addRange(range); ``` -The range object has following properties: +El objeto de rango tiene las siguientes propiedades: ![](range-example-p-2-b-3-range.svg) -- `startContainer`, `startOffset` -- node and offset of the start, - - in the example above: first text node inside `

` and `2`. -- `endContainer`, `endOffset` -- node and offset of the end, - - in the example above: first text node inside `` and `3`. -- `collapsed` -- boolean, `true` if the range starts and ends on the same point (so there's no content inside the range), - - in the example above: `false` -- `commonAncestorContainer` -- the nearest common ancestor of all nodes within the range, - - in the example above: `

` +- `startContainer`, `startOffset` -- nodo y desplazamiento del inicio, + - en el ejemplo anterior: primer nodo de texto dentro de `

` y `2`. +- `endContainer`, `endOffset` -- nodo y desplazamiento del final, + - en el ejemplo anterior: primer nodo de texto dentro de `` y `3`. +- `collapsed` -- booleano, `true` si el rango comienza y termina en el mismo punto (por lo que no hay contenido dentro del rango), + - en el ejemplo anterior: `false` +- `commonAncestorContainer` -- el ancestro común más cercano de todos los nodos dentro del rango, + - en el ejemplo anterior: `

` -## Range methods +## Métodos de Range -There are many convenience methods to manipulate ranges. +Hay muchos métodos convenientes para manipular rangos. -Set range start: +Establecer inicio de rango: -- `setStart(node, offset)` set start at: position `offset` in `node` -- `setStartBefore(node)` set start at: right before `node` -- `setStartAfter(node)` set start at: right after `node` +- `setStart(node, offset)` establecer inicio en: posición `offset` en `node` +- `setStartBefore(node)` establecer inicio en: justo antes `node` +- `setStartAfter(node)` establecer inicio en: justo después `node` -Set range end (similar methods): +Establecer fin de rango (métodos similares): -- `setEnd(node, offset)` set end at: position `offset` in `node` -- `setEndBefore(node)` set end at: right before `node` -- `setEndAfter(node)` set end at: right after `node` +- `setEnd(node, offset)` establecer final en: posición `offset` en `node` +- `setEndBefore(node)` establecer final en: justo antes `node` +- `setEndAfter(node)` establecer final en: justo después `node` -**As it was demonstrated, `node` can be both a text or element node: for text nodes `offset` skips that many of characters, while for element nodes that many child nodes.** +**Como quedó demostrado, `node` puede ser un nodo de texto o de elemento: para nodos de texto `offset` omite esa cantidad de caracteres, mientras que para los nodos de elementos esa cantidad de nodos secundarios.** -Others: -- `selectNode(node)` set range to select the whole `node` -- `selectNodeContents(node)` set range to select the whole `node` contents -- `collapse(toStart)` if `toStart=true` set end=start, otherwise set start=end, thus collapsing the range -- `cloneRange()` creates a new range with the same start/end +Otros: +- `selectNode(node)` establecer rango para seleccionar el `node` +- `selectNodeContents(node)` establecer rango para seleccionar todo el contenido de `node` +- `collapse(toStart)` si `toStart=true` establece final=comienzo, de otra manera comienzo=final, colapsando así el rango +- `cloneRange()` crea un nuevo rango con el mismo inicio/final -To manipulate the content within the range: +Para manipular el contenido dentro del rango: -- `deleteContents()` -- remove range content from the document -- `extractContents()` -- remove range content from the document and return as [DocumentFragment](info:modifying-document#document-fragment) -- `cloneContents()` -- clone range content and return as [DocumentFragment](info:modifying-document#document-fragment) -- `insertNode(node)` -- insert `node` into the document at the beginning of the range -- `surroundContents(node)` -- wrap `node` around range content. For this to work, the range must contain both opening and closing tags for all elements inside it: no partial ranges like `abc`. +- `deleteContents()` -- eliminar el contenido de rango del documento +- `extractContents()` -- eliminar el contenido de rango del documento y lo retorna como [DocumentFragment](info:modifying-document#document-fragment) +- `cloneContents()` -- clonar el contenido del rango y lo retorna como [DocumentFragment](info:modifying-document#document-fragment) +- `insertNode(node)` -- inserta `node` en el documento al comienzo del rango +- `surroundContents(node)` --envuelve `node` alrededor del contenido del rango. Para que esto funcione, el rango debe contener etiquetas de apertura y cierre para todos los elementos dentro de él: no hay rangos parciales como `abc`. -With these methods we can do basically anything with selected nodes. +Con estos métodos podemos hacer básicamente cualquier cosa con los nodos seleccionados. -Here's the test stand to see them in action: +Aquí está el banco de pruebas para verlos en acción: ```html run autorun height=260 -Click buttons to run methods on the selection, "resetExample" to reset it. +Haga clic en los botones para ejecutar métodos en la selección, "resetExample" para restablecerla.

Example: italic and bold

@@ -213,7 +213,7 @@ Click buttons to run methods on the selection, "resetExample" to reset it. ``` -There also exist methods to compare ranges, but these are rarely used. When you need them, please refer to the [spec](https://dom.spec.whatwg.org/#interface-range) or [MDN manual](https://developer.mozilla.org/en-US/docs/Web/API/Range). +También existen métodos para comparar rangos, pero rara vez se utilizan. Cuando los necesite, consulte el [spec](https://dom.spec.whatwg.org/#interface-range) o [MDN manual](https://developer.mozilla.org/en-US/docs/Web/API/Range). ## Selection -`Range` is a generic object for managing selection ranges. We may create such objects, pass them around -- they do not visually select anything on their own. +`Range` es un objeto genérico para gestionar rangos de selección. Podemos crear tales objetos, pasarlos alrededor -- no seleccionan visualmente nada por sí mismos. -The document selection is represented by `Selection` object, that can be obtained as `window.getSelection()` or `document.getSelection()`. +La selección de documentos está representada por el objeto `Selection`, que se puede obtener como `window.getSelection()` o `document.getSelection()`. -A selection may include zero or more ranges. At least, the [Selection API specification](https://www.w3.org/TR/selection-api/) says so. In practice though, only Firefox allows to select multiple ranges in the document by using `key:Ctrl+click` (`key:Cmd+click` for Mac). +Una selección puede incluir cero o más rangos. Al menos, el [Selection API specification](https://www.w3.org/TR/selection-api/) lo dice. Sin embargo, en la práctica, solo Firefox permite seleccionar múltiples rangos en el documento usando `key:Ctrl+click` (`key:Cmd+click` para Mac). -Here's a screenshot of a selection with 3 ranges, made in Firefox: +Aquí hay una captura de pantalla de una selección con 3 rangos, realizada en Firefox: ![](selection-firefox.svg) -Other browsers support at maximum 1 range. As we'll see, some of `Selection` methods imply that there may be many ranges, but again, in all browsers except Firefox, there's at maximum 1. +Otros navegadores admiten un rango máximo de 1. Como veremos, algunos de los métodos de `Selection` implica que puede haber muchos rangos, pero nuevamente, en todos los navegadores excepto Firefox, hay un máximo de 1. -## Selection properties +## Propiedades de Selection -Similar to a range, a selection has a start, called "anchor", and the end, called "focus". +Similar a Range, una selección tiene un inicio, llamado "ancla(anchor)", y un final, llamado "foco(focus)". -The main selection properties are: +Las principales propiedades de selection son: -- `anchorNode` -- the node where the selection starts, -- `anchorOffset` -- the offset in `anchorNode` where the selection starts, -- `focusNode` -- the node where the selection ends, -- `focusOffset` -- the offset in `focusNode` where the selection ends, -- `isCollapsed` -- `true` if selection selects nothing (empty range), or doesn't exist. -- `rangeCount` -- count of ranges in the selection, maximum `1` in all browsers except Firefox. +- `anchorNode` -- el nodo donde comienza la selección, +- `anchorOffset` -- el desplazamiento en `anchorNode` donde comienza la selección, +- `focusNode` -- el nodo donde termina la selección, +- `focusOffset` -- el desplazamiento en `focusNode` donde termina la selección, +- `isCollapsed` -- `true` si la selección no selecciona nada (rango vacío), o no existe. +- `rangeCount` -- recuento de rangos en la selección, máximo "1" en todos los navegadores excepto Firefox. -````smart header="Selection end may be in the document before start" -There are many ways to select the content, depending on the user agent: mouse, hotkeys, taps on a mobile etc. +````smart header="El final de la selección puede estar en el documento antes del inicio" +Hay muchas formas de seleccionar el contenido, dependiendo del agente de usuario: mouse, teclas de acceso rápido, toques en un móvil, etc. -Some of them, such as a mouse, allow the same selection can be created in two directions: "left-to-right" and "right-to-left". +Algunos de ellos, como un mouse, permiten que se pueda crear la misma selección en dos direcciones: "de izquierda a derecha" y "de derecha a izquierda". -If the start (anchor) of the selection goes in the document before the end (focus), this selection is said to have "forward" direction. +Si el inicio (ancla) de la selección va en el documento antes del final (foco), se dice que esta selección tiene una dirección "hacia adelante". -E.g. if the user starts selecting with mouse and goes from "Example" to "italic": +Ej. si el usuario comienza a seleccionar con el mouse y pasa de "Example" a "italic": ![](selection-direction-forward.svg) -Otherwise, if they go from the end of "italic" to "Example", the selection is directed "backward", its focus will be before the anchor: +De lo contrario, si van desde el final de "italic" to "Example", la selección se dirige "hacia atrás", su foco estará antes del ancla: ![](selection-direction-backward.svg) -That's different from `Range` objects that are always directed forward: the range start can't be after its end. +Eso es diferente de los objetos `Range` que siempre se dirigen hacia adelante: el inicio del rango no puede ser posterior a su final. ```` -## Selection events +## Eventos Selection -There are events on to keep track of selection: +Hay eventos para realizar un seguimiento de la selección: -- `elem.onselectstart` -- when a selection starts on `elem`, e.g. the user starts moving mouse with pressed button. - - Preventing the default action makes the selection not start. -- `document.onselectionchange` -- whenever a selection changes. - - Please note: this handler can be set only on `document`. +- `elem.onselectstart` -- cuando una selección comienza en `elem`, ej. el usuario comienza a mover el mouse con el botón presionado. + - Evitar la acción predeterminada hace que la selección no se inicie. +- `document.onselectionchange` -- siempre que cambie una selección. + - Tenga en cuenta: este controlador solo se puede configurar en `document`. -### Selection tracking demo +### Demostración de seguimiento de selección -Here's a small demo that shows selection boundaries dynamically as it changes: +Aquí hay una pequeña demostración que muestra los límites de selección de forma dinámica a medida que cambia: ```html run height=80

Select me: italic and bold

@@ -334,13 +334,13 @@ From – To ``` -### Selection getting demo +### Demostración de obtención de selección -To get the whole selection: -- As text: just call `document.getSelection().toString()`. -- As DOM nodes: get the underlying ranges and call their `cloneContents()` method (only first range if we don't support Firefox multiselection). +Para obtener toda la selección: +- Como texto: solo llama `document.getSelection().toString()`. +- Como nodos DOM: obtenga los rangos subyacentes y llame a su método `cloneContents()` (solo el primer rango si no admitimos la selección múltiple de Firefox). -And here's the demo of getting the selection both as text and as DOM nodes: +Y aquí está la demostración de cómo obtener la selección como texto y como nodos DOM: ```html run height=100

Select me: italic and bold

@@ -355,104 +355,104 @@ As text: cloned.innerHTML = astext.innerHTML = ""; - // Clone DOM nodes from ranges (we support multiselect here) + // Clonar nodos DOM de rangos (admitimos selección múltiple aquí) for (let i = 0; i < selection.rangeCount; i++) { cloned.append(selection.getRangeAt(i).cloneContents()); } - // Get as text + // Obtener como texto astext.innerHTML += selection; }; ``` -## Selection methods +## Métodos Selection -Selection methods to add/remove ranges: +Métodos de selección para agregar/eliminar rangos: -- `getRangeAt(i)` -- get i-th range, starting from `0`. In all browsers except firefox, only `0` is used. -- `addRange(range)` -- add `range` to selection. All browsers except Firefox ignore the call, if the selection already has an associated range. -- `removeRange(range)` -- remove `range` from the selection. -- `removeAllRanges()` -- remove all ranges. -- `empty()` -- alias to `removeAllRanges`. +- `getRangeAt(i)` -- obtener el rango i-ésimo, comenzando desde "0". En todos los navegadores, excepto Firefox, solo se utiliza `0`. +- `addRange(rango)` -- agrega un `rango` a la selección. Todos los navegadores excepto Firefox ignoran la llamada, si la selección ya tiene un rango asociado. +- `removeRange(rango)` --elimina `rango` de la selección. +- `removeAllRanges()` --elimina todos los rangos. +- `empty()` -- alias para `removeAllRanges`. -Also, there are convenience methods to manipulate the selection range directly, without `Range`: +Además, existen métodos convenientes para manipular el rango de selección directamente, sin `Range`: -- `collapse(node, offset)` -- replace selected range with a new one that starts and ends at the given `node`, at position `offset`. -- `setPosition(node, offset)` -- alias to `collapse`. -- `collapseToStart()` - collapse (replace with an empty range) to selection start, -- `collapseToEnd()` - collapse to selection end, -- `extend(node, offset)` - move focus of the selection to the given `node`, position `offset`, -- `setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset)` - replace selection range with the given start `anchorNode/anchorOffset` and end `focusNode/focusOffset`. All content in-between them is selected. -- `selectAllChildren(node)` -- select all children of the `node`. -- `deleteFromDocument()` -- remove selected content from the document. -- `containsNode(node, allowPartialContainment = false)` -- checks whether the selection contains `node` (partially if the second argument is `true`) +- `collapse(node, offset)` -- Reemplazar el rango seleccionado con uno nuevo que comienza y termina en el `node` dado, en posición `offset`. +- `setPosition(node, offset)` -- alias para `collapse`. +- `collapseToStart()` - colapsar (reemplazar con un rango vacío) al inicio de la selección, +- `collapseToEnd()` - colapso hasta el final de la selección, +- `extend(node, offset)` - mover el foco de la selección al `node` dado, posición `offset`, +- `setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset)` - reemplazar el rango de selección con el inicio dado `anchorNode/anchorOffset` y final `focusNode/focusOffset`. Se selecciona todo el contenido entre ellos. +- `selectAllChildren(node)` -- seleccionar todos los hijos del `node`. +- `deleteFromDocument()` -- eliminar el contenido seleccionado del documento. +- `containsNode(node, allowPartialContainment = false)` -- comprueba si la selección contiene `node` (parcialmente si el segundo argumento es `true`) -So, for many tasks we can call `Selection` methods, no need to access the underlying `Range` object. +Entonces, para muchas tareas podemos llamar a los métodos de `Selection`, y no es necesario acceder al objeto `Range` subyacente. -For example, selecting the whole contents of the paragraph `

`: +Por ejemplo, seleccionando todo el contenido del párrafo `

`: ```html run

Select me: italic and bold

``` -The same thing using ranges: +Lo mismo usando rangos: ```html run

Select me: italic and bold

``` -```smart header="To select, remove the existing selection first" -If the selection already exists, empty it first with `removeAllRanges()`. And then add ranges. Otherwise, all browsers except Firefox ignore new ranges. +```smart header="Para seleccionar, primero elimine la selección existente" +Si la selección ya existe, vacíelo primero con `removeAllRanges()`. Y luego agregue rangos. De lo contrario, todos los navegadores excepto Firefox ignoran los nuevos rangos. -The exception is some selection methods, that replace the existing selection, like `setBaseAndExtent`. +La excepción son algunos métodos de selección, que reemplazan la selección existente, como `setBaseAndExtent`. ``` -## Selection in form controls +## Selección en controles de formulario -Form elements, such as `input` and `textarea` provide [special API for selection](https://html.spec.whatwg.org/#textFieldSelection), without `Selection` or `Range` objects. As an input value is a pure text, not HTML, there's no need for such objects, everything's much simpler. +Elementos de formulario, como `input` y `textarea` proporciona [API especial para la selección](https://html.spec.whatwg.org/#textFieldSelection), sin objetos `Selection` o `Range`. Como un valor de entrada es un texto puro, no HTML, no hay necesidad de tales objetos, todo es mucho más simple. -Properties: -- `input.selectionStart` -- position of selection start (writeable), -- `input.selectionEnd` -- position of selection end (writeable), -- `input.selectionDirection` -- selection direction, one of: "forward", "backward" or "none" (if e.g. selected with a double mouse click), +Propiedades: +- `input.selectionStart` -- posición de inicio de selección (escribible), +- `input.selectionEnd` -- posición del final de la selección (escribible), +- `input.selectionDirection` -- dirección de selección, una de: "adelante" "hacia atrás" o "ninguno" (si, por ejemplo, se selecciona con un doble clic del mouse), -Events: -- `input.onselect` -- triggers when something is selected. +Eventos: +- `input.onselect` -- se activa cuando se selecciona algo. -Methods: +Métodos: -- `input.select()` -- selects everything in the text control (can be `textarea` instead of `input`), -- `input.setSelectionRange(start, end, [direction])` -- change the selection to span from position `start` till `end`, in the given direction (optional). -- `input.setRangeText(replacement, [start], [end], [selectionMode])` -- replace a range of text with the new text. +- `input.select()` -- selecciona todo en el control de texto (puede ser `textarea` en vez de `input`), +- `input.setSelectionRange(start, end, [direction])` -- cambiar la selección para abarcar desde la posición `start` hasta `end`, en la dirección indicada (opcional). +- `input.setRangeText(replacement, [start], [end], [selectionMode])` -- reemplace un rango de texto con el nuevo texto. - Optional arguments `start` and `end`, if provided, set the range start and end, otherwise user selection is used. + Los argumentos opcionales `start` y `end`, si se proporcionan, establecen el inicio y el final del rango; de lo contrario, se utiliza la selección del usuario. - The last argument, `selectionMode`, determines how the selection will be set after the text has been replaced. The possible values are: + El último argumento, `selectionMode`, determina cómo se establecerá la selección después de que se haya reemplazado el texto. Los posibles valores son: - - `"select"` -- the newly inserted text will be selected. - - `"start"` -- the selection range collapses just before the inserted text (the cursor will be immediately before it). - - `"end"` -- the selection range collapses just after the inserted text (the cursor will be right after it). - - `"preserve"` -- attempts to preserve the selection. This is the default. + - `"select"` -- se seleccionará el texto recién insertado. + - `"start"` -- el rango de selección se colapsa justo antes del texto insertado (el cursor estará inmediatamente antes). + - `"end"` -- el rango de selección se colapsa justo después del texto insertado (el cursor estará justo después). + - `"preserve"` -- intenta preservar la selección. Este es el predeterminado. -Now let's see these methods in action. +Ahora veamos estos métodos en acción. -### Example: tracking selection +### Ejemplo: Seguimiento de selección -For example, this code uses `onselect` event to track selection: +Por ejemplo, este código usa el evento `onselect` para rastrear la selección: ```html run autorun