1 utils = require 'utils'
2 prefs = require 'prefs'
5 { classes: Cc, interfaces: Ci, utils: Cu } = Components
7 XULDocument = Ci.nsIDOMXULDocument
9 CONTAINER_ID = 'VimFxHelpDialogContainer'
11 removeHelp = (document) ->
12 document.getElementById(CONTAINER_ID)?.remove()
14 injectHelp = (document, commands) ->
15 if document.documentElement
18 if document instanceof XULDocument
19 container = document.createElement('box')
20 # The `.VimFxReset` class is not needed in XUL documents. Instead it actullay causes layout
23 container = document.createElement('div')
24 container.className = 'VimFxReset'
25 container.id = CONTAINER_ID
27 container.appendChild(utils.parseHTML(document, helpDialogHtml(commands)))
29 document.documentElement.appendChild(container)
31 installHandlers(document, commands)
33 if button = document.getElementById('VimFxClose')
34 clickHandler = (event) ->
35 event.stopPropagation()
36 event.preventDefault()
38 button.addEventListener('click', clickHandler, false)
40 installHandlers = (document, commands) ->
41 promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
43 changeHandler = (event) ->
44 name = event.target.getAttribute('data-name')
45 cmd = commands.reduce(((m, v) -> if (v.name == name) then v else m), null)
46 cmd.enabled(event.target.checked)
48 for cb in document.getElementsByClassName('VimFxKeyCheckbox')
49 cb.addEventListener('change', changeHandler)
51 removeHandler = (event) ->
52 event.preventDefault()
53 event.stopPropagation()
54 key = event.target.getAttribute('data-key')
55 name = event.target.getAttribute('data-command')
56 if cmd = commands.reduce(((m, v) -> if (v.name == name) then v else m), null)
57 title = _('help_remove_shortcut_title')
58 text = _('help_remove_shortcut_text')
59 if promptService.confirm(document.defaultView, title, text)
60 cmd.keys(cmd.keys().filter((a) -> a != key))
61 event.target.parentNode.removeChild(event.target)
63 for a in document.getElementsByClassName('VimFxKeyLink')
64 a.addEventListener('click', removeHandler)
66 addHandler = (event) ->
67 event.preventDefault()
68 event.stopPropagation()
69 name = event.target.getAttribute('data-command')
70 if cmd = commands.reduce(((m, v) -> if (v.name == name) then v else m), null)
71 title = _('help_add_shortcut_title')
72 text = _('help_add_shortcut_text')
73 value = { value: null }
74 check = { value: null }
75 if promptService.prompt(document.defaultView, title, text, value, null, check)
76 if commands.filter((c) => c.keys().indexOf(value.value) != -1).length > 0
77 textError = _('help_add_shortcut_text_already_exists')
78 promptService.alert(document.defaultView, title, textError)
80 cmd.keys(cmd.keys().concat(value.value))
81 for div in document.getElementsByClassName('VimFxKeySequence')
82 if div.getAttribute('data-command') == cmd.name
83 node = utils.parseHTML(document, hint(cmd, value.value))
84 node.querySelector('a').addEventListener('click', removeHandler)
87 for a in document.getElementsByClassName('VimFxAddShortcutLink')
88 a.addEventListener('click', addHandler, false)
90 td = (text, klass='') ->
91 """<td class="VimFxReset #{ klass }">#{ text }</td>"""
94 keyDisplay = key.replace(/,/g, '')
95 """<a href="#" class="VimFxReset VimFxKeyLink" title="#{ _('help_remove_shortcut') }"
96 data-command="#{ cmd.name }" data-key="#{ key }">#{ keyDisplay }</a>"""
99 checked = if cmd.enabled() then 'checked' else null
101 <div class="VimFxKeySequence" data-command="#{ cmd.name }">
102 #{ (hint(cmd, key) for key in cmd.keys()).join('\n') }
105 dot = """<span class="VimFxReset VimFxDot">∙</span>"""
106 cb = """<input type="checkbox" class="VimFxReset VimFxKeyCheckbox" data-name="#{ cmd.name }" #{ checked }></input>"""
107 a = """#{ cmd.help() }"""
109 <a href="#" data-command="#{ cmd.name }"
110 class="VimFxReset VimFxAddShortcutLink" title="#{ _('help_add_shortcut') }">⊞</a>
114 <tr class="VimFxReset">
123 table = (commands) ->
125 <table class="VimFxReset">
126 #{ (tr(cmd) for cmd in commands).join('') }
130 section = (title, commands) ->
132 <div class="VimFxReset VimFxSectionTitle">#{ title }</div>
136 helpDialogHtml = (commands) ->
138 <div id="VimFxHelpDialog" class="VimFxReset">
139 <div class="VimFxReset VimFxHeader">
140 <div class="VimFxReset VimFxTitle">
141 <span class="VimFxReset VimFxTitleVim">Vim</span><span class="VimFxReset VimFxTitleFx">Fx</span>
142 <span class="VimFxReset">#{ _('help_title') }</span>
144 <span class="VimFxReset VimFxVersion">#{ _('help_version') } #{ utils.getVersion() }</span>
145 <a class="VimFxReset VimFxClose" id="VimFxClose" href="#">✖</a>
146 <div class="VimFxReset VimFxClearFix"></div>
149 <div class="VimFxReset VimFxBody">
150 <div class="VimFxReset VimFxColumn">
151 #{ section(_('help_section_urls'), commands.filter((a) -> a.group == 'urls')) }
152 #{ section(_('help_section_nav'), commands.filter((a) -> a.group == 'nav')) }
154 <div class="VimFxReset VimFxColumn">
155 #{ section(_('help_section_tabs'), commands.filter((a) -> a.group == 'tabs')) }
156 #{ section(_('help_section_browse'), commands.filter((a) -> a.group == 'browse')) }
157 #{ section(_('help_section_misc'), commands.filter((a) -> a.group == 'misc')) }
159 <div class="VimFxReset VimFxClearFix"></div>
162 <div class="VimFxReset VimFxFooter">
163 <p class="VimFxReset">#{ _('help_overlapping_hints') }</p>
164 <p class="VimFxReset">
165 #{ _('help_found_bug') }
166 <a class="VimFxReset" target="_blank" href="https://github.com/akhodakivskiy/VimFx/issues">
167 #{ _('help_report_bug') }
170 <p class="VimFxReset">
171 #{ _('help_enjoying') }
172 <a class="VimFxReset" target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/vimfx/">
173 #{ _('help_feedback') }
180 exports.injectHelp = injectHelp
181 exports.removeHelp = removeHelp