| | |
| |
|
| | |
| | |
| | |
| | |
| | var properties = [ |
| | 'direction', |
| | 'boxSizing', |
| | 'width', |
| | 'height', |
| | 'overflowX', |
| | 'overflowY', |
| |
|
| | 'borderTopWidth', |
| | 'borderRightWidth', |
| | 'borderBottomWidth', |
| | 'borderLeftWidth', |
| | 'borderStyle', |
| |
|
| | 'paddingTop', |
| | 'paddingRight', |
| | 'paddingBottom', |
| | 'paddingLeft', |
| |
|
| | |
| | 'fontStyle', |
| | 'fontVariant', |
| | 'fontWeight', |
| | 'fontStretch', |
| | 'fontSize', |
| | 'fontSizeAdjust', |
| | 'lineHeight', |
| | 'fontFamily', |
| |
|
| | 'textAlign', |
| | 'textTransform', |
| | 'textIndent', |
| | 'textDecoration', |
| |
|
| | 'letterSpacing', |
| | 'wordSpacing', |
| |
|
| | 'tabSize', |
| | 'MozTabSize' |
| |
|
| | ]; |
| |
|
| | var isBrowser = (typeof window !== 'undefined'); |
| | var isFirefox = (isBrowser && window.mozInnerScreenX != null); |
| |
|
| | function getCaretCoordinates(element, position, options) { |
| | if (!isBrowser) { |
| | throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser'); |
| | } |
| |
|
| | var debug = options && options.debug || false; |
| | if (debug) { |
| | var el = document.querySelector('#input-textarea-caret-position-mirror-div'); |
| | if (el) el.parentNode.removeChild(el); |
| | } |
| |
|
| | |
| | var div = document.createElement('div'); |
| | div.id = 'input-textarea-caret-position-mirror-div'; |
| | document.body.appendChild(div); |
| |
|
| | var style = div.style; |
| | var computed = window.getComputedStyle ? window.getComputedStyle(element) : element.currentStyle; |
| | var isInput = element.nodeName === 'INPUT'; |
| |
|
| | |
| | style.whiteSpace = 'pre-wrap'; |
| | if (!isInput) |
| | style.wordWrap = 'break-word'; |
| |
|
| | |
| | style.position = 'absolute'; |
| | if (!debug) |
| | style.visibility = 'hidden'; |
| |
|
| | |
| | properties.forEach(function (prop) { |
| | if (isInput && prop === 'lineHeight') { |
| | |
| | if (computed.boxSizing === "border-box") { |
| | var height = parseInt(computed.height); |
| | var outerHeight = |
| | parseInt(computed.paddingTop) + |
| | parseInt(computed.paddingBottom) + |
| | parseInt(computed.borderTopWidth) + |
| | parseInt(computed.borderBottomWidth); |
| | var targetHeight = outerHeight + parseInt(computed.lineHeight); |
| | if (height > targetHeight) { |
| | style.lineHeight = height - outerHeight + "px"; |
| | } else if (height === targetHeight) { |
| | style.lineHeight = computed.lineHeight; |
| | } else { |
| | style.lineHeight = 0; |
| | } |
| | } else { |
| | style.lineHeight = computed.height; |
| | } |
| | } else { |
| | style[prop] = computed[prop]; |
| | } |
| | }); |
| |
|
| | if (isFirefox) { |
| | |
| | if (element.scrollHeight > parseInt(computed.height)) |
| | style.overflowY = 'scroll'; |
| | } else { |
| | style.overflow = 'hidden'; |
| | } |
| |
|
| | div.textContent = element.value.substring(0, position); |
| | |
| | |
| | if (isInput) |
| | div.textContent = div.textContent.replace(/\s/g, '\u00a0'); |
| |
|
| | var span = document.createElement('span'); |
| | |
| | |
| | |
| | |
| | |
| | span.textContent = element.value.substring(position) || '.'; |
| | div.appendChild(span); |
| |
|
| | var coordinates = { |
| | top: span.offsetTop + parseInt(computed['borderTopWidth']), |
| | left: span.offsetLeft + parseInt(computed['borderLeftWidth']), |
| | height: parseInt(computed['lineHeight']) |
| | }; |
| |
|
| | if (debug) { |
| | span.style.backgroundColor = '#aaa'; |
| | } else { |
| | document.body.removeChild(div); |
| | } |
| |
|
| | return coordinates; |
| | } |
| |
|