Lisez-moi S.V.P. 

13 novembre 2000

2. Le modèle objet de document Range

Rédacteurs
Peter Sharpe, SoftQuad Software Inc.
Vidur Apparao, Netscape Communications Corp.
Lauren Wood, SoftQuad Software Inc.

Table des matières

2.1. Introduction

L'objet Range identifie une étendue de contenu dans un objet Document, DocumentFragment ou Attr. Elle est contiguë au sens où on peut la caractériser comme sélectionnant tout le contenu entre un couple de points limites.

Remarque : Dans un éditeur de texte ou un traitement de texte, l'utilisateur peut effectuer une sélection en pressant le bouton de la souris à un point du document puis en la déplaçant jusqu'à un autre point et enfin en relâchant le bouton de la souris. La sélection résultante est contiguë et se compose du contenu entre les deux points.

Le terme « sélection » ne signifie pas que toute étendue Range correspond à une sélection par l'utilisateur d'une interface graphique (GUI) ; par contre, une telle sélection pourra être retournée à un utilisateur DOM comme étendue Range.

Remarque : Dans une écriture bidirectionnelle (arabe, hébreu), une étendue peut correspondre à une sélection logique qui n'est pas forcément contiguë à l'affichage. Une sélection visuelle contiguë, utilisée dans certains cas également, ne correspondra peut-être pas à une seule sélection logique et pourra donc être représentée par plusieurs étendues.

L'interface Range fournit des méthodes permettant d'accéder et de manipuler l'arbre du document à un niveau supérieur à celui des méthodes similaires de l'interface Node. Chaque méthode fournie par l'interface Range pour insérer, supprimer et copier un contenu est censée correspondre directement à une série d'opérations d'édition via l'interface Node du module DOM Core. Dans cette optique, on peut considérer les opérations de l'interface Range comme des méthodes commodes qui permettent aussi à la mise en œuvre d'optimiser des motifs d'édition courants.

Ce chapitre décrit l'interface Range, dont des méthodes pour créer et déplacer une étendue Range et des méthodes pour manipuler un contenu avec des étendues Range.

Les interfaces trouvées dans cette section ne sont pas obligatoires. Une application DOM peut employer la méthode hasFeature(feature, version) de l'interface DOMImplementation, respectivement avec les valeurs de paramètre "Range" et "2.0", pour déterminer si ce module est reconnu ou non par la mise en œuvre. Pour la gestion complète de ce module, une mise en œuvre doit également gérer la fonctionnalité "Core", définie dans la spécification DOM niveau 2 Core [DOM niveau 2 Core]. Consulter la section à propos de la conformité→vf dans la spécification DOM niveau 2 Core [DOM niveau 2 Core] pour d'autres renseignements.

2.2. Les définitions et la notation

2.2.1. La position

Cette section renvoie à deux représentations différentes d'un document : la forme textuelle, ou source, qui comprend le balisage du document, et la forme en arbre similaire à celle décrite en introduction du DOM niveau 2 Core [DOM niveau 2 Core].

L'étendue Range se compose de deux points limites correspondant au début et à la fin de l'étendue. On peut caractériser la position d'un point de limite, dans l'arbre d'un nœud Document ou DocumentFragment, par un nœud et un décalage. On appelle ce nœud le conteneur du point limite et de sa position. Le conteneur et ses ancêtres sont les conteneurs ancêtres du point limite et de sa position. Le décalage à l'intérieur du nœud est appelé le décalage du point limite et de sa position. Si le conteneur est un nœud Attr, Document, DocumentFragment, Element ou EntityReference, le décalage se trouve entre ses nœuds enfants Si le conteneur est un nœud CharacterData, Comment ou ProcessingInstruction, le décalage se trouve entre les unités de 16 bits de la chaîne de caractères codée en UTF-16 contenu par le nœud.

Les points limites d'une étendue Range doivent avoir un conteneur ancêtre commun de type Document, DocumentFragment ou Attr. C'est-à-dire que le contenu d'une étendue Range doit se trouver entièrement dans le sous-arbre prenant racine dans un seul nœud Document, DocumentFragment ou Attr. Ce conteneur ancêtre commun est appelé le conteneur racine de l'étendue Range. L'arbre enraciné dans le conteneur racine s'appelle l'arbre de contexte de l'étendue Range.

Le conteneur d'un point limite d'une étendue Range doit être un nœud de type Element, Comment, ProcessingInstruction, EntityReference, CDATASection, Document, DocumentFragment, Attr ou Text. Aucun conteneur ancêtre d'un point limite de l'étendue Range ne peut être un nœud de type DocumentType, Entity ou Notation.

En ce qui concerne la représentation textuelle d'un document, les points limites de l'étendue Range peuvent se trouver seulement aux frontières d'un atome. C'est-à-dire qu'un point limite d'une étendue de texte ne peut pas se trouver au milieu de la balise ouvrante ou fermante d'un élément, ou encore dans le nom d'une entité ou d'un appel de caractère. L'étendue Range repère une portion contiguë de contenu du modèle de structure.

Les relations entre les positions dans la représentation textuelle d'un document et l'interface arborescente à nœuds Node du DOM sont illustrées dans le diagramme suivant :


Exemple d'étendue
Exemple d'étendues

Dans ce diagramme, on montre quatre étendues différentes. Les points limites de chaque étendue Range sont repérés par « dX » (le début de l'étendue) et par « fX » (la fin de l'étendue), où « X » est le numéro de l'étendue. Pour l'étendue 2, elle débute dans l'élément BODY, immédiatement après l'élément H1 et immédiatement avant l'élément P, et sa position est donc entre les enfants H1 et P de BODY. Le décalage d'un point limite dont le conteneur n'est pas un nœud CharacterData est de 0, si le point se trouve avant le premier enfant, de 1, s'il se trouve entre le premier et le deuxième enfant, et ainsi de suite. Donc, pour le début de l'étendue 2, le conteneur est BODY et le décalage est de 1. Le décalage d'un point limite dont le conteneur est un nœud CharacterData se détermine de façon similaire, cette fois en utilisant la position des unités de 16 bits. Par exemple, le point limite repéré par « d1 » de l'étendue 1 a pour conteneur un nœud Text (celui qui contient "Titre") et a un décalage de 2, puisqu'il se trouve entre la deuxième et la troisième unité de 16 bits.

Remarquer que les points limites des étendues 3 et 4 correspondent au même emplacement dans la représentation textuelle. Un aspect essentiel des étendues est que le point limite d'une étendue Range peut représenter sans ambiguïté n'importe quelle position dans l'arbre du document.

On peut déterminer les conteneurs et les décalages des points limites grâce aux attributs suivants (en lecture seule) de l'étendue Range :

  readonly attribute Node startContainer; 
  readonly attribute long startOffset;
  readonly attribute Node endContainer; 
  readonly attribute long endOffset;

Si les points limites d'une étendue Range ont les mêmes conteneurs et décalages, on dit de l'étendue qu'elle se rétracte. (Dans un agent utilisateur, cela renvoie souvent au point d'insertion).

2.2.2. La sélection et la sélection partielle

Un nœud, ou une unité de 16 bits, est dit sélectionné par une étendue Range s'il se trouve entre les deux points limites de cette étendue Range, c'est-à-dire si la position immédiatement avant le nœud, ou l'unité de 16 bits, est située avant la fin de l'étendue et si la position immédiatement après le nœud, ou l'unité de 16 bits, est située après le début de l'étendue. Par exemple, dans une représentation textuelle d'un document, un élément sera sélectionné par une étendue Range si sa balise ouvrante correspondante est située après le début de l'étendue et sa balise fermante située avant la fin de l'étendue. Dans les exemples du diagramme précédent, l'étendue 2 sélectionne le nœud P et l'étendue 3 le nœud de texte contenant le texte "Blah xyz."

On dit qu'un nœud est partiellement sélectionné par une étendue Range si c'est un conteneur ancêtre pour exactement un seul point limite de l'étendue. Par exemple, prenons l'étendue 1 du diagramme précédent. L'élément H1 est partiellement sélectionné par cette étendue Range car le début de l'étendue se trouve dans l'un de ses enfants.

2.2.3. La notation

Plusieurs exemples de ce chapitre sont illustrés en s'inspirant d'une représentation textuelle du document. Les points limites d'une étendue Range sont signalés par un affichage des caractères (qu'il s'agisse de balisage ou de données textuelles) entre les deux points limites dans une graisse plus forte comme suit :

    <TRUC>ABC<MUCHE>DEF</MUCHE></TRUC>
                 

Quand les deux points limites sont à la même position, ils sont signalés par un caractère signe d'insertion « ^ » dans une graisse plus forte comme suit :

    <TRUC>A^BC<MUCHE>DEF</MUCHE></TRUC>

2.3. La création d'une étendue

On crée une étendue Range en appelant la méthode createRange() de l'interface DocumentRange. On peut obtenir cette interface à partir de l'objet qui met en œuvre l'interface Document en utilisant les méthodes prépondérantes spécifiques de la liaison.

  interface DocumentRange {
    Range createRange();
  }

L'état initial de l'étendue Range retournée par cette méthode est tel que les deux points limites sont positionnés au début du nœud Document correspondant, avant tout contenu. En d'autres termes, le conteneur de chaque point limite est le nœud Document et le décalage dans ce nœud est de 0.

Comme pour certains objets créés en utilisant les méthodes de l'interface Document (tels que les nœuds Node et DocumentFragment), les étendues Range créées via une instance de document particulière peuvent seulement sélectionner un contenu associé à ce nœud Document, ou bien aux objets DocumentFragment et Attr dont l'attribut ownerDocument désigne le nœud Document en question. On ne peut donc pas utiliser ces étendues Range avec d'autres instances de l'objet Document.

2.4. Le changement de la position d'une étendue

On peut définir la position d'une étendue Range en paramétrant le conteneur et le décalage de chaque point limite à l'aide des méthodes setStart() et setEnd().

  void setStart(in Node parent, in long offset)
                        raises(RangeException);
  void setEnd(in Node parent, in long offset)
                raises(RangeException);

Si l'un des points limites d'une étendue Range est fixé avec un autre conteneur racine que le conteneur actuel de l'étendue Range, l'étendue se rétracte à cette nouvelle position. Cela pour respecter la restriction selon laquelle les deux points limites d'une étendue Range doivent avoir le même conteneur racine.

La position de début d'une étendue Range est assurée de ne jamais se trouver après sa position de fin. Pour respecter cette restriction, si on fixe le début à une position après celle de fin, alors l'étendue Range se rétracte à cette nouvelle position. Et inversement, si on fixe la fin à une position avant celle de début, l'étendue se rétracte à la nouvelle position.

On peut également fixer la position de l'étendue Range par rapport aux nœuds dans l'arbre :

  void setStartBefore(in Node node);
                              raises(RangeException);
  void setStartAfter(in Node node);
                       raises(RangeException);
  void setEndBefore(in Node node);
                      raises(RangeException);
  void setEndAfter(in Node node);
                     raises(RangeException);

Le parent du nœud devient le conteneur du point limite et l'étendue Range est soumise aux mêmes restrictions que celles indiquées dans la description des méthodes setStart() et setEnd().

L'étendue Range peut se rétracter à l'un ou l'autre point limite :

  void collapse(in boolean toStart);

La valeur true du paramètre toStart entraînera la rétractation de l'étendue Range à sa position de début, et une valeur false à celle de fin.

On peut tester si une étendue Range s'est rétractée en examinant la valeur de l'attribut collapsed :

  readonly attribute boolean collapsed;

Les méthodes suivantes peuvent servir pour qu'une étendue Range sélectionne le contenu d'un nœud ou le nœud même.

  void selectNode(in Node n);
  void selectNodeContents(in Node n);

Les exemples suivants illustrent l'action des méthodes selectNode() et selectNodeContents() :

Avant :
  ^<MUCHE><TRUC>A<CHOSE>B</CHOSE>C</TRUC></MUCHE>
Après Range.selectNodeContents(TRUC) :
  <MUCHE><TRUC>A<CHOSE>B</CHOSE>C</TRUC></MUCHE>
(Dans ce cas, TRUC est le parent des deux points limites)
Après Range.selectNode(TRUC) :

<MUCHE><TRUC>A<CHOSE>B</CHOSE>C</TRUC></MUCHE>

2.5. La comparaison des points limites de deux étendues

On peut comparer deux étendues Range en comparant leurs points limites :

  short compareBoundaryPoints(in CompareHow how, in Range sourceRange) raises(RangeException);

Où le paramètre CompareHow prend l'une de quatres valeurs : START_TO_START, START_TO_END, END_TO_END et END_TO_START. La valeur retournée est -1, 0 ou 1, selon que le point limite correspondant de l'étendue Range se trouve avant, est égal ou se trouve après le point limite correspondant de l'étendue Range désignée par l'attribut sourceRange. Une exception est soulevée si les deux étendues Range ont des conteneurs racines différents.

Le résultat de la comparaison de deux points limites (ou de deux positions) est précisé ci-dessous. Une définition informelle mais parfois inexacte est qu'un point limite se trouvera avant, sera égal ou se trouvera après un autre point limite s'il correspond, dans la représentation textuelle, à une position avant, égale ou après la position correspondante de l'autre point limite.

Soit deux points limites (ou positions) A et B. L'une des propositions suivantes sera alors vérifiée : A est avant B, A est égal à B, ou A est après B. On détermine celle qui est vérifiée en examinant les quatre cas suivants :

Premier cas : les points limites ont le même conteneur. A est avant B si son décalage est inférieur à celui de B ; A est égal à B si son décalage est égal à celui de B A est après B si son décalage est supérieur à celui de B.

Deuxième cas : un nœud enfant C du conteneur de A est un conteneur ancêtre de B. Auquel cas, A est avant B si le décalage de A est inférieur ou égal à l'index du nœud enfant C ; sinon A est après B.

Troisième cas : un nœud enfant C du conteneur de B est un conteneur ancêtre de A. Auquel cas, A est avant B si l'index du nœud enfant C est inférieur au décalage de B ; sinon A est après B.

Quatrième cas : aucun des trois autres cas n'est vérifié et les conteneurs de A et B sont frères ou des descendants de nœuds frères. Auquel cas, A est avant B si le conteneur de A est avant celui de B dans une traversée préordonnée de l'arbre de contexte des étendues Range ; sinonA est après B.

Remarquer que, puisqu'une même position dans la représentation textuelle du document peut correspondre à deux positions distinctes dans l'arbre DOM, il est possible que la comparaison de deux points limites ne corresponde pas à une égalité, quoiqu'elle le puisse dans la représentation textuelle. La définition informelle qui précède est donc parfois inexacte pour cette raison.

2.6. La suppression d'un contenu par une étendue

On peut supprimer le contenu sélectionné par une étendue Range :

  void deleteContents();

La méthode deleteContents() supprime tous les nœuds et caractères sélectionnés par l'étendue Range. Tous les autres nœuds et caractères restent dans l'arbre de contexte de l'étendue Range. Voici quelques exemples de suppression :

(1) <TRUC>AB<CHOSE>CD</CHOSE>CD</TRUC>
--> <TRUC>A^CD</TRUC>
(2) <TRUC>A<CHOSE>BC</CHOSE>DE</TRUC>
--> <TRUC>A<CHOSE>B</CHOSE>^E</TRUC>
(3) <TRUC>XY<MUCHE>ZW</MUCHE>Q</TRUC>
--> <TRUC>X^<MUCHE>W</MUCHE>Q</TRUC>
(4) <TRUC><MUCHE1>AB</MUCHE1><MUCHE2/><MUCHE3>CD</MUCHE3></TRUC>
--> <TRUC><MUCHE1>A</MUCHE1>^<MUCHE3>D</MUCHE3>

Après l'invocation de la méthode deleteContents() sur une étendue Range, celle-ci se rétracte. Si aucun nœud n'est partiellement sélectionné par l'étendue Range, alors l'étendue se rétracte à son point de début original, comme dans l'exemple (1). Si un nœud est partiellement sélectionné par l'étendue Range, et que ce nœud est un conteneur ancêtre du début de l'étendue Range, et qu'aucun ancêtre de ce nœud ne satisfasse aux deux premières conditions, alors l'étendue Range se rétracte à la position immédiatement après le nœud, comme dans les exemples (2) et (4). Si un nœud est partiellement sélectionné par l'étendue Range, et que ce nœud est un conteneur ancêtre de la fin de l'étendue Range, et qu'aucun ancêtre du nœud ne satisfasse à ces deux conditions, alors l'étendue Range se rétracte à la position immédiatement avant le nœud, comme dans les exemples (3) et (4).

Remarquer que si la suppression d'une étendue laisse des nœuds Text adjacents, ils ne fusionnent pas automatiquement et les nœuds vides ne sont pas retirés non plus. Deux nœuds Text devraient seulement être joints si chacun est le conteneur de l'un des points limites d'une étendue Range dont le contenu est supprimé. Pour fusionner des nœuds Text adjacents, ou retirer des nœuds Text vides, on devrait employer la méthode normalize() de l'interface Node.

2.7. L'extraction d'un contenu

Si on doit extraire le contenu d'une étendue Range au lieu de le supprimer, on peut utiliser la méthode suivante :

  DocumentFragment extractContents();

La méthode extractContents() retire les nœuds de l'arbre de contexte de l'étendue Range de façon similaire à la méthode deleteContents(). En outre, elle range le contenu supprimé dans un nouvel objet DocumentFragment. Les exemples suivants montrent le contenu de l'objet DocumentFragment retourné :

(1) <TRUC>AB<CHOSE>CD</CHOSE>CD</TRUC>
--> B<CHOSE>CD</CHOSE>
(2) <TRUC>A<CHOSE>BC</CHOSE>DE</TRUC>
--> <CHOSE>C<CHOSE>D
(3) <TRUC>XY<MUCHE>ZW</MUCHE>Q</TRUC>
--> Y<MUCHE>Z</MUCHE>
(4)
<TRUC><MUCHE1>AB</MUCHE1><MUCHE2/><MUCHE3>CD</MUCHE3></TRUC>
--> <MUCHE1>B</MUCHE1><MUCHE2/><MUCHE3>C</MUCHE3>

Il importe de remarquer que les nœuds partiellement sélectionnés par l'étendue Range sont clonés. Puisqu'une partie du contenu de ce nœud doit rester dans l'arbre de contexte de l'étendue Range et qu'une partie du contenu doit être déplacée dans le nouvel objet DocumentFragment, un clone du nœud partiellement sélectionné est inclus au nouvel objet DocumentFragment. Remarquer que le clonage n'intervient pas sur les éléments sélectionnés ; ces nœuds sont déplacés sur le nouvel objet DocumentFragment.

2.8. Le clonage d'un contenu

On peut dupliquer le contenu d'une étendue Range en utilisant la méthode suivante :

  DocumentFragment cloneContents();

Cette méthode retourne un objet DocumentFragment similaire à celui retourné par la méthode extractContents(). Dans ce cas, par contre, les nœuds et données textuelles d'origine dans l'étendue Range ne sont pas retirés de son arbre de contexte. Plutôt, tous les nœuds et le contenu textuel de l'objet DocumentFragment retourné sont clonés.

2.9. L'insertion d'un contenu

On peut insérer un nœud dans une étendue Range en utilisant la méthode suivante :

  void insertNode(in Node n) raises(RangeException);

La méthode insertNode() insère le nœud indiqué dans l'arbre de contexte de l'étendue Range. Le nœud est inséré au point limite de début de l'étendue Range sans le modifier.

Si le point limite de début de l'étendue Range se trouve dans un nœud Text, la méthode insertNode scinde le nœud Text au point limite. Si le nœud à insérer est également un nœud Text, les nœuds Text adjacents qui en résultent ne sont pas automatiquement normalisés ; cette opération est laissée à l'application.

Le nœud passé à cette méthode peut être un objet DocumentFragment. Auquel cas, son contenu est inséré au point limite de début de l'étendue Range mais pas le nœud DocumentFragment en question. Remarquer que si le nœud représente la racine d'un sous-arbre, le sous-arbre entier est inséré.

Les mêmes règles applicables à la méthode insertBefore() de l'interface Node s'applique ici. Notamment, le nœud Node passé, s'il a déjà un parent, sera retiré de sa position existante.

2.10. L'entourage d'un contenu

On peut insérer un seul nœud afin d'incorporer le contenu sélectionné par une étendue Range :

  void surroundContents(in Node newParent);

La méthode surroundContents() entraîne l'enracinement de tout le contenu sélectionné par l'étendue Range sur le nœud indiqué. Ce nœud ne peut pas être du type Attr, Entity, DocumentType, Notation, Document ou DocumentFragment. L'appel de la méthode surroundContents() avec le nœud TRUC de type Element produit le résultat suivant :

     Avant :
       <MUCHE>AB<CHOSE>C</CHOSE>DE</MUCHE>

     Après surroundContents(TRUC) :

<MUCHE>A<TRUC>B<CHOSE>C</CHOSE>D</TRUC>E</MUCHE>

On peut décrire autrement l'effet de cette méthode sur l'arbre de contexte de l'étendue Range en le décomposant en d'autres opérations :

  1. Retirer le contenu sélectionné par l'étendue Range par un appel de la méthode extractContents() ;
  2. Insérer le nœud indiqué par l'attribut newParent là où l'étendue Range se rétracte (après l'extraction) avec la méthode insertNode() ;
  3. Insérer le contenu entier de l'objet DocumentFragment extrait dans le nœud indiqué par newParent. Notamment, invoquer la méthode appendChild() sur le nœud newParent en lui passant l'objet DocumentFragment extrait, retourné en résultat de l'appel de la méthode extractContents() ;
  4. Sélectionner le nœud newParent et tout son contenu avec la méthode selectNode().

La méthode surroundContents() soulève une exception si l'étendue Range sélectionne partiellement un nœud d'un autre type que Text. Voici un exemple d'étendue Range pour lequel la méthode surroundContents() soulève une exception :

     <TRUC>AB<MUCHE>CD</MUCHE>E</TRUC>

Si le nœud indiqué par l'attribut newParent a des enfants, ces derniers sont retirés avant l'insertion du nœud. Également, si le nœud newParent a déjà un parent, il est retiré de la liste originale décrite par l'attribut childNodes du parent.

2.11. Les membres divers

On peut cloner une étendue Range :

  Range cloneRange();

Cette méthode crée une nouvelle étendue Range sélectionnant exactement le même contenu que celui de l'étendue Range sur laquelle est invoquée la méthode cloneRange. Le contenu n'est pas affecté par cette opération.

Comme les points limites d'une étendue Range n'ont pas forcément les mêmes conteneurs, utiliser :

  readonly attribute Node commonAncestorContainer;

Pour obtenir le conteneur ancêtre des deux points limites le plus éloigné en descendant le conteneur racine de l'étendue Range.

On peut obtenir une copie de toutes les données textuelles sélectionnées ou partiellement sélectionnées par une étendue Range :

  DOMString toString();

L'effet est une simple concaténation de toutes les données textuelles sélectionnées par l'étendue Range. Cela concerne les données textuelles des nœuds Text et CDATASection.

2.12. La modification des étendues pendant la mutation du document

Lors de la modification d'un document, les étendues Range du document doivent être mises à jour. Par exemple, si un point limite d'une étendue Range se trouve dans un nœud retiré du document, l'étendue Range sera invalide à moins de la réparer d'une façon ou d'une autre. Cette section décrit comment les étendues Range sont modifiées au cours des mutations du document afin de rester valides.

Deux principes généraux s'appliquent aux étendues Range en cas de mutation du document : premièrement, que toutes les étenduee Range dans le document resteront valide après une opération de mutation et, deuxièmement, que toutes les étendues Range sélectionneront, autant que possible, la même portion du document après sa mutation.

On peut assimiler la mutation de l'arbre du document, qui affecte les étendues Range, à une combinaison de suppressions et d'insertions élémentaires. En fait, il peut être commode de considérer ces opérations comme réalisées en se servant des méthodes deleteContents() et insertNode() de l'étendue Range et, dans le cas des mutations de texte, des méthodes splitText() et normalize().

2.12.1. Les insertions

Une insertion a lieu en un seul point dans le document : le point d'insertion. Considérer chaque point limite pour toute étendue Range dans l'arbre du document. Le seul cas où le point limite changera après l'insertion est celui dans lequel le point limite et le point d'insertion ont le même conteneur et dans lequel le décalage du point d'insertion est strictement inférieur à celui du point limite de l'étendue Range. Auquel cas, le décalage du point limite de l'étendue Range augmentera de façon à se trouver entre les mêmes nœuds, ou les mêmes caractères, où le point limite était avant l'insertion.

Remarquer que, à l'insertion d'un contenu à un point limite, le repositionnement du point de délimitation si sa position relative devait être conservée est ambigu. Il y a deux possibilités : au début ou à la fin du contenu nouvellement inséré. Nous avons décidé que ni le conteneur ni le décalage du point limite ne changeront dans ce cas. En conséquence, le point limite se positionnera au début du contenu inséré.

Exemples

Supposons que l'étendue Range fasse la sélection suivante :

<P>Abcd efgh XY blah ijkl</P>

Examinons l'insertion du texte texte inséré aux positions suivantes :

1. Avant le 'X' :

<P>Abcd efgh texte inséréXY blah ijkl</P>

2. Après le 'X' :

<P>Abcd efgh Xtexte inséréY blah ijkl</P>

3. Après le 'Y' :

<P>Abcd efgh XYtexte inséré blah ijkl</P>

4. Après le 'h' de "Y blah" :

<P>Abcd efgh XY blahtexte inséré ijkl</P>

2.12.2. Les suppressions

On peut assimiler toute suppression dans l'arbre du document à une succession d'opérations deleteContents() appliquées à un ensemble minimal d'étendues Range disjointes. Pour définir comment une étendue Range est modifiée pendant des suppressions, on a seulement besoin d'étudier ce qui arrive à une étendue Range au cours d'une seule opération deleteContents() exercée par une autre étendue Range. Et, en réalité, on a uniquement besoin d'examiner ce qui arrive à un seul point limite de l'étendue Range puisque les points limites sont modifiés d'après le même algorithme.

Si un point limite de l'étendue Range initiale se trouve dans le contenu à supprimer, il sera alors, après la suppression, à la même position que le point limite final de l'étendue Range (désormais rétractée) qui a servi à supprimer le contenu.

Si un point limite se trouve après le contenu à supprimer, alors il n'est pas affecté par la suppression, à moins que son conteneur ne soit aussi celui de l'un des points limites de l'étendue Range à supprimer. En présence d'un tel conteneur commun, l'index du point limite est modifié de façon à ce que le point limite conserve sa position relativement au contenu du conteneur.

Si un point limite se trouve avant le contenu à supprimer, alors il n'est pas du tout affecté par la suppression.

Exemples

Dans ces exemples, l'étendue Range sur laquelle on invoque la méthode deleteContents() est signalée par un trait souligné.

Exemple 1.

Avant :

<P>Abcd efgh The Range ijkl</P>

Après :

<P>Abcd Range ijkl</P>

Exemple 2.

Avant :

<p>Abcd efgh The Range ijkl</p>

Après :

<p>Abcd ^kl</p>

Exemple 3.

Avant :

<P>ABCD efgh The <EM>Range</EM> ijkl</P>

Après :

<P>ABCD <EM>ange</EM> ijkl</P>

Pour cet exemple, le conteneur du point limite de début après suppression est le nœud de type Text contenant la chaîne "ange".

Exemple 4.

Avant :

<P>Abcd efgh The Range ijkl</P>

Après :

<P>Abcd he Range ijkl</P>

Exemple 5.

Avant :

<P>Abcd <EM>efgh The Range ij</EM>kl</P>

Après :

<P>Abcd ^kl</P>

2.13. La description formelle de l'interface Range

En résumé, on donne ci-dessous la description formelle complète de l'interface Range :

L'interface Range (introduite dans DOM niveau 2)

Définition IDL
// Introduite dans DOM niveau 2 :
interface Range {
  readonly attribute Node             startContainer;
                     // soulève une exception DOMException en retour

  readonly attribute long             startOffset;
                     // soulève une exception DOMException en retour

  readonly attribute Node             endContainer;
                     // soulève une exception DOMException en retour

  readonly attribute long             endOffset;
                     // soulève une exception DOMException en retour

  readonly attribute boolean          collapsed;
                     // soulève une exception DOMException en retour

  readonly attribute Node             commonAncestorContainer;
                     // soulève une exception DOMException en retour

  void               setStart(in Node refNode, 
                              in long offset)
                                        raises(RangeException, 
                                               DOMException);
  void               setEnd(in Node refNode, 
                            in long offset)
                                        raises(RangeException, 
                                               DOMException);
  void               setStartBefore(in Node refNode)
                                        raises(RangeException, 
                                               DOMException);
  void               setStartAfter(in Node refNode)
                                        raises(RangeException, 
                                               DOMException);
  void               setEndBefore(in Node refNode)
                                        raises(RangeException, 
                                               DOMException);
  void               setEndAfter(in Node refNode)
                                        raises(RangeException, 
                                               DOMException);
  void               collapse(in boolean toStart)
                                        raises(DOMException);
  void               selectNode(in Node refNode)
                                        raises(RangeException, 
                                               DOMException);
  void               selectNodeContents(in Node refNode)
                                        raises(RangeException, 
                                               DOMException);

  // Paramètre compareHow
  const unsigned short      START_TO_START                 = 0;
  const unsigned short      START_TO_END                   = 1;
  const unsigned short      END_TO_END                     = 2;
  const unsigned short      END_TO_START                   = 3;

  short              compareBoundaryPoints(in unsigned short how, 
                                           in Range sourceRange)
                                        raises(DOMException);
  void               deleteContents()
                                        raises(DOMException);
  DocumentFragment   extractContents()
                                        raises(DOMException);
  DocumentFragment   cloneContents()
                                        raises(DOMException);
  void               insertNode(in Node newNode)
                                        raises(DOMException, 
                                               RangeException);
  void               surroundContents(in Node newParent)
                                        raises(DOMException, 
                                               RangeException);
  Range              cloneRange()
                                        raises(DOMException);
  DOMString          toString()
                                        raises(DOMException);
  void               detach()
                                        raises(DOMException);
};

Groupe de définition CompareHow

Passé comme paramètre à la méthode compareBoundaryPoints.

Constantes définies
END_TO_END
Compare le point limite de fin de l'étendue désignée par sourceRange au point limite de fin de l'étendue Range sur laquelle la méthode compareBoundaryPoints est invoquée.
END_TO_START
Compare le point limite de fin de l'étendue désignée par sourceRange au point limite de début de l'étendue Range sur laquelle la méthode compareBoundaryPoints est invoquée.
START_TO_END
Compare le point limite de début de l'étendue désignée par sourceRange au point limite de fin de l'étendue Range sur laquelle la méthode compareBoundaryPoints est invoquée.
START_TO_START
Compare le point limite de début de l'étendue désignée par sourceRange au point limite de début de l'étendue Range sur laquelle la méthode compareBoundaryPoints est invoquée.
Attributs
collapsed de type boolean, en lecture seule
La valeur true si l'étendue Range est rétractée.
Exceptions en retour

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

commonAncestorContainer de type Node, en lecture seule
Le conteneur ancêtre commun le plus profond des deux points limites de l'étendue Range.
Exceptions en retour

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

endContainer de type Node, en lecture seule
Le nœud dans lequel finit l'étendue Range.
Exceptions en retour

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

endOffset de type long, en lecture seule
Le décalage dans le nœud où finit l'étendue Range.
Exceptions en retour

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

startContainer de type Node, en lecture seule
Le nœud dans lequel commence l'étendue Range.
Exceptions en retour

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

startOffset de type long, en lecture seule
Le décalage dans le nœud où commence l'étendue Range.
Exceptions en retour

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Méthodes
cloneContents
Duplique le contenu d'une étendue Range.
Valeur retournée

DocumentFragment

Un objet DocumentFragment dont le contenu équivaut à cette étendue Range.

Exceptions

DOMException

HIERARCHY_REQUEST_ERR : Soulevée si un nœud DocumentType était extrait dans le nouvel objet DocumentFragment.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Aucun paramètre
cloneRange
Produit une nouvelle étendue Range dont les points limites sont identiques à ceux de l'étendue Range initiale.
Valeur retournée

Range

L'étendue Range dupliquée.

Exceptions

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Aucun paramètre
collapse
Rétracte une étendue Range à l'un de ses points limites.
Paramètres
toStart de type boolean
Pour la valeur true, rétracte l'étendue Range sur son début ; pour false, rétracte l'étendue Range sur sa fin.
Exceptions

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Aucune valeur retournée
compareBoundaryPoints
Compare les points limites de deux étendues Range dans un document.
Paramètres
how de type unsigned short
Un code représentant le type de la comparaison, comme défini précédemment.
sourceRange de type Range
L'étendue Range à laquelle l'étendue Range courante est comparée.
Valeur retournée

short

La valeur -1, 0 ou 1, selon que le point limite de l'étendue Range soit respectivement avant, égal ou après le point limite correspondant de l'étendue désignée par sourceRange.

Exceptions

DOMException

WRONG_DOCUMENT_ERR : Soulevée si les deux étendues Range ne se trouvent pas dans le même nœud Document ou DocumentFragment.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

deleteContents
Retire le contenu d'une étendue Range du document, ou du fragment de document, qui le contient, sans retourner de référence au contenu retiré.
Exceptions

DOMException

NO_MODIFICATION_ALLOWED_ERR : Soulevée si une portion du contenu de l'étendue Range est en lecture seule ou si une partie de son contenu se trouve dans un nœud en lecture seule.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Aucun paramètre
Aucune valeur retournée
detach
Appelée pour indiquer que l'étendue Range ne sert plus, et la mise en œuvre peut renoncer aux ressources associées à cette étendue Range. Les appels suivants d'une méthode ou d'un attribut de cette étendue Range soulèveront une exception DOMException de code d'erreur INVALID_STATE_ERR.
Exceptions

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Aucun paramètre
Aucune valeur retournée
extractContents
Déplace le contenu d'un objet Range du document, ou du fragment de document, qui le contient vers un nouvel objet DocumentFragment.
Valeur retournée

DocumentFragment

Un objet DocumentFragment qui contient l'extrait.

Exceptions

DOMException

NO_MODIFICATION_ALLOWED_ERR : Soulevée si une portion du contenu de l'étendue Range est en lecture seule ou si une partie de son contenu se trouve dans un nœud en lecture seule.

HIERARCHY_REQUEST_ERR : Soulevée si un nœud DocumentType était extrait dans le nouvel objet DocumentFragment.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Aucun paramètre
insertNode
Insère un nœud dans l'objet Document, ou DocumentFragment, au début de l'étendue Range. Si le conteneur est un nœud Text, il sera scindé au début de l'étendue Range (comme si la méthode splitText du type Text opérait au point d'insertion) et l'insertion interviendra entre les deux nœuds Text résultants. Les nœuds Text adjacents ne fusionneront pas automatiquement. Si le nœud à insérer est du type DocumentFragment, les enfants seront insérés au lieu du nœud DocumentFragment en question.
Paramètres
newNode de type Node
Le nœud à insérer au début de l'étendue Range.
Exceptions

DOMException

NO_MODIFICATION_ALLOWED_ERR : Soulevée si un conteneur ancêtre du début de l'étendue Range est en lecture seule.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par newNode et le conteneur du début de l'étendue Range n'ont pas été créés à partir du même document.

HIERARCHY_REQUEST_ERR : Soulevée si le conteneur du début de l'étendue Range est d'un type n'admettant pas d'enfants du type du nœud indiqué par newNode ou si le nœud de newNode est un ancêtre du conteneur.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le nœud indiqué par newNode est du type Attr, Entity, Notation ou Document.

Aucune valeur retournée
selectNode
Selectionne un nœud et son contenu.
Paramètres
refNode de type Node
Le nœud à sélectionner.
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si un ancêtre du nœud indiqué par refNode est du type Entity, Notation ou DocumentType, ou si refNode est un nœud du type Document, DocumentFragment, Attr, Entity ou Notation.

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
selectNodeContents
Selectionne le contenu d'un nœud.
Paramètres
refNode de type Node
Le nœud dont on doit sélectionner le contenu.
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le nœud indiqué par refNode, ou un ancêtre de ce nœud, est du type nœud Entity, Notation ou DocumentType.

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
setEnd
Fixe les attributs décrivant la fin d'une étendue Range.
Paramètres
refNode de type Node
La valeur de refNode. Ce paramètre doit être différent de la valeur null.
offset de type long
La valeur de endOffset.
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le nœud indiqué par refNode, ou un ancêtre de ce nœud, est du type Entity, Notation ou DocumentType.

DOMException

INDEX_SIZE_ERR : Soulevée si le paramètre offset est négatif ou supérieur au nombre d'unités enfants dans le nœud indiqué par refNode. Les unités enfants sont des unités de 16 bits si refNode est du type CharacterData (par exemple, un nœud Text ou Comment) ou du type ProcessingInstruction. Les unités enfants sont des nœuds dans tous les autres cas.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
setEndAfter
Fixe la fin d'une étendue Range afin qu'elle soit après un nœud.
Paramètres
refNode de type Node
L'étendue Range finit après le nœud indiqué par refNode.
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le conteneur racine du nōud indiqué par refNode n'est pas du type Attr, Document ou DocumentFragment, ou si refNode est du type Document, DocumentFragment, Attr, Entity ou Notation.

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
setEndBefore
Fixe la fin de l'étendue Range afin qu'elle soit avant un nœud.
Paramètres
refNode de type Node
L'étendue Range finit avant le nœud indiqué par refNode
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le conteneur racine du œud indiqué par refNode n'est pas du type Attr, Document ou DocumentFragment, ou si refNode est du type Document, DocumentFragment, Attr, Entity ou Notation.

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
setStart
Fixe les attributs décrivant le début de l'étendue Range.
Paramètres
refNode de type Node
La valeur de refNode. Ce paramètre doit avoir une valeur différente de null.
offset de type long
La valeur de startOffset.
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le nœud indiqué par refNode, ou un ancêtre de ce nœud, est du type Entity, Notation ou DocumentType.

DOMException

INDEX_SIZE_ERR : Soulevée si le paramètre offset est négatif ou supérieur au nombre d'unités enfants dans le nœud indiqué par refNode. Les unités enfants sont des unités de 16 bits si refNode est du type CharacterData (par exemple, un nœud Text ou Comment) ou du type ProcessingInstruction. Les unités enfants sont des nœuds dans tous les autres cas.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
setStartAfter
Fixe le début de l'étendue Range afin qu'elle soit après un nœud.
Paramètres
refNode de type Node
L'étendue Range débute après le nœud indiqué par refNode
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le conteneur racine du nœud indiqué par refNode n'est pas du type Attr, Document ou DocumentFragment, ou si refNode est du type Document, DocumentFragment, Attr, Entity ou Notation.

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
setStartBefore
Fixe la position de début avant un nœud.
Paramètres
refNode de type Node
L'étendue Range débute avant le nœud indiqué par refNode.
Exceptions

RangeException

INVALID_NODE_TYPE_ERR : Soulevée si le conteneur racine du nœud indiqué par refNode n'est pas du type Attr, Document ou DocumentFragment, ou si refNode est du type Document, DocumentFragment, Attr, Entity ou Notation.

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par refNode a été créé depuis un document différent de celui qui a créé cette étendue Range.

Aucune valeur retournée
surroundContents
Le nœud indiqué devient le nouveau parent du contenu de l'étendue Range et s'insère à la position de début de l'étendue Range.
Paramètres
newParent de type Node
Le nœud qui englobe le contenu.
Exceptions

DOMException

NO_MODIFICATION_ALLOWED_ERR : Soulevée si un conteneur ancêtre de l'un ou l'autre point limite de l'étendue Range est en lecture seule.

WRONG_DOCUMENT_ERR : Soulevée si le nœud indiqué par newParent et le conteneur du début de l'étendue Range n'ont pas été créés à partir du même document.

HIERARCHY_REQUEST_ERR : Soulevée si le container du début de l'étendue Range est d'un type n'admettant pas d'enfant du type du nœud newParent, ou si newParent est un ancêtre du conteneur, ou si le nœud donnerait un nœud enfant d'un type non admis par le type du nœud.

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

RangeException

BAD_BOUNDARYPOINTS_ERR : Soulevée si l'étendue Range sélectionne partiellement un nœud non textuel.

INVALID_NODE_TYPE_ERR : Soulevée si c'est un nœud de type Attr, Entity, DocumentType, Notation, Document ou DocumentFragment.

Aucune valeur retournée
toString
Retourne le contenu d'une étendue Range sous forme d'une chaîne. Cette chaîne ne contient que des données textuelles sans balisage.
Valeur retournée

DOMString

Le contenu de l'étendue Range.

Exceptions

DOMException

INVALID_STATE_ERR : Soulevée si la méthode detach() a déjà été invoquée sur cet objet.

Aucun paramètre
L'interface DocumentRange (introduite dans DOM niveau 2)

Définitions IDL
// Introduite dans DOM niveau 2 :
interface DocumentRange {
  Range              createRange();
};

Méthodes
createRange
On peut obtenir cette interface à partir de l'objet qui met en œuvre l'interface Document en utilisant les méthodes prépondérantes spécifiques de la liaison.
Valeur retournée

Range

L'état initial de l'étendue Range retournée par cette méthode est tel que ses points limites sont tous deux positionnés au début de l'objet Document correspondant, avant tout contenu. On ne peut utiliser l'étendue Range retournée que pour sélectionner un contenu associé à cet objet Document ou aux objets DocumentFragment et Attr dont l'attribut ownerDocument désigne cet objet Document.

Aucun paramètre
Aucune exception
Exception RangeException introduit dans DOM niveau 2

Les opérations sur les étendues Range peuvent soulever des exceptions RangeException comme défini dans la description de leurs méthodes.


Définitions IDL
// Introduite dans DOM niveau 2 :
exception RangeException {
  unsigned short   code;
};
// RangeExceptionCode
const unsigned short      BAD_BOUNDARYPOINTS_ERR         = 1;
const unsigned short      INVALID_NODE_TYPE_ERR          = 2;

Groupe de définition RangeExceptionCode

Un entier indiquant le type d'erreur généré.

Constantes définies
BAD_BOUNDARYPOINTS_ERR
Si les points limites d'une étendues Range ne satisfont pas aux obligations spécifiques.
INVALID_NODE_TYPE_ERR
Si on attribue comme conteneur d'un point limite d'une étendue Range un nœud d'un type invalide, ou dont un ancêtre est d'un type invalide.