2 , setPref } = require 'prefs'
3 { injectHelp } = require 'help'
4 { commands } = require 'commands'
5 utils = require 'utils'
6 { unload } = require 'unload'
9 KEYSET_ID = 'vimfx-keyset'
10 BUTTON_ID = 'vimfx-toolbar-button'
12 MENUPOPUP_ID = 'vimfx-menupopup'
13 MENU_ITEM_PREF = 'vimfx-menu-item-preferences'
14 MENU_ITEM_HELP = 'vimfx-menu-item-help'
15 TEXTBOX_BLACKLIST_ID = 'vimfx-textbox-blacklist-id'
16 BUTTON_BLACKLIST_ID = 'vimfx-button-blacklist-id'
18 $ = (document, sel) -> document.getElementById(sel)
19 $$ = (document, sel) -> document.querySelectorAll(sel)
23 setButtonInstallPosition = (toolbarId, beforeId) ->
24 positions[BUTTON_ID] = {toolbarId, beforeId}
26 addToolbarButton = (vimBucket, window) ->
27 document = window.document
28 win = document.querySelector('window')
30 [ button, keyset ] = createButton(vimBucket, window)
32 # Namespace to put the VimFx state on, for example
35 restorePosition(document, button)
37 if tabWindow = utils.getCurrentTabWindow(window)
38 blacklisted = utils.isBlacklisted(tabWindow.location.href)
39 disabled = getPref('disabled')
40 updateToolbarButton(window, {disabled, blacklisted})
42 win.appendChild(keyset)
45 if buttonParent = button.parentNode
46 buttonParent.removeChild(button)
47 if keysetParent = keyset.parentNode
48 keysetParent.removeChild(keyset)
49 $(document, 'navigator-toolbox').palette.removeChild(button)
51 createButton = (vimBucket, window) ->
52 document = window.document
54 button = document.createElement('toolbarbutton')
55 button.setAttribute('id', BUTTON_ID)
56 button.setAttribute('type', 'menu-button')
57 button.setAttribute('label', 'VimFx')
58 button.setAttribute('class', 'toolbarbutton-1')
60 menupopup = createMenupopup(window, button)
62 onButtonCommand = (event) ->
64 when button.VimFx.blacklisted
65 menupopup.openPopup(button, 'after_start')
66 when button.VimFx.insertMode
67 return unless currentTabWindow = utils.getEventCurrentTabWindow(event)
68 return unless vim = vimBucket.get(currentTabWindow)
69 updateToolbarButton(window, {insertMode: false})
70 vim.enterMode('normal')
72 disabled = not getPref('disabled')
73 setPref('disabled', disabled)
74 updateToolbarButton(window, {disabled})
76 event.stopPropagation()
78 button.addEventListener('command', onButtonCommand, false)
80 vimkey = document.createElement('key')
81 vimkey.setAttribute('id', KEY_ID)
82 vimkey.setAttribute('key', 'V')
83 vimkey.setAttribute('modifiers', 'shift,alt')
84 vimkey.setAttribute('oncommand', 'void(0);')
85 vimkey.addEventListener('command', onButtonCommand, false)
87 keyset = document.createElement('keyset')
88 keyset.setAttribute('id', KEYSET_ID)
89 keyset.appendChild(vimkey)
91 return [button, keyset]
93 createMenupopup = (window, button) ->
94 document = window.document
96 blacklistTextbox = document.createElement('textbox')
97 blacklistTextbox.id = TEXTBOX_BLACKLIST_ID
98 blacklistButton = document.createElement('toolbarbutton')
99 blacklistButton.id = BUTTON_BLACKLIST_ID
100 blacklistButton.setAttribute('class', 'toolbarbutton-1')
101 hbox = document.createElement('hbox')
102 hbox.appendChild(blacklistTextbox)
103 hbox.appendChild(blacklistButton)
105 itemPreferences = document.createElement('menuitem')
106 itemPreferences.id = MENU_ITEM_PREF
107 itemPreferences.setAttribute('label', _('item_preferences'))
109 itemHelp = document.createElement('menuitem')
110 itemHelp.id = MENU_ITEM_HELP
111 itemHelp.setAttribute('label', _('help_title'))
113 menupopup = document.createElement('menupopup')
114 menupopup.id = MENUPOPUP_ID
115 menupopup.setAttribute('ignorekeys', true)
116 menupopup.appendChild(hbox)
117 menupopup.appendChild(itemPreferences)
118 menupopup.appendChild(itemHelp)
120 onPopupShowing = (event) ->
121 return unless tabWindow = utils.getCurrentTabWindow(window)
123 if button.VimFx.blacklisted
124 matchingRules = utils.getMatchingBlacklistRules(tabWindow.location.href)
125 blacklistTextbox.value = matchingRules.join(', ')
126 blacklistTextbox.setAttribute('readonly', true)
127 blacklistButton.setAttribute('tooltiptext', _('item_blacklist_button_inverse_tooltip'))
128 blacklistButton.style.listStyleImage = iconUrl('blacklist_inverse')
130 # In `about:` pages, the `host` property is an empty string. Fall back to the whole URL
131 blacklistTextbox.value = "*#{ tabWindow.location.host or tabWindow.location.href }*"
132 blacklistTextbox.removeAttribute('readonly')
133 blacklistButton.setAttribute('tooltiptext', _('item_blacklist_button_tooltip'))
134 blacklistButton.style.listStyleImage = iconUrl('blacklist')
136 onBlacklistButtonCommand = (event) ->
137 return unless tabWindow = utils.getCurrentTabWindow(window)
139 if button.VimFx.blacklisted
140 utils.updateBlacklist({remove: blacklistTextbox.value})
142 utils.updateBlacklist({add: blacklistTextbox.value})
144 menupopup.hidePopup()
146 tabWindow.location.reload(false)
148 event.stopPropagation()
150 onPreferencesCommand = (event) ->
151 id = encodeURIComponent(getPref('addon_id'))
152 window.BrowserOpenAddonsMgr("addons://detail/#{ id }/preferences")
154 event.stopPropagation()
156 onHelpCommand = (event) ->
157 if tabWindow = utils.getCurrentTabWindow(window)
158 injectHelp(tabWindow.document, commands)
160 event.stopPropagation()
162 menupopup.addEventListener('popupshowing', onPopupShowing, false)
163 blacklistButton.addEventListener('command', onBlacklistButtonCommand, false)
164 itemPreferences.addEventListener('command', onPreferencesCommand, false)
165 itemHelp.addEventListener('command', onHelpCommand, false)
167 button.appendChild(menupopup)
170 restorePosition = (document, button) ->
171 $(document, 'navigator-toolbox').palette.appendChild(button)
173 for tb in $$(document, 'toolbar')
174 currentset = tb.getAttribute('currentset').split(',')
175 idx = currentset.indexOf(button.id)
180 # Saved position not found, using the default one, after persisting it
181 if !toolbar and button.id of positions
182 { toolbarId, beforeId } = positions[button.id]
183 if toolbar = $(document, toolbarId)
184 [ currentset, idx ] = persist(document, toolbar, button.id, beforeId)
186 if toolbar and idx != -1
187 # Inserting the button before the first item in `currentset`
188 # after `idx` that is present in the document
189 for id in currentset[idx+1..]
190 if before = $(document, id)
191 toolbar.insertItem(button.id, before)
194 toolbar.insertItem(button.id)
196 persist = (document, toolbar, buttonId, beforeId) ->
197 currentset = toolbar.currentSet.split(',')
198 idx = if beforeId then currentset.indexOf(beforeId) else -1
200 currentset.splice(idx, 0, buttonId)
202 currentset.push(buttonId)
204 toolbar.setAttribute('currentset', currentset.join(','))
205 document.persist(toolbar.id, 'currentset')
206 return [currentset, idx]
208 updateToolbarButton = (window, { disabled, blacklisted, insertMode }) ->
209 return unless button = $(window.document, BUTTON_ID)
211 button.VimFx.disabled = disabled if disabled?
212 button.VimFx.blacklisted = blacklisted if blacklisted?
213 button.VimFx.insertMode = insertMode if insertMode?
215 [ icon, tooltip ] = switch
216 when button.VimFx.disabled
218 when button.VimFx.blacklisted
219 ['red', 'blacklisted']
220 when button.VimFx.insertMode
221 ['grey', 'insertMode']
223 ['normal', 'enabled']
225 button.style.listStyleImage = iconUrl(icon)
226 button.setAttribute('tooltiptext', _("button_tooltip_#{ tooltip }"))
229 url = utils.getResourceURI("resources/icon16-#{ kind }.png").spec
230 return "url(#{ url })"
232 exports.setButtonInstallPosition = setButtonInstallPosition
233 exports.addToolbarButton = addToolbarButton
234 exports.updateToolbarButton = updateToolbarButton