From 659038614d577551c16135d1afe06520714b8ece Mon Sep 17 00:00:00 2001 From: Rob Garrison Date: Fri, 27 Nov 2015 18:03:42 -0600 Subject: [PATCH 1/3] remove border properties, no change to result --- index.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/index.js b/index.js index aafec76..baebd9b 100644 --- a/index.js +++ b/index.js @@ -14,12 +14,6 @@ var properties = [ 'overflowX', 'overflowY', // copy the scrollbar for IE - 'borderTopWidth', - 'borderRightWidth', - 'borderBottomWidth', - 'borderLeftWidth', - 'borderStyle', - 'paddingTop', 'paddingRight', 'paddingBottom', From fcbb626f5db04e5157bd7f74528dab5d4266ea1a Mon Sep 17 00:00:00 2001 From: Rob Garrison Date: Fri, 27 Nov 2015 18:06:46 -0600 Subject: [PATCH 2/3] Calculate scrollbar width & use when overflowing. Fixes #21 --- index.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index baebd9b..d3d2d3a 100644 --- a/index.js +++ b/index.js @@ -9,10 +9,8 @@ var properties = [ 'direction', // RTL support 'boxSizing', - 'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does 'height', 'overflowX', - 'overflowY', // copy the scrollbar for IE 'paddingTop', 'paddingRight', @@ -44,6 +42,25 @@ var properties = [ var isBrowser = (typeof window !== 'undefined'); var isFirefox = (isBrowser && window.mozInnerScreenX != null); +var scrollbarWidth = 0; + +// modified from http://davidwalsh.name/detect-scrollbar-width +function getScrollbarWidth() { + if (!scrollbarWidth) { + var div = document.createElement('div'), + style = div.style; + document.body.appendChild(div); + style.position = 'absolute'; + style.top = '-9999px'; + style.left = 0; + style.width = style.height = '100px'; + style.overflow = 'scroll'; + style.visibility = 'hidden'; + scrollbarWidth = div.offsetWidth - div.clientWidth; + document.body.removeChild(div); + } + return scrollbarWidth; +}; function getCaretCoordinates(element, position, options) { if(!isBrowser) { @@ -79,14 +96,16 @@ function getCaretCoordinates(element, position, options) { style[prop] = computed[prop]; }); + style.overflowY = element.scrollHeight > parseInt(computed.height) ? 'scroll' : 'auto'; + if (isFirefox) { // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275 - if (element.scrollHeight > parseInt(computed.height)) - style.overflowY = 'scroll'; + // so we still use computed width + style.width = computed.width; } else { - style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll' + // include scrollbar width - Chrome & IE renders scrollbar and gets width added + style.width = parseInt( computed.width, 10 ) + getScrollbarWidth() + 'px'; } - div.textContent = element.value.substring(0, position); // the second special handling for input type="text" vs textarea: spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037 if (element.nodeName === 'INPUT') From 85d35b7692f16fef38fc68c77ce06816ac4cf21e Mon Sep 17 00:00:00 2001 From: Rob Garrison Date: Sat, 20 Feb 2016 12:45:57 -0600 Subject: [PATCH 3/3] Demo: Add debug checkbox --- test/index.css | 36 +++++++++++++++++++++++------------- test/index.html | 8 +++++++- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/test/index.css b/test/index.css index ac73df5..69798b0 100644 --- a/test/index.css +++ b/test/index.css @@ -1,13 +1,23 @@ -input[type="text"], textarea { - font-family: 'Times New Roman'; /* a proportional font makes it more difficult to calculate the position */ - font-size: 14px; - line-height: 16px; - padding: 24px 32px 16px 8px; /* different paddings so position computations don't accidentally return a "correct" result */ - text-transform: uppercase; /* this drastically changes character width on proportional fonts */ - text-indent: 20px; - border: 16px lightblue dotted; /* needs to be accounted for when returning the final position */ - border-right-width: 24px; /* discourage naive border arithmetic */ - background: lightyellow; - tab-size: 20; - -moz-tab-size: 20; -} +input[type="text"], textarea { + font-family: 'Times New Roman'; /* a proportional font makes it more difficult to calculate the position */ + font-size: 14px; + line-height: 16px; + padding: 24px 32px 16px 8px; /* different paddings so position computations don't accidentally return a "correct" result */ + text-transform: uppercase; /* this drastically changes character width on proportional fonts */ + text-indent: 20px; + border: 16px lightblue dotted; /* needs to be accounted for when returning the final position */ + border-right-width: 24px; /* discourage naive border arithmetic */ + background: lightyellow; + tab-size: 20; + -moz-tab-size: 20; +} +body { + width: 400px; + position: relative; +} +#input-textarea-caret-position-mirror-div { + background: #ddd; + position: fixed; + top: 150px; + left: 400px; +} diff --git a/test/index.html b/test/index.html index f20698d..587cee9 100644 --- a/test/index.html +++ b/test/index.html @@ -12,6 +12,10 @@ +
+