]> git.gir.st - VimFx.git/blob - extension/lib/marker.coffee
Simplify hint matching
[VimFx.git] / extension / lib / marker.coffee
1 ###
2 # Copyright Anton Khodakivskiy 2012, 2013.
3 # Copyright Simon Lydell 2013, 2014.
4 #
5 # This file is part of VimFx.
6 #
7 # VimFx is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # VimFx is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
19 ###
20
21 # Wraps the markable element and provides methods to manipulate the markers.
22 class Marker
23 # Creates the marker DOM node.
24 constructor: (@element, @elementShape) ->
25 document = @element.ownerDocument
26 @markerElement = document.createElement('div')
27 @markerElement.classList.add('VimFxHintMarker')
28
29 reset: ->
30 @setHint(@hint)
31 @show()
32
33 show: -> @setVisibility(true)
34 hide: -> @setVisibility(false)
35 setVisibility: (visible) ->
36 @markerElement.classList.toggle('VimFxHiddenHintMarker', not visible)
37
38 # To be called when the marker has been both assigned a hint and inserted
39 # into the DOM, and thus gotten a height and width.
40 setPosition: (viewport) ->
41 {
42 markerElement: { offsetHeight: height, offsetWidth: width }
43 elementShape: { nonCoveredPoint: { x: left, y: top, offset, rect } }
44 } = this
45
46 # Center the marker vertically on the non-covered point.
47 top -= height / 2
48
49 # Make sure that the marker stays within its element (vertically).
50 top = Math.min(top, rect.bottom - height)
51 top = Math.max(top, rect.top)
52
53 # Make the position relative to the top frame.
54 left += offset.left
55 top += offset.top
56
57 # Make sure that the marker stays within the viewport.
58 left = Math.min(left, viewport.right - width)
59 top = Math.min(top, viewport.bottom - height)
60 left = Math.max(left, viewport.left)
61 top = Math.max(top, viewport.top)
62
63 # The positioning is absolute.
64 @markerElement.style.left = "#{ left }px"
65 @markerElement.style.top = "#{ top }px"
66
67 # For quick access.
68 @position = {
69 left, right: left + width,
70 top, bottom: top + height,
71 height, width
72 }
73
74 setHint: (@hint) ->
75 @hintIndex = 0
76
77 document = @element.ownerDocument
78
79 while @markerElement.hasChildNodes()
80 @markerElement.firstChild.remove()
81
82 fragment = document.createDocumentFragment()
83 for char in @hint
84 charContainer = document.createElement('span')
85 charContainer.textContent = char
86 fragment.appendChild(charContainer)
87
88 @markerElement.appendChild(fragment)
89
90 matchHintChar: (char) ->
91 if char == @hint[@hintIndex]
92 @toggleLastHintChar(true)
93 @hintIndex++
94 return true
95 return false
96
97 deleteHintChar: ->
98 if @hintIndex > 0
99 @hintIndex--
100 @toggleLastHintChar(false)
101
102 toggleLastHintChar: (visible) ->
103 @markerElement.children[@hintIndex]
104 .classList.toggle('VimFxCharMatch', visible)
105
106 isMatched: -> (@hintIndex == @hint.length)
107
108 exports.Marker = Marker
Imprint / Impressum