diff options
| author | Stephen Blott | 2015-02-09 11:40:53 +0000 |
|---|---|---|
| committer | Stephen Blott | 2015-02-09 11:40:53 +0000 |
| commit | 0bf605a934115083e700f5de090f39841417482a (patch) | |
| tree | 408c191bd702da6847bca9943f6eba93ad28b209 /lib | |
| parent | ac648a0e9f53c2fc359daa68309c25dd8c9db031 (diff) | |
| parent | ed306994697f6f9f5e13f9d018b5c7ffa2fff680 (diff) | |
| download | vimium-0bf605a934115083e700f5de090f39841417482a.tar.bz2 | |
Merge branch 'visual-and-edit-modes'
Conflicts:
background_scripts/main.coffee
content_scripts/vimium_frontend.coffee
lib/keyboard_utils.coffee
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/dom_utils.coffee | 64 | ||||
| -rw-r--r-- | lib/handler_stack.coffee | 15 | ||||
| -rw-r--r-- | lib/keyboard_utils.coffee | 9 | ||||
| -rw-r--r-- | lib/utils.coffee | 17 |
4 files changed, 100 insertions, 5 deletions
diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index 4f36e395..2ae9412e 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -231,5 +231,69 @@ DomUtils = @remove() false + simulateTextEntry: (element, text) -> + event = document.createEvent "TextEvent" + event.initTextEvent "textInput", true, true, null, text + element.dispatchEvent event + + # Adapted from: http://roysharon.com/blog/37. + # This finds the element containing the selection focus. + getElementWithFocus: (selection, backwards) -> + r = t = selection.getRangeAt 0 + if selection.type == "Range" + r = t.cloneRange() + r.collapse backwards + t = r.startContainer + t = t.childNodes[r.startOffset] if t.nodeType == 1 + o = t + o = o.previousSibling while o and o.nodeType != 1 + t = o || t?.parentNode + t + + # 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 to the mirrored div. + properties = [ + '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 diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee index 3d635005..b0fefc7d 100644 --- a/lib/handler_stack.coffee +++ b/lib/handler_stack.coffee @@ -38,6 +38,7 @@ class HandlerStack # @stopBubblingAndTrue. bubbleEvent: (type, event) -> @eventNumber += 1 + eventNumber = @eventNumber # We take a copy of the array in order to avoid interference from concurrent removes (for example, to # avoid calling the same handler twice, because elements have been spliced out of the array by remove). for handler in @stack[..].reverse() @@ -45,13 +46,15 @@ class HandlerStack if handler?.id and handler[type] @currentId = handler.id result = handler[type].call @, event - @logResult type, event, handler, result if @debug + @logResult eventNumber, type, event, handler, result if @debug if not result DomUtils.suppressEvent event if @isChromeEvent event return false return true if result == @stopBubblingAndTrue return false if result == @stopBubblingAndFalse return @bubbleEvent type, event if result == @restartBubbling + else + @logResult eventNumber, type, event, handler, "skip" if @debug true remove: (id = @currentId) -> @@ -80,7 +83,7 @@ class HandlerStack false # Debugging. - logResult: (type, event, handler, result) -> + logResult: (eventNumber, type, event, handler, result) -> # FIXME(smblott). Badge updating is too noisy, so we filter it out. However, we do need to look at how # many badge update events are happening. It seems to be more than necessary. We also filter out # registerKeyQueue as unnecessarily noisy and not particularly helpful. @@ -90,9 +93,15 @@ class HandlerStack when @stopBubblingAndTrue then "stop/true" when @stopBubblingAndFalse then "stop/false" when @restartBubbling then "rebubble" + when "skip" then "skip" when true then "continue" label ||= if result then "continue/truthy" else "suppress" - console.log "#{@eventNumber}", type, handler._name, label + console.log "#{eventNumber}", type, handler._name, label + + show: -> + console.log "#{@eventNumber}:" + for handler in @stack[..].reverse() + console.log " ", handler._name # For tests only. reset: -> diff --git a/lib/keyboard_utils.coffee b/lib/keyboard_utils.coffee index 693c9b1c..5c95680c 100644 --- a/lib/keyboard_utils.coffee +++ b/lib/keyboard_utils.coffee @@ -1,6 +1,6 @@ KeyboardUtils = keyCodes: - { ESC: 27, backspace: 8, deleteKey: 46, enter: 13, space: 32, shiftKey: 16, ctrlKey: 17, f1: 112, + { ESC: 27, backspace: 8, deleteKey: 46, enter: 13, ctrlEnter: 10, space: 32, shiftKey: 16, ctrlKey: 17, f1: 112, f12: 123, tab: 9, downArrow: 40, upArrow: 38 } keyNames: @@ -59,7 +59,12 @@ KeyboardUtils = # identify any of chrome's own keyboard shortcuts as printable. isPrintable: (event) -> return false if event.metaKey or event.ctrlKey or event.altKey - @getKeyChar(event)?.length == 1 + keyChar = + if event.type == "keypress" + String.fromCharCode event.charCode + else + @getKeyChar event + keyChar.length == 1 KeyboardUtils.init() diff --git a/lib/utils.coffee b/lib/utils.coffee index 661f7e84..64c87842 100644 --- a/lib/utils.coffee +++ b/lib/utils.coffee @@ -152,6 +152,23 @@ Utils = # locale-sensitive uppercase detection hasUpperCase: (s) -> s.toLowerCase() != s + # Give objects (including elements) distinct identities. + getIdentity: do -> + identities = [] + + (obj) -> + index = identities.indexOf obj + if index < 0 + index = identities.length + identities.push obj + "identity-" + index + + # Return a copy of object, but with some of its properties omitted. + copyObjectOmittingProperties: (obj, properties...) -> + obj = extend {}, obj + delete obj[property] for property in properties + obj + # This creates a new function out of an existing function, where the new function takes fewer arguments. This # allows us to pass around functions instead of functions + a partial list of arguments. Function::curry = -> |
