2 # Copyright Anton Khodakivskiy 2012, 2013.
3 # Copyright Simon Lydell 2013, 2014.
5 # This file is part of VimFx.
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.
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.
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/>.
21 # Wraps the markable element and provides methods to manipulate the markers.
23 # Creates the marker DOM node.
24 constructor: (@element, @elementShape) ->
25 document = @element.ownerDocument
26 @markerElement = document.createElement('div')
27 @markerElement.classList.add('VimFxHintMarker')
29 show: -> @setVisibility(true)
30 hide: -> @setVisibility(false)
31 setVisibility: (visible) ->
32 @markerElement.classList.toggle('VimFxHiddenHintMarker', not visible)
34 if @hintChars.startsWith(@enteredHintChars) then @show() else @hide()
36 # To be called when the marker has been both assigned a hint and inserted
37 # into the DOM, and thus gotten a height and width.
38 setPosition: (viewport) ->
40 markerElement: { offsetHeight: height, offsetWidth: width }
41 elementShape: { nonCoveredPoint: { x: left, y: top, offset, rect } }
44 # Center the marker vertically on the non-covered point.
47 # Make sure that the marker stays within its element (vertically).
48 top = Math.min(top, rect.bottom - height)
49 top = Math.max(top, rect.top)
51 # Make the position relative to the top frame.
55 # Make sure that the marker stays within the viewport.
56 left = Math.min(left, viewport.right - width)
57 top = Math.min(top, viewport.bottom - height)
58 left = Math.max(left, viewport.left)
59 top = Math.max(top, viewport.top)
61 # The positioning is absolute.
62 @markerElement.style.left = "#{ left }px"
63 @markerElement.style.top = "#{ top }px"
67 left, right: left + width,
68 top, bottom: top + height,
72 setHint: (@hintChars) ->
73 # Hint chars that have been matched so far.
74 @enteredHintChars = ''
76 document = @element.ownerDocument
78 while @markerElement.hasChildNodes()
79 @markerElement.firstChild.remove()
81 fragment = document.createDocumentFragment()
82 for char in @hintChars
83 charContainer = document.createElement('span')
84 charContainer.textContent = char.toUpperCase()
85 fragment.appendChild(charContainer)
87 @markerElement.appendChild(fragment)
89 matchHintChar: (char) ->
90 @toggleLastHintChar(true)
91 @enteredHintChars += char.toLowerCase()
95 @enteredHintChars = @enteredHintChars[...-1]
96 @toggleLastHintChar(false)
99 toggleLastHintChar: (visible) ->
100 @markerElement.children[@enteredHintChars.length]
101 ?.classList.toggle('VimFxCharMatch', visible)
104 return @hintChars == @enteredHintChars
110 exports.Marker = Marker