I have a standard HTML input element that accepts text input in my website. One important part is that I need to track the horizontal position of a given word at all times, which I'm currently achieving by creating an invisible <span>
element, filling the span with the content of the input field, and using getClientRects()
to find the width of the content within.
This works fine, except HTML input elements have the ability to "horizontally scroll", meaning when I keep typing at the end of the element, content at the beginning gets pushed back.
Is there a way to calculate the negative offset of the beginning of the input at any given moment? Manually calculating this seems a bit tricky, especially since sometimes, the offset is only equal to a partial character width.
(edit) Clarification: The final goal is to calculate the position of the first character in the input field as a pixel offset, where an offset of 0 means the beginning of the text is at the beginning of the input field, while an offset of -100 means the beginning of the text is 100 pixels to the left of the start of the input field.
Simply calculating the difference between the width of the text and the width of the field won't do, since text can overflow both left and right.
CodePudding user response:
Is this what you want ?
//updatesize at launch
updatesize(document.querySelector("input"));
function updatesize(element){
//get left and right scrolloverflow by subtracting scrollWidth who contains the width of the element and its overflow with the clientWidth of the element
document.getElementById("scrolloverflow").innerHTML = element.scrollWidth - element.clientWidth;
//scrollWidth contains the width of the element and its overflow
document.getElementById("widthwithoverflow").innerHTML = element.scrollWidth;
//get the scroll left value of the input element. Corresponds to the position of the first character in the input field
//the multiplied by 10 and then divided by 10 is there to give a number with one digit after the decimal
document.getElementById("posfirstchar").innerHTML = -(Math.floor(element.scrollLeft * 10) / 10);
}
<!--Create a input with event listener on it :
- oninput : to update updatesize() each time we do input
- onkeydown : to catch arrow key
- onm ousemove : to catch selection made by the mouse
-->
<input type="text" value="Lorem ipsum dolor sit amet" oninput="updatesize(this)" onkeydown="updatesize(this)" onm ousemove="updatesize(this)">
<!--Debug html-->
<p>Scroll Overflow : <span id="scrolloverflow"></span> px</p>
<p>Element width (with overlow) : <span id="widthwithoverflow"></span> px</p>
<p>Position of the first character in the input field : <span id="posfirstchar"></span> px</p>
Edit : I did a pixel count to check if the position of the first character is correct. First of all, if you want to make pixel count too, you need to make your DPI (devicePixelRatio) to 100%. (by default, this is set to 125% on Windows).
With photoshop I counted the pixels from two screenshots. I found the expected number of pixels, in my case 140. I attach below the image of the count.