aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorStephen Blott2015-02-06 15:34:59 +0000
committerStephen Blott2015-02-06 17:03:18 +0000
commit14f259479bd9e398d477b1d535719407b9c0c618 (patch)
treea830086e3efd9ce0bf6c595efa62912e72b8aa74 /lib
parent449462b2580478b9c6d8b35f05231aad989d01aa (diff)
downloadvimium-14f259479bd9e398d477b1d535719407b9c0c618.tar.bz2
Visual/edit modes: code cleanup.
- convert getCaretCoordinates from JS to CS - handle x axis in scrollIntoView - better comments throughout.
Diffstat (limited to 'lib')
-rw-r--r--lib/dom_utils.coffee131
1 files changed, 41 insertions, 90 deletions
diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee
index 9360bb95..2ae9412e 100644
--- a/lib/dom_utils.coffee
+++ b/lib/dom_utils.coffee
@@ -250,99 +250,50 @@ DomUtils =
t = o || t?.parentNode
t
-extend DomUtils,
+ # This calculates the caret coordinates within an input element. It is used by edit mode to calculate the
+ # caret position for scrolling. It creates a hidden div contain a mirror of element, and all of the text
+ # from element up to position, then calculates the scroll position.
# 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.
+ # The properties that we copy to the mirrored div.
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 <span> 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;
- }
- `
+ 'direction', 'boxSizing', 'width', 'height', 'overflowX', 'overflowY',
+ 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth',
+ 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',
+ 'fontStyle', 'fontVariant', 'fontWeight', 'fontStretch', 'fontSize', 'fontSizeAdjust',
+ 'lineHeight', 'fontFamily',
+ 'textAlign', 'textTransform', 'textIndent', 'textDecoration',
+ 'letterSpacing', 'wordSpacing' ]
+
+ (element, position) ->
+ div = document.createElement "div"
+ div.id = "vimium-input-textarea-caret-position-mirror-div"
+ document.body.appendChild div
+
+ style = div.style
+ computed = getComputedStyle element
+
+ style.whiteSpace = "pre-wrap"
+ style.wordWrap = "break-word" if element.nodeName.toLowerCase() != "input"
+ style.position = "absolute"
+ style.visibility = "hidden"
+ style[prop] = computed[prop] for prop in properties
+ style.overflow = "hidden"
+
+ div.textContent = element.value.substring 0, position
+ if element.nodeName.toLowerCase() == "input"
+ div.textContent = div.textContent.replace /\s/g, "\u00a0"
+
+ span = document.createElement "span"
+ span.textContent = element.value.substring(position) || "."
+ div.appendChild span
+
+ coordinates =
+ top: span.offsetTop + parseInt computed["borderTopWidth"]
+ left: span.offsetLeft + parseInt computed["borderLeftWidth"]
+
+ document.body.removeChild div
+ coordinates
root = exports ? window
root.DomUtils = DomUtils