1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#
# A heads-up-display (HUD) for showing Vimium page operations.
# Note: you cannot interact with the HUD until document.body is available.
#
HUD =
tween: null
hudUI: null
_displayElement: null
findMode: null
abandon: -> @hudUI?.hide false
# This HUD is styled to precisely mimick the chrome HUD on Mac. Use the "has_popup_and_link_hud.html"
# test harness to tweak these styles to match Chrome's. One limitation of our HUD display is that
# it doesn't sit on top of horizontal scrollbars like Chrome's HUD does.
init: ->
@hudUI ?= new UIComponent "pages/hud.html", "vimiumHUDFrame", ({data}) => this[data.name]? data
@tween ?= new Tween "iframe.vimiumHUDFrame.vimiumUIComponentVisible", @hudUI.shadowDOM
showForDuration: (text, duration) ->
@show(text)
@_showForDurationTimerId = setTimeout((=> @hide()), duration)
show: (text) ->
DomUtils.documentComplete =>
@init()
clearTimeout(@_showForDurationTimerId)
@hudUI.activate {name: "show", text}
@tween.fade 1.0, 150
showFindMode: (@findMode = null) ->
DomUtils.documentComplete =>
@init()
@hudUI.activate name: "showFindMode"
@tween.fade 1.0, 150
search: (data) ->
@findMode.findInPlace data.query
# Show the number of matches in the HUD UI.
matchCount = if FindMode.query.parsedQuery.length > 0 then FindMode.query.matchCount else 0
showMatchText = FindMode.query.rawQuery.length > 0
@hudUI.postMessage {name: "updateMatchesCount", matchCount, showMatchText}
# Hide the HUD.
# If :immediate is falsy, then the HUD is faded out smoothly (otherwise it is hidden immediately).
# If :updateIndicator is truthy, then we also refresh the mode indicator. The only time we don't update the
# mode indicator, is when hide() is called for the mode indicator itself.
hide: (immediate = false, updateIndicator = true) ->
if @hudUI? and @tween?
clearTimeout @_showForDurationTimerId
@tween.stop()
if immediate
if updateIndicator then Mode.setIndicator() else @hudUI.hide()
else
@tween.fade 0, 150, => @hide true, updateIndicator
# These parameters describe the reason find mode is exiting, and come from the HUD UI component.
hideFindMode: ({exitEventIsEnter, exitEventIsEscape}) ->
@findMode.checkReturnToViewPort()
# An element won't receive a focus event if the search landed on it while we were in the HUD iframe. To
# end up with the correct modes active, we create a focus/blur event manually after refocusing this
# window.
window.focus()
focusNode = DomUtils.getSelectionFocusElement()
document.activeElement?.blur()
focusNode?.focus()
if exitEventIsEnter
handleEnterForFindMode()
if FindMode.query.hasResults
postExit = -> new PostFindMode
else if exitEventIsEscape
# We don't want FindMode to handle the click events that handleEscapeForFindMode can generate, so we
# wait until the mode is closed before running it.
postExit = handleEscapeForFindMode
@findMode.exit()
postExit?()
class Tween
opacity: 0
intervalId: -1
styleElement: null
constructor: (@cssSelector, insertionPoint = document.documentElement) ->
@styleElement = DomUtils.createElement "style"
unless @styleElement.style
# We're in an XML document, so we shouldn't inject any elements. See the comment in UIComponent.
Tween::fade = Tween::stop = Tween::updateStyle = ->
return
@styleElement.type = "text/css"
@styleElement.innerHTML = ""
insertionPoint.appendChild @styleElement
fade: (toAlpha, duration, onComplete) ->
clearInterval @intervalId
startTime = (new Date()).getTime()
fromAlpha = @opacity
alphaStep = toAlpha - fromAlpha
performStep = =>
elapsed = (new Date()).getTime() - startTime
if (elapsed >= duration)
clearInterval @intervalId
@updateStyle toAlpha
onComplete?()
else
value = (elapsed / duration) * alphaStep + fromAlpha
@updateStyle value
@updateStyle @opacity
@intervalId = setInterval performStep, 50
stop: -> clearInterval @intervalId
updateStyle: (@opacity) ->
@styleElement.innerHTML = """
#{@cssSelector} {
opacity: #{@opacity};
}
"""
root = exports ? window
root.HUD = HUD
|