1

I'm using window.selection() for coloring some text. Now I need to color a selection which do not contain a <p> tag.

Code:

 function abc() {
   var range = window.getSelection().getRangeAt(0);
   span =  document.createElement('span');
   span.className = 'colored';
   span.appendChild(range.extractContents());
   range.insertNode(span);
 }

How can I check if window.getSelection() contains the <p> tag?

1
  • 1
    Wouldn't CSS ::selection work instead for your case? css-tricks.com/… Commented Sep 30, 2018 at 15:22

3 Answers 3

3

You can use range.cloneContents() to get a document fragment to work with and avoid mutating the DOM. Then run simple document queries like querySelector() on that document fragment to find any p tags:

var range = window.getSelection().getRangeAt(0);
var docFragment = range.cloneContents();

if (docFragment.querySelector('p')) return;

var span = document.createElement('span');
span.className = 'colored';
range.surroundContents(span);

I also used range.surroundContents() to surround the range's contents in the span since that looks like all you're trying to do here.

Here's an example. Any selections that contain any part of the p tag don't have any effect, while all other selections get a yellow highlight:

function abc() {
  var range = window.getSelection().getRangeAt(0);
  var docFragment = range.cloneContents();

  if (docFragment.querySelector('p')) return;

  var span = document.createElement('span');
  span.className = 'colored';
  range.surroundContents(span);
 }
 
 window.onclick = abc
.colored {
  background: yellow;
}
stuff outside a p tag
<p>stuff inside a p tag</p>
more stuff outside a p tag

The caveat here is that any selections completely inside the p tag itself are still highlighted. If that's undesirable, you'd need to grab the selection's start or end container node and recursively check for a parent p tag. Example:

function isInPTag(node) {
  return node && (node.tagName === 'P' || isInPTag(node.parentNode));
}

function abc() {
  var range = window.getSelection().getRangeAt(0);
  var docFragment = range.cloneContents();
  
  if (docFragment.querySelector('p') || isInPTag(range.startContainer)) return;

  var span = document.createElement('span');
  span.className = 'colored';
  range.surroundContents(span);
}
 
 window.onclick = abc
.colored {
  background: yellow;
}
stuff outside a p tag
<p>stuff inside a p tag</p>
more stuff outside a p tag

Sign up to request clarification or add additional context in comments.

Comments

2

This will get you the selection's parent node's tag name:

var selection = window.getSelection();
if (selection && selection.anchorNode.parentNode.tagName === "P") {
    // code
}

Comments

-1

Here's a Jquery version to do that.

You can use .anchorNode attribute and get the parent of the selection then you can get the tag name of the parent easily by doing .prop("tagName").

$(range.anchorNode).parent().prop("tagName");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.