Instructions for relocating the ending of a javascript range to a sentence within the Chrome browser

When working with a javascript range object, Internet Explorer offers a moveEnd method that can shift the end of a range by a specified number of sentence units.

How can a similar functionality be achieved in Chrome?

Below is the code I have written that seems to work, but it also highlights beyond the end of the sentence.

var range = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : new Range();
var startNode = document.getElementsByTagName("p")[0];
var endNode = document.getElementsByTagName("p")[0];
var endOffset = endNode.childNodes.length;
range.setStart(startNode, 0);
for (i = 0; i <= endNode.childNodes.length; i++) {
  range.setEnd(endNode, i);
  if (/.+\./.test(range.toString()))
    break;
}
var newNode = document.createElement("span");
newNode.setAttribute('class', 'highlight');
range.surroundContents(newNode);
.highlight {
  
  background-color:yellow;
}
<p><b>John Fitzgerald</b> "<b>Jack</b>" <b>Kennedy</b> (May 29, 1917 – November 22, 1963), commonly referred to by his initials <b>JFK</b>, was an American politician who served as the <a href="/wiki/List_of_Presidents_of_the_United_States" title="List of Presidents of the United States">35th President of the United States</a> from January 1961 until <a href="/wiki/Assassination_of_John_F._Kennedy" title="Assassination of John F. Kennedy">his assassination</a> in November 1963. The <a href="/wiki/Cuban_Missile_Crisis" title="Cuban Missile Crisis">Cuban Missile Crisis</a>, <a href="/wiki/The_Bay_of_Pigs_Invasion" class="mw-redirect" title="The Bay of Pigs Invasion">The Bay of Pigs Invasion</a>, the <a href="/wiki/Partial_Nuclear_Test_Ban_Treaty" title="Partial Nuclear Test Ban Treaty">Nuclear Test Ban Treaty</a>, the establishment of the <a href="/wiki/Peace_Corps" title="Peace Corps">Peace Corps</a>, developments in the <a href="/wiki/Space_Race" title="Space Race">Space Race</a>, the building of the <a href="/wiki/Berlin_Wall" title="Berlin Wall">Berlin Wall</a>, the <a href="/wiki/Trade_Expansion_Act" title="Trade Expansion Act">Trade Expansion Act</a> to lower tariffs, and the <a href="/wiki/African-American_Civil_Rights_Movement_(1955%E2%80%931968)" class="mw-redirect" title="African-American Civil Rights Movement (1955–1968)">Civil Rights Movement</a> all took place during his presidency. A member of the <a href="/wiki/Democratic_Party_(United_States)" title="Democratic Party (United States)">Democratic Party</a>, his <a href="/wiki/New_Frontier" title="New Frontier">New Frontier</a> domestic program was largely enacted as a memorial to him after his death.</p>

Answer №1

My solution works really well.

MySolution.Example = class extends Range {
  /*  Example object understands everything about examples
      It has a starting and ending point, and completes with a concluding statement
      It can move around the document
  */
  
  constructor() {
    super();
    this.document = new MySolution.Document();
    this.pattern = new MySolution.Pattern();
    this.highlighted = false;
    this.backupHtml = '';
    this.document.LoadAllTextNodes();
    this.SetToRange(this.document.GetSelectedRange() || this.document.GetFirstRange());
    this.collapse(true);
    this.SetEndPoints();
    this.Expand();
  }

  /* public properties */
  get CanMoveBack() {
    return !this.StartPoint.Bof;
  }

  get CanMoveForward() {
    return !this.EndPoint.Eof;
  }

  set Highlighted(value) {
    if (value == this.highlighted) return;
    if (value)
      this.Highlight();
    else
      this.Unhighlight();
    this.highlighted = value;
  }

  /* public methods */
  Expand() {
    this.StartPoint.Search(this.pattern.ConcludingStatement, false);
    this.StartPoint.Search(this.pattern.NonEmpty, true);
    this.EndPoint.Search(this.pattern.ConcludingStatement, true);
    this.Align();
  }

  MoveForward() {
    this.EndPoint.Next();
    this.Align();
    this.collapse(false);
    this.SetEndPoints();
    this.Expand();
  }

  MoveBackward() {
    this.StartPoint.Search(this.pattern.ConcludingStatement, false);
    this.StartPoint.Previous();
    this.Align();
    this.collapse(true);
    this.SetEndPoints();
    this.Expand();
  }

  Align() {
    this.setStart(this.StartPoint.TextNode, this.StartPoint.Offset);
    this.setEnd(this.EndPoint.TextNode, this.EndPoint.Offset);
  }

  SetToRange(range) {
    this.setStart(range.startContainer, range.startOffset);
    this.setEnd(range.endContainer, range.endOffset);
  }

  SetEndPoints() {
    this.StartPoint = new MySolution.Point(this.document, this);
    this.EndPoint = new MySolution.Point(this.document, this);
  }

  Highlight() {
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(this);
    this.highlighted = true;
  }

  Unhighlight() {
    this.highlighted = false;
  }

  Visualize(label) {
    // Visualization method to display the example
  }
}

/* Classes */
MySolution.Point = class {
  constructor(document, range) {
    this.document = document;
    this.TextNode = range.startContainer;
    this.Offset = range.startOffset;
    this.Bof = false;
    this.Eof = false;
  }

  Search(regex, forward) {
    // Search method to find a specific pattern
  }

  Previous() {
    // Move backward method
  }

  Next() {
    // Move forward method
  }

  toString() {
    // Convert point to string
  }
}
.highlight {
  background-color: yellow;
  outline: 1px solid green;
}
Your HTML code here.

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

Is it feasible to package shared modules into individual files using Browserify?

In my web app, I am using Browserify, Babel, and Gulp to bundle my scripts into a single file. However, when I checked the file size, it was over 3MB which seems excessive to me. Although I'm not entirely sure how Babel and Browserify modify my sourc ...

AngularJS provides users with the ability to access additional information by matching specific identification

Is there a simple way in Angular to display the label of an item from an array without looping through it? I have an array of color options: $scope.colors=[ {id:"0",label:"blue"}, {id:"1",label:"red"}, {id:"2",label:"green"} ] And my data object store ...

Restrict the quantity of items retrieved from an AJAX response

An AJAX call has returned a response consisting of a list of <a> elements: <a href="/1/">One</a> <a href="/2/">Two</a> <a href="/3/">Three</a> I am looking to select only the first n a elements from this response ...

Displaying currency format in an input field using AngularJS filter

I'm currently dealing with an input field that looks like this: <input type="text" class="form-control pull-right" ng-model="ceremony.CeremonyFee | number:2"> Although it is displaying correctly, I've noticed that it's disabled. The ...

In Next.js, the Typescript compiler does not halt when an error occurs

I am looking to incorporate Next.js with TypeScript into my project. I followed the official method of adding TypeScript to Next.js using npx create-next-app --typescript. Everything seemed fine, but when a TypeScript error occurs (e.g. const st: string = ...

Discovering the specifics of an appointment within a shift event using FullCalendar

The title of the question may not accurately depict the scenario I am about to discuss. I'm currently working with FullCalendar and utilizing an open source library that allows me to add resources at the top. You can view the outcome of this on Js ...

Adding or removing a class using Jquery based on the condition of form validation

I am facing a problem with the following code that adds and removes classes to bring the next stage of the form. The form progresses step by step where certain fields need to be filled before validation on the next button, followed by filling other fields. ...

Rounding Decimals using JavaScript

I am facing the challenge described in this particular query. In most cases, my code works fine to round numbers to two decimal places with the following formula: Math.round(num * 100) / 100 However, there was a peculiar scenario where it failed. When tr ...

The error message "Error: 'x' is not a defined function or its output is not iterable"

While experimenting, I accidentally discovered that the following code snippet causes an error in V8 (Chrome, Node.js, etc): for (let val of Symbol()) { /*...*/ } TypeError: Symbol is not a function or its return value is not iterable I also found out ...

Creating compressed files using JavaScript

I am currently working on unzipping a file located in the directory "./Data/Engine/modules/xnc.zip" to the destination folder "./Data/Engine/modules/xnc". Once I have completed writing to these files, I will need an easy method to rezip them! While I wou ...

Utilize the split() function to break down a string into separate

I'm facing an issue with splitting a string into an array using a regex that doesn't seem to be working properly. Here is my code: <script type="text/javascript"> function GetURLParameter(sParam) { var sPageURL = window.l ...

Nested Op.or operations within Sequelize for multiple conditions

Is it feasible to execute multiple operations using Op.or? For instance, when attempting: [Op.and]: { [Op.or]: [{x: 1}, {x: 1}], [Op.or]: [{y}, {y}] } The second Op.or seems to replace the first one. Is there a method to perform a ...

Searching for variables within files using Node.js and constructing an object from the results

Trying to figure out how to streamline this process. Here's the directory structure I'm working with: src/ modules/ clients/ i18n/ en-US.ts tasks/ i18n/ en-US.ts So, ea ...

jQuery's element loading function fails to work with ajax requests

When trying to preload ajax data before attaching it to a div, I utilized the following code: $.ajax({ url: 'ajax.php', data: { modelID:id }, type: 'post', success: function(result){ $(result).load(function(){ ...

Setting up a React application and API on the same port: A step-by-step guide

I have developed a React app that fetches data from a separate database through an API. While testing the app locally, it runs on one port while the API runs on another port. Since I need to make AJAX calls from the app to the API, I have to specify the ...

How to eliminate the hash from a particular page in VueJS

My dilemma is quite similar to the one discussed in this Vue router thread on removing hash on certain pages I need to configure the hash mode for all pages except for mysite.com/success. This specific page is accessed via redirect from ...

Include the name of the uploaded attachment in the textarea before hitting the submit button

Is there a way to automatically insert the filename into a textarea before the user submits the form? Can this be achieved using PHP or JavaScript? Thank you. <form id="Apply" name="Apply" method="post" enctype="multipart/form-data" action="applyLea ...

Ways to access text content in an HtmlTableCellElement

I am currently working on a jQuery tic-tac-toe project and facing an issue with iterating through the board to save the values of each cell in an array. I have tried using .text() and .value(), but both returned undefined index.html: <html> < ...

Extract ID for Bootstrap modal display

In my project, I am using a bootstrap modal that displays various strings. The challenge I am facing involves a loop of cards, each with a distinct 'id'. When triggering the modal, I want to show the corresponding id inside the modal itself, whic ...

Adding Labels to Doughnut Charts in React using Chart.js 2.0

Currently, I'm exploring the world of data visualizations using react, react-chartjs-2, and chart.js version 2.2.1. While searching for a solution to my inquiry, I came across a potentially relevant answer on this link (specifically check out the upda ...