Issue encountered while attempting to utilize setStart and setEnd functions on Range object: Unhandled IndexSizeError: Unable to execute 'setEnd' on 'Range'

Every time I attempt to utilize a range, an error message appears in the console:

Uncaught IndexSizeError: Failed to execute 'setEnd' on 'Range': The offset 2 is larger than or equal to the node's length (0).

This is the script I am using:

<script type="text/javascript">
    function gotMark() {
        var range = document.createRange();
        var startNode = document.getElementById("dividTeste1").firstChild;

        range.setStart(startNode, 0);
        range.setEnd(startNode, 2);

        var newNode = document.createElement("span");
        range.surroundContents(newNode);
    }
</script>

And here is a snippet of the page:

<div class="ui-block-a" id="divid" value="div1">
    <div style="background-color: black; color: white; padding: 20px;" id="divid2">
        <h2>London</h2>
        <p id="dividTeste1">London is the capital city of England. It is the most
            populous city in the United Kingdom, with a metropolitan area of
            over 13 million inhabitants.</p>
    </div>
        
    <div style="background-color: black; color: white; padding: 20px;" id="divid2">
        <h2>London</h2>
        <p id="dividTeste2">London is the capital city of England. It is the most
            populous city in the United Kingdom, with a metropolitan area of
            over 13 million inhabitants.</p>
    </div>
</div>
<input type="button" value="Marcar com range" onClick="gotMark()"
        id="marcarconranger12" />

I made an effort to adhere to the guidance provided in dom range.setStart / setEnd for selecting the start and end positions.

Answer №1

I managed to resolve the issue with just one simple line of code:

function highlightText() {
    var selection = document.createRange();
    var startingPoint = document.getElementById("targetElement").firstChild;

    selection.setStart(startingPoint, 0);
    selection.setEnd(startingPoint, 2);

    var newHighlight = document.createElement("span");
    newHighlight.className = 'highlight-yellow'; // <-- this is the line that did the trick

    selection.surroundContents(newHighlight);
}

The text has now been highlighted as intended.

Answer №2

While the code provided by OP appears to be secure and within limits, complications often arise when multiple alterations are made to the same node. This can alter its properties and disrupt any subsequent calculations of offsets that have been made.

For instance, imagine we want to apply highlighting to a paragraph based on an array of start-end pairs. The straightforward approach involves iterating through the pairs in sequence and applying the necessary modifications for each start-end range:

const addHighlights = (textElement, positions) =>
  positions.forEach(([start, end]) => {
    const selectionRange = document.createRange();
    selectionRange.setStart(textElement.firstChild, start);
    selectionRange.setEnd(textElement.firstChild, end);
    const highlightSpan = document.createElement("span");
    highlightSpan.style.background = "#0f6";
    selectionRange.surroundContents(highlightSpan);
  })
;

const positions = [[0, 3], [8, 11]];
addHighlights(document.querySelector("p"), positions);
<p>foo bar baz</p>

To resolve this issue, it is important to ensure that the positions are properly sorted and do not overlap. Furthermore, it is advisable to iterate in reverse order so that changes in the content of the node do not impact earlier index offsets within the content.

const addHighlights = (textElement, positions) =>
  positions.slice().reverse().forEach(([start, end]) => {
    const selectionRange = document.createRange();
    selectionRange.setStart(textElement.firstChild, start);
    selectionRange.setEnd(textElement.firstChild, end);
    const highlightSpan = document.createElement("span");
    highlightSpan.style.background = "#0f6";
    selectionRange.surroundContents(highlightSpan);
  })
;

const positions = [[0, 3], [8, 11]];
addHighlights(document.querySelector("p"), positions);
<p>foo bar baz</p>

Situations where offset computations span multiple nodes can also lead to problems. It is crucial to ensure that the offset is local to the node specified as the first argument in the range.

There are various strategies available to avoid such issues, such as using Node.normalize() to combine text children, constructing the desired text on a new node or string before setting .innerHTML once it is ready, and more.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating JEST unit tests for a basic functionality

Here is the React code I have written: getDetails: function () { var apiUrl = ConfigStore.get('api') request .get(apiUrl) .set('X-Auth-Token', AuthStore.jwt) .set('Accept&apo ...

What is the best way to eliminate the bottom border of an input field?

Seeking advice on how to eliminate the border-bottom of an input field when typing starts. .car-list-input { font-family: 'Source Sans Pro', sans-serif; border-radius: 3px; font-size: 14px; font-weight: 400 !important; height: 35px; ...

Employing the html.validationmessagefor to display a client-side error notification

My text fields have server-side validation messages. The field 'title' is a required field on the server side with a '[Required]' data attribute in the class, but it only seems to be checked on a postback or form submit. I am saving the ...

Retrieve the rendered component color variables exclusively from the global color variable file

color_variables.css: [data-theme='default'] { --avatar_bg: #000; --avatar_text: #fff; --avatar_border: red; --button_bg: blue; --button_text: #fff; --button_border: darkblue; --modal_widget_bg: orange; --footer_bg: yellow; --foo ...

Tips for Achieving Observable Synchronization

I've encountered a coding challenge that has led me to this code snippet: ngOnInit(): void { this.categories = this.categoryService.getCategories(); var example = this.categories.flatMap((categor) => categor.map((categories) = ...

What is the encoding for Javascript in UTF-8?

My current ajax call is able to successfully send the request and retrieve the expected response. However, I am facing difficulty in correctly displaying it in li items. $.ajax({ url: "{% url 'users:profile_page_tags_get' 'primary&apos ...

Experience choppy scrolling in Internet Explorer

Check out my click and drag scrolling Image Viewer here. While it functions perfectly in Firefox and Chrome, Internet Explorer is giving me some trouble. The movement seems jerky, especially when scrolling diagonally. It's like the scroll is sluggish ...

In JavaScript, provide a boolean response to a callback function from a separate function

Working with the jQuery validate plugin involves utilizing a submitHandler callback function. This function determines whether the form submission should proceed based on its return value - false will prevent submission, while true will allow it to go thro ...

Display or conceal a div depending on the value of an integer stored in the $scope variable

Consider the ng repeat pattern below: <div class="presentForm" id="presentForm{{$index}}" ng:repeat="slide in slides" style="display: block;"> <img id ="presentationSlide" ng-src='{{slide}}' style="height: 300px" width ...

Using the foreach Loop in Javascript and AngularJs

Having trouble with a foreach loop because you're not sure of the column name to access specific data? Here's a solution to display all columns along with their corresponding data: angular.forEach(data, function(value, key) { console.log( &a ...

Tips for dynamically styling a Styled Component with all the CSS housed in an external file

My goal is to dynamically render a Styled Component. In the past, it was simple because all styling was contained within the component itself. However, I now strive to maintain a separation of concerns by storing the CSS in an external file. While this app ...

Issue with nextJS/Firebase database while experimenting with enabling web frameworks

I encountered an issue with a nextJS app I built on Firebase, following the steps and running the commands mentioned below: % npx create-next-app@latest % cd myapp % firebase experiments:enable webframeworks % npm install -g firebase-tools % firebase ...

Generating individual div elements for every piece of data in ReactJS with the help of Redux

I am utilizing redux to manage the data within a React application. Each block of data is displayed within its own DIV element. My goal is to have each div separated by space and transformed into an accordion card. I am seeking guidance on the best appro ...

The comparison between installing a JavaScript library and simply copying .js files

As I dive into the world of web development and JavaScript, I've noticed that many open-source JavaScript libraries like jqueryUI come with readme files containing installation instructions. These instructions often mention the need to install additio ...

Tips for displaying an HTML page using JavaScript

In my project, I am working with an .html file (File X) that needs to immediately open another .html file (File Y) based on a certain value. Could someone provide guidance on the best way to achieve this using JavaScript? Additionally, I would like the pa ...

Safari's Failure to Execute Ajax Requests

My HTML page includes an ajax request that is functioning properly on Firefox, but does not work on Safari. While debugging, I noticed that the readystate is undefined and the status is "". Can anyone suggest why it might not be working on Safari? Javascr ...

JavaScript regular expression to switch menu

Could someone clarify the meaning of this code snippet: /expanded/.test(classes) I understand that the '/' characters indicate a regular expression and 'expanded' is a class name. However, I am unsure about what .test(classes) does ...

What is the best way to manage a session using JavaScript?

Currently developing a website that initially hides all elements except for the password box upon loading. Once the user enters the correct password, all webpage elements are revealed. Seeking a solution to keep the elements visible on reload by utilizing ...

Using Selenium to interact with drop-down lists using div tags instead of select tags

As a newcomer to automated testing using Selenium Web Driver, I am struggling to test drop down lists for the location type without relying on the select command. The element in question is enclosed within a div tag. I attempted sending keys but that meth ...

Attempting to grasp the intricacies of HTML5/JS video playback quality

I've been diving deep into research on this topic, but I can't seem to find a straightforward answer to my specific query. My main focus is understanding the inner workings of how video players transition between different quality settings (480p, ...