Ways to eliminate the child element(s) from a highlighted text portion

I'm currently struggling to figure out how to manipulate text elements within a span. When a user selects a portion of text in a div, I successfully append a span element. However, if the user selects the same text again, I want to remove the existing span and wrap the selection in a new span, ensuring that there are no children for any span element (aside from other span elements).

Does anyone know how to clear the span during text selection?

In my code, I am applying borders to the spans to highlight them.

Check out the Live Demo here

JavaScript Code:

function manipulativeSpan() {
    var newSpan = document.createElement("span");
    var selectedRange = getSelection().getRangeAt(0);   

    console.log(selectedRange); 
    try {
        selectedRange.surroundContents(newSpan);
        $(newSpan).addClass('highlight');
    } catch (exception) {
        console.log("The Range has partially selected a non-Text node.")
    }
}

$("#addText").on('click',  function(event) {
    event.preventDefault();
    $(manipulativeSpan());
});

$("button").click(function(){
    $(manipulativeSpan());
});

$("div.content").mouseup(function(event) {
    var range = window.getSelection().getRangeAt(0);
    if (!range.collapsed) {
        var bounds = range.getBoundingClientRect();
        var x = bounds.left + ((bounds.right - bounds.left - $(".savetooltipAll").outerWidth()) / 2);
        var y = bounds.top - $(".savetooltipAll").outerHeight() + $(window).scrollTop();

        $(".savetooltipAll").css("top", (y+(bounds.top*3)) + 'px');
        $(".savetooltipAll").css("left",x + 'px');
        $(".savetooltipAll").show();

    } else {
        $(".savetooltipAll").hide();
    }
});

$("div.content").mousedown(function(event) {
    var range = window.getSelection();
    console.log(range.type);
});

Answer №1

It is advisable to clear all existing spans from the parent element each time the user makes a selection. Starting fresh every time allows for better tracking of the selections and implementation of logic.

When creating a new span, it's important to store the starting and ending index data within the text itself. This way, the logic can remain separate from the display elements, ensuring independence in functionality.

The ability to store multiple sets of start and end points allows for seamless addition of user-selected areas into the data. This could result in an array structure like:

[
    {start: 2, end: 6},
    {start: 8, end: 21}
]

(where each object represents a selected "span")

With this structured data, it becomes easier to identify overlaps between selections. Merging overlapping spans simplifies the process, leading to a more cohesive set of selections.

Once all the necessary logic has been applied, the span elements can then be reintroduced back into the page for display.

Answer №2

To determine if the selection contains a highlighted span and remove it before highlighting, you can use the following condition:

    if (w.startContainer.parentElement.className == 'highlight') {
        $(w.startContainer.parentElement).replaceWith(function () {
            return $(this).contents();
        });
    }

Please note: This is just a basic idea that you can implement. The code specifically targets span.highlight, but you can modify it to handle other elements as well.

DEMO: http://jsfiddle.net/jsr150L5/

function selHTML() {
    var nNd = document.createElement("span");
    var w = getSelection().getRangeAt(0);

    console.log(w);
    console.log(w.startOffset + ' ' + w.endOffset);
    try {
        if (w.startContainer.parentElement.className == 'highlight') {
            $(w.startContainer.parentElement).replaceWith(function () {
                return $(this).contents();
            });
        }
        if (w.endContainer.parentElement.className == 'highlight') {
            $(w.endContainer.parentElement).replaceWith(function () {
                return $(this).contents();
            });
        }
        w.surroundContents(nNd);
        $(nNd).addClass('highlight');
    } catch (ex) {
        console.log("The Range has partially selected a non-Text node.")
    }

}

$("#addText").on('click', function (event) {
    event.preventDefault();
    $(selHTML());
});

$("button").click(function () {
    $(selHTML());
});

$("div.content").mouseup(function (event) {
    var range = window.getSelection().getRangeAt(0);
    if (!range.collapsed) {
        var bounds = range.getBoundingClientRect();
        var x = bounds.left + ((bounds.right - bounds.left - $(".savetooltipAll").outerWidth()) / 2);
        var y = bounds.top - $(".savetooltipAll").outerHeight() + $(window).scrollTop();

        $(".savetooltipAll").css("top", (y + (bounds.top * 3)) + 'px');
        $(".savetooltipAll").css("left", x + 'px');
        $(".savetooltipAll").show();

    } else {
        $(".savetooltipAll").hide();
    }
});

$("div.content").mousedown(function (event) {
    var range = window.getSelection();
    console.log(range.type);
});
.highlight {
    border: 1px solid red;
}
.savetooltipAll {
    position: absolute;
    display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="content">
    <p>Lorem ipsum dolor sit amet, <strong>consectetur</strong>&nbsp;adipisicing elit. Error ipsa quo illum excepturi autem voluptatem, maiores tempora quasi temporibus architecto ratione delectus modi qui cum earum, omnis itaque nam iure!</p>
</div>
<div class="savetooltipAll">
    <button>Click</button>
</div>
<input type="button" id="addText" value="Surround">

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

Converting an array of 8-bit unsigned integers into a string without the

Currently, I am working on extracting JSON data from an HTML document stored in a Uint8 array. The process involves converting the array to text and then isolating the JSON within a script tag. To achieve this, I initially converted the array into text fo ...

Add an image tag to the Canvas element

I'm attempting to add an image to a canvas element. Consider this code snippet (http://jsfiddle.net/n3L6e1wp/). I am aiming to replace the text shown in the canvas with an img tag. I have attempted to substitute the content of the div with: <img s ...

The jquery fancybox ajax modal popup fails to display in Internet Explorer 7

Recently, I utilized JQuery fancy box for the first time to display a menu list. When clicking on a specific item, the page is rendered properly in an iframe. However, if there is already an AJAX model popup present on the rendered page, it doesn't di ...

"Revealing the specific row and column of the selected element in each table when hovering over it

On my webpage, I have set up two tables positioned side by side like this: <!DOCTYPE html> <table> <tr> <td> <table> <tr><td>1</td><td>2& ...

Exploring the power of onMounted for handling asynchronous tasks in Nuxt 3

I'm having trouble figuring out what's going on with this code snippet – the value of the repository ref doesn't seem to be updating. Even though I used async/await, it doesn't appear to be functioning correctly. The repository is ju ...

What can I do to ensure that this nested footer stays fixed to the bottom of the page?

I've been experimenting with different approaches, but I'm struggling to find a solution for making the footer stay at the bottom of the page. The challenge arises from having multiple nested divs within each other. My goal is to have the border- ...

Eliminate the hover effect from every element

Is there a method in CSS or Javascript that allows me to eliminate the hover effect on all elements? I am specifically looking for a solution that will disable the hover effect on mobile devices while keeping it intact on desktop. I attempted using pointer ...

Manipulate properties of objects with React by assigning values from an array

I am working with various objects and values in my code: const [validFilters, setValidFilters] = useState({}); const [endedEvents, setEndedEventsSort] = useState(false); const [joinedEvents, setJoinedEventsSort] = useState(true); const [startDate, setStart ...

What is the best location to place an HTML wrapper element within a React Project?

Just diving into the world of React, I've embarked on a simple project with bootstrap My goal is to reuse a specific HTML structure: <div className="container"> <div className="row"> <div className="col-lg-8 col-md-10 mx-auto"&g ...

Changing colors when hovering over different elements

I am struggling to create a hover color change effect that applies to all elements (icon, text, and button) from top to bottom. Currently, the hover effect only changes the color of either the text and icon or the button individually. Below is the code sn ...

The reason for setting a variable as void 0 in JavaScript

Currently, I am delving into the libraries referenced in this particular article as well as other sources. There are some truly mind-boggling concepts contained within these resources, one of which is highlighted by the following line: var cb = void 0; I ...

How can we accurately identify the server that initiated an AJAX call in a secure manner?

Imagine a scenario where Site A embeds a JavaScript file from Server B and then makes a JSONP or AJAX request to a resource on Server B. Is there any foolproof way for Server B to determine that the specific JSONP request originated from a user on Site A, ...

Did I incorrectly pass headers in SWR?

After taking a break from coding for some time, I'm back to help a friend with a website creation project. However, diving straight into the work, I've encountered an issue with SWR. Challenge The problem I'm facing is related to sending an ...

Error: selenium web driver java cannot locate tinyMCE

driver.switchTo().frame("tinymce_iframe"); String script="var editor=tinyMCE.get('tinymce_textarea');"; JavascriptExecutor js=(JavascriptExecutor) driver; js.executeScript(script); I'm encountering a WebDriverException while try ...

Using Javascript to fetch undefined data from a C# backend with AJAX

I am struggling to create a web page using Google charts. I attempted to build it with C# as a web form and retrieve data from a local database to JavaScript. However, I keep receiving an error stating that the data is undefined in the response from Ajax. ...

Confirming if the value is an array using jQuery

Currently, I have a list of elements with various types associated with them. My goal is to identify specific text within these types and hide only those types that do not contain the desired text, leaving the rest unaffected. The structure looks like thi ...

Is there a substitute for the /deep selector in CSS shadow dom?

It seems that the /deep selector is no longer an option for selecting shadow DOM children, so I'm in search of an alternative solution. CSS scoping offers solutions for ascending selectors, but not for descending ones. Considering this DOM structure ...

Managing a plethora of JavaScript scripts in Aptana Studio

Recently, I wrote a few lines of Javascript code using Aptana Studio 3 for a web project and decided to outsource some of it. Here is the original code structure: (function(window) { var App = { // properties and functions... }; App.SubObject1 = { // ...

Flipping json stringify safety

In my NextJS React application, I encountered an issue with circular references when using getInitialProps to fetch data. Due to the serialization method used by NextJS involving JSON.stringify, it resulted in throwing an error related to circular structur ...

Filter the object by its unique identifier and locate the entry with the highest score

I'm currently working on figuring out the proper syntax for sorting an object by ID and then identifying the highest score within that ID array. While I've managed to sort the object up to this point using conditionals and the sort() method, I&ap ...