I have text in a <p>
tag:
<p>Hello world... and goodbye mind A B!</p>
How do I increase the area in which the text is selectable? I know I can increase the font-size
and that would increase the area which is selectable, but is there a better way?
To clarify this question. For example, on mobile screens, I find it difficult to highlight words that are one letter like i
, but if the hit detection would be on a wider area, it would be a lot easier to select it.
How to do it? A mind-teasing puzzle.
Looking for a working cross browser solution. Please read the question thoroughly and the comments before posting an answer to avoid confusion. User @mmm posted a question that's quite close, but in his approach, while the <p>
tag is has a wider hit detection (perfect!), it auto-selects upon click. I need the user to interact with the <p>
tag just like we do with normal text based <p>
tags... however with a larger hit detector.
Further clarification. As an example, the selection area for a comment to this very question is this large:
You can find this comment below. Hover your cursor over it until the cursor gets changed to cursor:text
. That's the default selection area.
But my aim is to extend it to a larger area, like this:
We simply add the onlcick event and add a location to it. Then, additionally and optionally, we add a cursor: pointer to indicate to the user the div is clickable. This will make the whole div clickable.
canvas does not have any built-in mechanism for selecting text, so you would have to roll out your own text rendering and selecting code - which can be rather tricky to get right.
Remarks. Note. Setting the UNSELECTABLE attribute to off does not ensure that an element is selectable. One example is an HTML Application (HTA) with the SELECTION attribute set to no. Elements in the body of the HTA cannot be selected, even if the UNSELECTABLE attribute for an element is set to off.
From my test it works on the iphone as well as ff and chrome - if someone can test on android I'll appreciate feedback!
The border obviously can be removed.
This code uses code from this answer (part of the SelectText() function): Selecting text in an element (akin to highlighting with your mouse)
Fiddle
Code:
function extendSelection() { var extendBy = arguments.length <= 0 || arguments[0] === undefined ? 15 : arguments[0]; var extended = document.getElementsByClassName('extendedSelection'); [].slice.call(extended).forEach(function (v) { var bounds = v.getBoundingClientRect(); var x = bounds.left; var r = textWidth(v.innerHTML, ''+ css(v, 'font-weight') +' ' + css(v, 'font-size') + ' ' + css(v, 'font-family') ); var y = bounds.top; var w = bounds.width; var h = bounds.height; var element = document.createElement('div'); element.style.position = 'absolute'; element.style.height = h + extendBy + 'px'; element.style.width = r + extendBy + 'px'; element.style.left = x - extendBy / 2 + 'px'; element.style.top = y - extendBy / 2 + 'px'; element.style.border = '1px dotted black'; document.body.appendChild(element); element.addEventListener('click', function (e) { SelectText(v); }); element.addEventListener('touchend', function (e) { SelectText(v); }); }); } function css(element, property) { return window.getComputedStyle(element, null).getPropertyValue(property); } function textWidth(text, font) { var el = textWidth.canvas || (textWidth.canvas = document.createElement("canvas")); var draw = el.getContext("2d"); draw.font = font; var m = draw.measureText(text); return m.width; }; function SelectText(element) { var doc = document, text = element, range, selection; if (doc.body.createTextRange) { range = document.body.createTextRange(); range.moveToElementText(text); range.select(); } else if (window.getSelection) { selection = window.getSelection(); range = document.createRange(); range.selectNodeContents(text); selection.removeAllRanges(); selection.addRange(range); selection.setSelectionRange(0, element.value.length) } } extendSelection();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With