2

I'm allowing a user to highlight text in a document and when it is highlighted, it will be denoted by showing a vertical bar in the left gutter. I need help drawing the vertical bar highlights on the left side of the below screenshot.

Mockup screenshot where black bars would be text

enter image description here

CodePen with current attempts I Will be referencing

I am already able to capture the selection using getSelection(). I am adding an inline element around the selection. I need help with the vertical bars that designate which part of the document was selected.

I've tried a couple things that get partially there and I'm a little lost.

This text is displayed in a <pre>. The desire is to keep the <pre> as prestine as possible. I'm trying to find a way to get this gutter through plain old HTML/CSS/JS without something complex like an angular GutterComponent that would have to track a ton of offsets, heights, and positions.

1) Append a relative-absolute <div> pair

I thought I could get away with appending a relatively positioned div that had the gutter position I needed with an absolute div for height and top of inline element through a call to getBoundingClientRect().

This sucks because the call to getBoundingClientRect() doesn't work well with inline elements, as illustrated in the CodePen. Also, the divs create a new line which potentially breaks up blocks of text.

2) Make each highlighted section a block element and use border

This sucks because I can't position the border in the gutter properly without messing up the spacing with the rest of the document. Also it has the same issue as above with breaking up the text into block elements.


I'm mainly looking for guidance on how to create those highlights on the left so they span the entire height of the inline element.

Also I have read this question but I wasn't able to parse out how to actually apply these concepts here and I'd need some guidance Inline elements and line-height

Thank you

Dhaval Jardosh
  • 7,151
  • 5
  • 27
  • 69
ballmerspeak
  • 157
  • 2
  • 14
  • I believe [this question](https://stackoverflow.com/questions/47017623/creating-revision-bars-markers-in-margin-using-css/47017993#47017993) might be of help, [my answer](https://stackoverflow.com/questions/47017623/creating-revision-bars-markers-in-margin-using-css/47017993#answer-47017993). Blend that with `getSelection()`? – hungerstar Feb 05 '18 at 21:30
  • You will need to use window.getSelection and using getRangeAt, those should get you started in the direction you want, – Cam Feb 05 '18 at 21:30
  • @Cam That is actually what I am using to grab the text and create the inline elements, however this doesn't help with the drawing of the highlights. I am using `getBoundingClientRect()` on elements drawn with `getSelection()` however, i still have issues – ballmerspeak Feb 05 '18 at 21:32
  • @hungerstar Your answer is very close to what I am doing now, however, in the case a `pre` has whitespace before or after the text, the `height` and `top` properties are 100% accurate. – ballmerspeak Feb 05 '18 at 21:36
  • Why not just create obfuscated text, and then use replace of current text that is selected and have it in a span that has a black background... Solved. – Cam Feb 05 '18 at 21:36
  • We dont understand the project guidelines, so theres about a hundred ways to solve your issue. 99 of which wont work, and only 1 will. But understanding the goal will help. – Cam Feb 05 '18 at 21:38
  • @Cam I'm trying to create the highlights on the left side of the screen shot. The black bars on the screen shot are not what I'm after. – ballmerspeak Feb 05 '18 at 21:38
  • The red and blue bars? – Cam Feb 05 '18 at 21:39
  • Yes, the blue and reddish/orange bars are what I need help on. – ballmerspeak Feb 05 '18 at 21:40

1 Answers1

1

The simpliest way is following one (but it's NOT resize friendly).

Select some text and wait a second:

var t;

function mark() {
  var selection = getSelection()
  
  if (selection.isCollapsed) return
  
  var rect = selection.getRangeAt(0).getBoundingClientRect()
  var base = document.body.getBoundingClientRect()
  
  var span = document.createElement('span')
  span.style.top = rect.top - base.top + 'px'
  span.style.height = rect.height + 'px'
  document.body.appendChild(span)
}

document.addEventListener('selectionchange', function (e) {
  clearTimeout(t)
  t = setTimeout(mark, 1000)
})
body {
  padding-left: .75em;
  position: relative;
}

span {
  position: absolute;
  left: 0;
  width: .25em;
  background: blue;
}
<p>I'm allowing a user to highlight text in a document and when it is highlighted, it will be denoted by showing a vertical bar in the left gutter. I need help drawing the vertical bar highlights on the left side of the below screenshot.
<p>Mockup screenshot where black bars would be text
<p>CodePen with current attempts I Will be referencing
<p>I am already able to capture the selection using getSelection(). I am adding an inline element around the selection. I need help with the vertical bars that designate which part of the document was selected.
<p>I've tried a couple things that get partially there and I'm a little lost.
<p>This text is displayed in a &lt;pre&gt;. The desire is to keep the &lt;pre&gt; as prestine as possible. I'm trying to find a way to get this gutter through plain old HTML/CSS/JS without something complex like an angular GutterComponent that would have to track a ton of offsets, heights, and positions.
Qwertiy
  • 19,681
  • 15
  • 61
  • 128