]> git.gir.st - VimFx.git/blob - extension/packages/help.coffee
Improve coding style
[VimFx.git] / extension / packages / help.coffee
1 utils = require 'utils'
2 prefs = require 'prefs'
3 { _ } = require 'l10n'
4
5 { classes: Cc, interfaces: Ci, utils: Cu } = Components
6
7 XULDocument = Ci.nsIDOMXULDocument
8
9 CONTAINER_ID = 'VimFxHelpDialogContainer'
10
11 removeHelp = (document) ->
12 document.getElementById(CONTAINER_ID)?.remove()
13
14 injectHelp = (document, commands) ->
15 if document.documentElement
16 removeHelp(document)
17
18 type = if document instanceof XULDocument then 'box' else 'div'
19 container = utils.createElement(document, type, {id: CONTAINER_ID})
20
21 container.appendChild(utils.parseHTML(document, helpDialogHtml(commands)))
22 for element in container.getElementsByTagName('*')
23 element.classList.add('VimFxReset')
24
25 document.documentElement.appendChild(container)
26
27 container.addEventListener('click',
28 removeHandler.bind(undefined, document, commands), false)
29 container.addEventListener('click',
30 addHandler.bind(undefined, document, commands), false)
31
32 if button = document.getElementById('VimFxClose')
33 clickHandler = (event) ->
34 event.stopPropagation()
35 event.preventDefault()
36 removeHelp(document)
37 button.addEventListener('click', clickHandler, false)
38
39 promptService = Cc['@mozilla.org/embedcomp/prompt-service;1']
40 .getService(Ci.nsIPromptService)
41
42 removeHandler = (document, commands, event) ->
43 return unless event.target.classList.contains('VimFxKeyLink')
44 event.preventDefault()
45 event.stopPropagation()
46 key = event.target.getAttribute('data-key')
47 name = event.target.getAttribute('data-command')
48 if cmd = commands.reduce(((m, v) -> if (v.name == name) then v else m), null)
49 title = _('help_remove_shortcut_title')
50 text = _('help_remove_shortcut_text')
51 if promptService.confirm(document.defaultView, title, text)
52 cmd.keys(cmd.keys().filter((a) -> a != key))
53 event.target.remove()
54
55 addHandler = (document, commands, event) ->
56 return unless event.target.classList.contains('VimFxAddShortcutLink')
57 event.preventDefault()
58 event.stopPropagation()
59 name = event.target.getAttribute('data-command')
60 if cmd = commands.reduce(((m, v) -> if (v.name == name) then v else m), null)
61 title = _('help_add_shortcut_title')
62 text = _('help_add_shortcut_text')
63 value = {value: null}
64 check = {value: null}
65 if promptService.prompt(document.defaultView, title, text, value, null, check)
66 return if value.value.length == 0
67 conflicts = getConflicts(commands, value.value)
68 if conflicts.length == 0 or overwriteCmd(document, conflicts, value.value)
69 cmd.keys(cmd.keys().concat(value.value))
70 for div in document.getElementsByClassName('VimFxKeySequence')
71 if div.getAttribute('data-command') == cmd.name
72 div.insertAdjacentHTML('beforeend', hint(cmd, value.value))
73 return
74
75 getConflicts = (commands, value) ->
76 conflicts = []
77 for command in commands
78 conflictingKeys = []
79 for key in command.keys()
80 shortest = Math.min(value.length, key.length)
81 if "#{ value },"[..shortest] == "#{ key },"[..shortest]
82 conflictingKeys.push(key)
83 if conflictingKeys.length > 0
84 conflicts.push({command, conflictingKeys})
85 return conflicts
86
87 overwriteCmd = (document, conflicts, key) ->
88 title = _('help_add_shortcut_title')
89 conflictSummary = conflicts.map((conflict) ->
90 return "#{ conflict.command.help() }: #{ conflict.conflictingKeys.join(' ') }"
91 ).join("\n")
92 text = """
93 #{ _('help_add_shortcut_text_overwrite', key) }
94
95 #{ conflictSummary }
96 """
97 if promptService.confirm(document.defaultView, title, text)
98 for { command, conflictingKeys } in conflicts
99 command.keys(command.keys().filter((key) -> key not in conflictingKeys))
100 for key in conflictingKeys
101 document.querySelector("a[data-key='#{ key }']").remove()
102 return true
103 else
104 return false
105
106 td = (text, klass='') ->
107 """<td class="#{ klass }">#{ text }</td>"""
108
109 hint = (cmd, key) ->
110 keyDisplay = key.replace(/,/g, '')
111 """<a href="#" class="VimFxReset VimFxKeyLink" title="#{ _('help_remove_shortcut') }"
112 data-command="#{ cmd.name }" data-key="#{ key }">#{ keyDisplay }</a>"""
113
114 tr = (cmd) ->
115 hints = """
116 <div class="VimFxKeySequence" data-command="#{ cmd.name }">
117 #{ (hint(cmd, key) for key in cmd.keys()).join('\n') }
118 </div>
119 """
120 dot = """<span class="VimFxDot">&#8729;</span>"""
121 a = """#{ cmd.help() }"""
122 add = """
123 <a href="#" data-command="#{ cmd.name }"
124 class="VimFxAddShortcutLink" title="#{ _('help_add_shortcut') }">&#8862;</a>
125 """
126
127 return """
128 <tr>
129 #{ td(hints) }
130 #{ td(add) }
131 #{ td(dot) }
132 #{ td(a) }
133 </tr>
134 """
135
136 table = (commands) ->
137 """
138 <table>
139 #{ (tr(cmd) for cmd in commands).join('') }
140 </table>
141 """
142
143 section = (title, commands) ->
144 """
145 <div class="VimFxSectionTitle">#{ title }</div>
146 #{ table(commands) }
147 """
148
149 helpDialogHtml = (commands) ->
150 return """
151 <div id="VimFxHelpDialog">
152 <div class="VimFxHeader">
153 <div class="VimFxTitle">
154 <span class="VimFxTitleVim">Vim</span><span class="VimFxTitleFx">Fx</span>
155 <span>#{ _('help_title') }</span>
156 </div>
157 <span class="VimFxVersion">#{ _('help_version') } #{ utils.getVersion() }</span>
158 <a class="VimFxClose" id="VimFxClose" href="#">&#10006;</a>
159 <div class="VimFxClearFix"></div>
160 <p>Did you know that you can add/remove shortucts in this dialog?</p>
161 <div class="VimFxClearFix"></div>
162 <p>Click the shortcut to remove it, and click &#8862; to add new shortcut!</p>
163 </div>
164
165 <div class="VimFxBody">
166 <div class="VimFxColumn">
167 #{ section(_('help_section_urls'), commands.filter((a) -> a.group == 'urls')) }
168 #{ section(_('help_section_nav'), commands.filter((a) -> a.group == 'nav')) }
169 </div>
170 <div class="VimFxColumn">
171 #{ section(_('help_section_tabs'), commands.filter((a) -> a.group == 'tabs')) }
172 #{ section(_('help_section_browse'), commands.filter((a) -> a.group == 'browse')) }
173 #{ section(_('help_section_misc'), commands.filter((a) -> a.group == 'misc')) }
174 </div>
175 <div class="VimFxClearFix"></div>
176 </div>
177
178 <div class="VimFxFooter">
179 <p>#{ _('help_overlapping_hints') }</p>
180 <p>
181 #{ _('help_found_bug') }
182 <a target="_blank" href="https://github.com/akhodakivskiy/VimFx/issues">
183 #{ _('help_report_bug') }
184 </a>
185 </p>
186 <p>
187 #{ _('help_enjoying') }
188 <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/vimfx/">
189 #{ _('help_feedback') }
190 </a>
191 </p>
192 </div>
193 </div>
194 """
195
196 exports.injectHelp = injectHelp
197 exports.removeHelp = removeHelp
Imprint / Impressum