]> git.gir.st - VimFx.git/blob - extension/packages/button.coffee
Fix #190: Improve blacklisting UI
[VimFx.git] / extension / packages / button.coffee
1 { getPref
2 , setPref } = require 'prefs'
3 { injectHelp } = require 'help'
4 { commands } = require 'commands'
5 utils = require 'utils'
6 { unload } = require 'unload'
7 { _ } = require 'l10n'
8
9 KEYSET_ID = 'vimfx-keyset'
10 BUTTON_ID = 'vimfx-toolbar-button'
11 KEY_ID = 'vimfx-key'
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'
17
18 $ = (doc, sel) -> doc.getElementById(sel)
19 $$ = (doc, sel) -> doc.querySelectorAll(sel)
20
21 positions = {}
22
23 setButtonInstallPosition = (toolbarId, beforeId) ->
24 positions[BUTTON_ID] = [toolbarId, beforeId]
25
26 persist = (document, toolbar, buttonId, beforeId) ->
27 currentset = toolbar.currentSet.split(',')
28 idx = if beforeId then currentset.indexOf(beforeId) else -1
29 if idx != -1
30 currentset.splice(idx, 0, buttonId)
31 else
32 currentset.push(buttonId)
33
34 toolbar.setAttribute('currentset', currentset.join(','))
35 document.persist(toolbar.id, 'currentset')
36 return [currentset, idx]
37
38 restorePosition = (doc, button) ->
39 $(doc, 'navigator-toolbox').palette.appendChild(button)
40
41 for tb in $$(doc, 'toolbar')
42 currentset = tb.getAttribute('currentset').split(',')
43 idx = currentset.indexOf(button.id)
44 if idx != -1
45 toolbar = tb
46 break
47
48 # Saved position not found, using the default one, after persisting it
49 if !toolbar and pos = positions[button.id]
50 [tbID, beforeId] = pos
51 if toolbar = $(doc, tbID)
52 [currentset, idx] = persist(doc, toolbar, button.id, beforeId)
53
54 if toolbar and idx != -1
55 # Inserting the button before the first item in `currentset`
56 # after `idx` that is present in the document
57 for i in [idx + 1 ... currentset.length]
58 if before = $(doc, currentset[i])
59 toolbar.insertItem(button.id, before)
60 return
61
62 toolbar.insertItem(button.id)
63
64 iconUrl = (kind) ->
65 url = utils.getResourceURI("resources/icon16-#{kind}.png").spec
66 return "url(#{ url })"
67
68
69 createMenupopup = (window, button) ->
70 doc = window.document
71
72 blacklistTextbox = doc.createElement('textbox')
73 blacklistTextbox.id = TEXTBOX_BLACKLIST_ID
74 blacklistButton = doc.createElement('toolbarbutton')
75 blacklistButton.id = BUTTON_BLACKLIST_ID
76 blacklistButton.setAttribute('class', 'toolbarbutton-1')
77 hbox = doc.createElement('hbox')
78 hbox.appendChild(blacklistTextbox)
79 hbox.appendChild(blacklistButton)
80
81 itemPreferences = doc.createElement('menuitem')
82 itemPreferences.id = MENU_ITEM_PREF
83 itemPreferences.setAttribute('label', _('item_preferences'))
84
85 itemHelp = doc.createElement('menuitem')
86 itemHelp.id = MENU_ITEM_HELP
87 itemHelp.setAttribute('label', _('help_title'))
88
89 menupopup = doc.createElement('menupopup')
90 menupopup.id = MENUPOPUP_ID
91 menupopup.setAttribute('ignorekeys', true)
92 menupopup.appendChild(hbox)
93 menupopup.appendChild(itemPreferences)
94 menupopup.appendChild(itemHelp)
95
96 onPopupShowing = (event) ->
97 return unless tabWindow = window.gBrowser.selectedTab.linkedBrowser.contentWindow
98
99 { blacklisted, matchedRule } = button['VimFx_blacklisted'] or {}
100 if blacklisted
101 blacklistTextbox.value = matchedRule
102 blacklistButton.setAttribute('tooltiptext', _('item_blacklist_button_inverse_tooltip'))
103 blacklistButton.style.listStyleImage = iconUrl('blacklist_inverse')
104 else
105 # In `about:` pages, the `host` property is an empty string. Fall back to the whole URL
106 blacklistTextbox.value = "*#{ tabWindow.location.host or tabWindow.location }*"
107 blacklistButton.setAttribute('tooltiptext', _('item_blacklist_button_tooltip'))
108 blacklistButton.style.listStyleImage = iconUrl('blacklist')
109
110 onBlacklistButtonCommand = (event) ->
111 { blacklisted, matchedRule } = button['VimFx_blacklisted'] or {}
112 if blacklisted
113 utils.updateBlacklist({remove: matchedRule})
114 else
115 utils.updateBlacklist({add: blacklistTextbox.value})
116
117 menupopup.hidePopup()
118
119 if tabWindow = window.gBrowser.selectedTab.linkedBrowser.contentWindow
120 tabWindow.location.reload(false)
121
122 event.stopPropagation()
123
124 onPreferencesCommand = (event) ->
125 id = encodeURIComponent(getPref('addon_id'))
126 window.BrowserOpenAddonsMgr("addons://detail/#{ id }/preferences")
127
128 event.stopPropagation()
129
130 onHelpCommand = (event) ->
131 if tabWindow = window.gBrowser.selectedTab.linkedBrowser.contentWindow
132 injectHelp(tabWindow.document, commands)
133
134 event.stopPropagation()
135
136 menupopup.addEventListener 'popupshowing', onPopupShowing, false
137 blacklistButton.addEventListener 'command', onBlacklistButtonCommand, false
138 itemPreferences.addEventListener 'command', onPreferencesCommand, false
139 itemHelp.addEventListener 'command', onHelpCommand, false
140
141 button.appendChild(menupopup)
142 return menupopup
143
144 createButton = (window) ->
145 doc = window.document
146
147 button = doc.createElement('toolbarbutton')
148 button.setAttribute('id', BUTTON_ID)
149 button.setAttribute('type', 'menu-button')
150 button.setAttribute('label', 'VimFx')
151 button.setAttribute('class', 'toolbarbutton-1')
152
153 # Create and install event listeners
154 onButtonCommand = (event) ->
155 # Change disabled state value which is stored in Prefs
156 setPref('disabled', not getPref 'disabled')
157 updateToolbarButton(button)
158
159 event.stopPropagation()
160
161 button.addEventListener('command', onButtonCommand, false)
162
163 createMenupopup(window, button)
164
165 vimkey = doc.createElement('key')
166 vimkey.setAttribute('id', KEY_ID)
167 vimkey.setAttribute('key', 'V')
168 vimkey.setAttribute('modifiers', 'shift,alt')
169 vimkey.setAttribute('oncommand', 'void(0);')
170 vimkey.addEventListener('command', onButtonCommand, false)
171
172 keyset = doc.createElement('keyset')
173 keyset.setAttribute('id', KEYSET_ID)
174 keyset.appendChild(vimkey)
175
176 return [button, keyset]
177
178 addToolbarButton = (window) ->
179 doc = window.document
180 win = doc.querySelector('window')
181
182 [button, keyset] = createButton(window)
183 updateToolbarButton(button)
184
185 restorePosition(doc, button)
186 win.appendChild(keyset)
187
188 unload ->
189 if buttonParent = button.parentNode
190 buttonParent.removeChild(button)
191 if keysetParent = keyset.parentNode
192 keysetParent.removeChild(keyset)
193 $(doc, 'navigator-toolbox').palette.removeChild(button)
194
195 updateToolbarButton = (button) ->
196 if getPref('disabled')
197 button.style.listStyleImage = iconUrl('grey')
198 button.setAttribute('tooltiptext', _('button_tooltip_disabled'))
199 else if button['VimFx_blacklisted']
200 button.style.listStyleImage = iconUrl('red')
201 button.setAttribute('tooltiptext', _('button_tooltip_blacklisted'))
202 else
203 button.style.listStyleImage = iconUrl('normal')
204 button.setAttribute('tooltiptext', _('button_tooltip_enabled'))
205
206 setWindowBlacklisted = (window, blacklisted) ->
207 if button = $(window.document, BUTTON_ID)
208 button['VimFx_blacklisted'] = blacklisted
209 updateToolbarButton(button)
210
211 exports.addToolbarButton = addToolbarButton
212 exports.setWindowBlacklisted = setWindowBlacklisted
213 exports.setButtonInstallPosition = setButtonInstallPosition
Imprint / Impressum