diff --git a/src/pyj/read_book/hints.pyj b/src/pyj/read_book/hints.pyj index 366ace09af..b583950722 100644 --- a/src/pyj/read_book/hints.pyj +++ b/src/pyj/read_book/hints.pyj @@ -1,6 +1,7 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2020, Kovid Goyal from __python__ import bound_methods, hash_literals +from read_book.shortcuts import shortcut_for_key_event class Hints: @@ -44,11 +45,38 @@ class Hints: def on_keydown(self, ev): ev.preventDefault(), ev.stopPropagation() + if ev.key is 'Escape': + self.hide() + return + if ev.key is 'Backspace': + if self.current_prefix: + self.current_prefix = self.current_prefix[:-1] + self.apply_prefix() + return + hint_keys = list('01234567890abcdefghijklmnopqrstuvwxyz') + q = ev.key.toLowerCase() + if hint_keys.indexOf(q) > -1: + self.current_prefix += q + self.apply_prefix() + + sc_name = shortcut_for_key_event(ev, self.view.keyboard_shortcut_map) + if not sc_name: + return def container_clicked(self, ev): ev.stopPropagation(), ev.preventDefault() self.hide() + def apply_prefix(self): + matches = v'[]' + if self.current_prefix: + for k in Object.keys(self.hints_map): + if k.startswith(self.current_prefix): + matches.push(k) + if matches.length is 1: + self.send_message('activate', hint=self.hints_map[matches[0]]) + self.hide() + def send_message(self, type, **kw): self.view.iframe_wrapper.send_message('hints', type=type, **kw) @@ -72,15 +100,15 @@ def hint_visible_links(link_attr): if is_visible(a): i += 1 h = i + '' - a.setAttribute('calibre-hint-render', i.toString(36)) - a.setAttribute('calibre-hint-value', h) - hint_map[h] = {'type': 'link', 'data':a.getAttribute(link_attr)} + a.dataset.calibreHintRender = i.toString(36) + a.dataset.calibreHintValue = h a.classList.add('calibre-hint-visible') + hint_map[h] = {'type': 'link', 'data':JSON.parse(a.getAttribute(link_attr)), 'value': i} return hint_map def unhint_links(link_attr): for a in document.body.querySelectorAll(f'a[{link_attr}]'): a.classList.remove('calibre-hint-visible') - a.removeAttribute('calibre-hint-render') - a.removeAttribute('calibre-hint-value') + v'delete a.dataset.calibreHintRender' + v'delete a.dataset.calibreHintValue' diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index bd4cb51710..379161f2bd 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -677,17 +677,19 @@ class IframeBoss: except: print('WARNING: Failed to parse link data {}, ignoring'.format(evt.currentTarget?.getAttribute?(self.link_attr))) return - name, frag = data.name, data.frag + self.activate_link(data.name, data.frag, evt.currentTarget) + + def activate_link(self, name, frag, target_elem): if not name: name = current_spine_item().name try: - is_popup = is_footnote_link(evt.currentTarget, name, frag, current_spine_item().name, self.book.manifest.link_to_map or {}) + is_popup = is_footnote_link(target_elem, name, frag, current_spine_item().name, self.book.manifest.link_to_map or {}) except: import traceback traceback.print_exc() is_popup = False if is_popup: - self.send_message('show_footnote', name=name, frag=frag, title=evt.currentTarget.textContent, cols_per_screen=calc_columns_per_screen()) + self.send_message('show_footnote', name=name, frag=frag, title=target_elem.textContent, cols_per_screen=calc_columns_per_screen()) return if name is current_spine_item().name: self.replace_history_on_next_cfi_update = False @@ -927,6 +929,11 @@ class IframeBoss: self.send_message('hints', type='shown', hints_map=hints_map) elif data.type is 'hide': unhint_links(self.link_attr) + elif data.type is 'activate': + hint = data.hint + if hint.type is 'link': + a = document.body.querySelector(f'[data-calibre-hint-value="{hint.value}"]') + self.activate_link(hint.data.name, hint.data.frag, a) def main(): diff --git a/src/pyj/read_book/settings.pyj b/src/pyj/read_book/settings.pyj index bb11040ebd..6a2fe7f443 100644 --- a/src/pyj/read_book/settings.pyj +++ b/src/pyj/read_book/settings.pyj @@ -114,7 +114,7 @@ def apply_colors(is_content_popup): # follow links hint box text += f'''\n\n .calibre-hint-visible::before {{ - content: attr(calibre-hint-render);\ + content: attr(data-calibre-hint-render);\ text-decoration: none !important;\ font-weight: bold !important;\ color: {selfg} !important;\