From 256beee031efef70f4ee750044d9e697d66868bd Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 22 Jan 2015 16:50:58 +0000 Subject: Visual/edit modes: develop edit mode. - implement "i", "a". - fix "w" for edit mode. - try out "e" for enter edit mode. - initial implementation "o", "O" - Suppress backspace and delete. - Scroll in text areas. --- lib/dom_utils.coffee | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) (limited to 'lib/dom_utils.coffee') diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index 4f36e395..477abef2 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -231,5 +231,99 @@ DomUtils = @remove() false +extend DomUtils, + # From: https://github.com/component/textarea-caret-position/blob/master/index.js + getCaretCoordinates: do -> + # The properties that we copy into a mirrored div. + # Note that some browsers, such as Firefox, + # do not concatenate properties, i.e. padding-top, bottom etc. -> padding, + # so we have to do every single property specifically. + 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 + + 'borderTopWidth', + 'borderRightWidth', + 'borderBottomWidth', + 'borderLeftWidth', + + 'paddingTop', + 'paddingRight', + 'paddingBottom', + 'paddingLeft', + + # https://developer.mozilla.org/en-US/docs/Web/CSS/font + 'fontStyle', + 'fontVariant', + 'fontWeight', + 'fontStretch', + 'fontSize', + 'fontSizeAdjust', + 'lineHeight', + 'fontFamily', + + 'textAlign', + 'textTransform', + 'textIndent', + 'textDecoration', # might not make a difference, but better be safe + + 'letterSpacing', + 'wordSpacing' + ] + + `function (element, position, recalculate) { + // mirrored div + 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? getComputedStyle(element) : element.currentStyle; // currentStyle for IE < 9 + + // default textarea styles + style.whiteSpace = 'pre-wrap'; + if (element.nodeName !== 'INPUT') + style.wordWrap = 'break-word'; // only for textarea-s + + // position off-screen + style.position = 'absolute'; // required to return coordinates properly + style.visibility = 'hidden'; // not 'display: none' because we want rendering + + // transfer the element's properties to the div + properties.forEach(function (prop) { + style[prop] = computed[prop]; + }); + + style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll' + + 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') + div.textContent = div.textContent.replace(/\s/g, "\u00a0"); + + var span = document.createElement('span'); + // Wrapping must be replicated *exactly*, including when a long word gets + // onto the next line, with whitespace at the end of the line before (#7). + // The *only* reliable way to do that is to copy the *entire* rest of the + // textarea's content into the created at the caret position. + // for inputs, just '.' would be enough, but why bother? + span.textContent = element.value.substring(position) || '.'; // || because a completely empty faux span doesn't render at all + div.appendChild(span); + + var coordinates = { + top: span.offsetTop + parseInt(computed['borderTopWidth']), + left: span.offsetLeft + parseInt(computed['borderLeftWidth']) + }; + + document.body.removeChild(div); + + return coordinates; + } + ` + root = exports ? window root.DomUtils = DomUtils -- cgit v1.2.3