user11553898
user11553898

Reputation:

How to get the tag of selection?

I created a function that wraps the selected text in the h1 tag, and also deletes the tags when it is called again. The function also deletes tags and creates again if you select an area larger than the previous selection.

However, if after creating the heading from the selection, select another text, and then select the word again, then the tags do not include in the selection (although the selection completely coincides with the created heading). I use the Selection and Range methods.

It turns out that with repeated selection, the tags do not fall into Selection. I also tried to do auto-replace using a regular expression, but this method is not good, because a phrase or a word can occur several times in the text.

Please tell me, is there any way in Javascript that allows us to find a node that matches this selection?

Maybe I didn’t explain well, and to better show, I created a snippet that demonstrates that. what's happening:

https://jsfiddle.net/narzantaria/2ex6bnq3/2/

Also here is the same code. The function is called by clicking the button:

document.getElementById('h1-trigger').addEventListener('click', function () {
  headerFormatter();
});

function headerFormatter() {
  let newTag = document.createElement('h1');
  if (window.getSelection) {
    let sel = window.getSelection();
    if (sel.rangeCount) {
      let range = sel.getRangeAt(0).cloneRange();
      // create an object from range for querying tags
      let rangeProxy = sel.getRangeAt(0).cloneContents();
      if (rangeProxy.querySelector('h1')) {
        let tagContent = rangeProxy.querySelector('h1').innerHTML;
        // compare selection length with queried tag length
        if (range.startOffset == 1) {
          tagContent = tagContent.replace(/(<([^>]+)>)/ig, "");
          range.deleteContents();
          range.insertNode(document.createTextNode(tagContent));
          sel.removeAllRanges();
          sel.addRange(range);
          return;
        }
        else {
          let rangeToString = range.toString().replace(/(<([^>]+)>)/ig, "");
          range.deleteContents();
          range.insertNode(document.createTextNode(rangeToString));
          sel.removeAllRanges();
          sel.addRange(range);
          return;
        }
      } else {
        range.surroundContents(newTag);
        sel.removeAllRanges();
        sel.addRange(range);
      }
    }
  }
}

Regards.

Upvotes: 0

Views: 173

Answers (2)

nwillo
nwillo

Reputation: 1294

You'll have to do a few things to achieve the type of functionality you desire:

  1. When you insert an H1 tag, add an identifier to it. Store this identifier along with the selected range values. Also, use a boolean flag variable to show the text is being highlighted.
  2. Next time when you click the button, check whether the flag variable is true. If it is, using the stored range values from the previous selection, remove the h1 highlighting.
  3. Once done, you can now add the highlighting to the new range and repeat step 1.

This might be a lengthier approach, but it may be more effective than your current approach. I hope this helps. Thanks!

A flowchart to explain the steps above enter image description here

Upvotes: 0

jiwopene
jiwopene

Reputation: 3627

You can get tag where the selection starts/ends using getSelection().anchorNode and getSelection().focusNode.

Upvotes: 0

Related Questions