diff --git a/src/pyj/read_book/goto.pyj b/src/pyj/read_book/goto.pyj index 533447ef3c..f02c1e51b9 100644 --- a/src/pyj/read_book/goto.pyj +++ b/src/pyj/read_book/goto.pyj @@ -1,14 +1,16 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2016, Kovid Goyal -from __python__ import hash_literals, bound_methods +from __python__ import bound_methods, hash_literals -from dom import set_css from elementmaker import E from gettext import gettext as _ -from book_list.item_list import create_item, build_list -from read_book.toc import get_toc_maps, get_border_nodes -from read_book.globals import current_book +from book_list.item_list import build_list, create_item +from dom import ensure_id, set_css +from modals import error_dialog +from read_book.globals import current_book, ui_operations +from read_book.toc import get_border_nodes, get_toc_maps +from widgets import create_button def create_goto_list(onclick, current_cfi): @@ -24,8 +26,10 @@ def create_goto_list(onclick, current_cfi): items.push(create_item(_('Previous section'), icon='caret-left', subtitle=before.title, action=onclick.bind(None, before.dest, before.frag))) items.push(create_item(_('Document start'), action=onclick.bind(None, def(view): view.goto_doc_boundary(True);))) items.push(create_item(_('Document end'), action=onclick.bind(None, def(view): view.goto_doc_boundary(False);))) - items.push(create_item(_('Metadata'), subtitle=_('Details about this book'), action=onclick.bind(None, def(view): view.show_book_metadata();))) - items.push(create_item(_('Location'), subtitle=current_cfi or None, action=onclick.bind(None, def(view): view.ask_for_location();))) + items.push(create_item(_('Metadata'), subtitle=_('Details about this book'), action=onclick.bind(None, def(view): + view.overlay.show_metadata() + ))) + items.push(create_item(_('Location'), subtitle=current_cfi or None, action=onclick.bind(None, def(view): view.overlay.show_ask_for_location();))) for l in landmarks: items.push(create_item(l.title, action=onclick.bind(None, l.dest, l.frag))) build_list(ans, items) @@ -44,3 +48,45 @@ def create_goto_panel(current_cfi, book, container, onclick): set_css(container, display='flex', flex_direction='column') set_css(panel, flex_grow='10') container.appendChild(panel) + + +def create_location_overlay(current_cfi, overlay, container): + container_id = ensure_id(container) + if current_cfi: + container.appendChild(E.div( + style='margin: 1rem; display: flex; align-items: baseline', + E.input( + type='text', readonly='readonly', value=_('Currently at: {}').format(current_cfi), name='current_location', + style='border-width: 0; background-color: transparent; outline: none; flex-grow: 10; font-family: inherit' + ), + create_button(_('Copy'), action=def(): + src = document.querySelector(f'#{container_id} [name=current_location]') + orig = src.value + src.value = current_cfi + src.focus() + src.select() + try: + document.execCommand('copy') + finally: + src.value = orig + src.blur() + ) + )) + + container.appendChild(E.div( + style='margin: 1rem;', + E.div( + style='display: flex; align-items: baseline', + E.label(_('Go to:'), style='margin-right: 1rem'), + E.input(name='newloc', type='text', style='flex-grow: 10; margin-right: 1rem'), E.span(' '), + create_button(_('Go'), action=def(): + src = document.querySelector(f'#{container_id} [name=newloc]') + if src.value: + if ui_operations.goto_bookpos(src.value): + overlay.hide() + else: + error_dialog(_('No such location'), _( + 'No location {} found').format(src.value)) + ) + ) + )) diff --git a/src/pyj/read_book/overlay.pyj b/src/pyj/read_book/overlay.pyj index 2a3cc4e4dc..64831622e6 100644 --- a/src/pyj/read_book/overlay.pyj +++ b/src/pyj/read_book/overlay.pyj @@ -5,13 +5,14 @@ from __python__ import bound_methods, hash_literals from elementmaker import E from gettext import gettext as _ +from book_list.book_details import CLASS_NAME as BD_CLASS_NAME, render_metadata from book_list.library_data import sync_library_books from book_list.router import home from book_list.theme import get_color from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id from modals import error_dialog from read_book.globals import runtime, ui_operations -from read_book.goto import create_goto_panel +from read_book.goto import create_goto_panel, create_location_overlay from read_book.open_book import create_open_book from read_book.prefs.font_size import create_font_size_panel from read_book.prefs.main import create_prefs_panel @@ -170,8 +171,7 @@ class SyncBook: # {{{ # }}} -# MainOverlay {{{ - +# CSS {{{ MAIN_OVERLAY_TS_CLASS = 'read-book-main-overlay-top-section' MAIN_OVERLAY_ACTIONS_CLASS = 'read-book-main-overlay-actions' @@ -188,8 +188,22 @@ add_extra_css(def(): style += build_rule(sel + ':active > *:first-child', transform='scale(1.8)') return style ) +# }}} -class MainOverlay: +def simple_overlay_title(title, overlay, container): + container.style.backgroundColor = get_color('window-background') + container.appendChild(E.div( + style='padding: 1ex 1em; border-bottom: solid 1px currentColor; display:flex; justify-content: space-between', + E.h2(title), + E.div(svgicon('close'), style='cursor:pointer', onclick=def (event): + event.preventDefault() + event.stopPropagation() + overlay.hide_current_panel(event) + , class_='simple-link'), + )) + + +class MainOverlay: # {{{ def __init__(self, overlay): self.overlay = overlay @@ -317,23 +331,30 @@ class MainOverlay: # }}} -class TOCOverlay: # {{{ +class SimpleOverlay: # {{{ + + def __init__(self, overlay, create_func, title): + self.overlay = overlay + self.create_func = create_func + self.title = title + + def on_container_click(self, evt): + pass # Dont allow panel to be closed by a click + + def show(self, container): + simple_overlay_title(self.title, self.overlay, container) + self.create_func(self.overlay, container) +# }}} + +class TOCOverlay(SimpleOverlay): # {{{ def __init__(self, overlay, create_func, title): self.overlay = overlay self.create_func = create_func or create_toc_panel self.title = title or _('Table of Contents') - def on_container_click(self, evt): - pass # Dont allow panel to be closed by a click - def show(self, container): - container.style.backgroundColor = get_color('window-background') - container.appendChild(E.div( - style='padding: 1ex 1em; border-bottom: solid 1px currentColor; display:flex; justify-content: space-between', - E.h2(self.title), - E.div(svgicon('close'), style='cursor:pointer', onclick=def(event):event.preventDefault(), event.stopPropagation(), self.overlay.hide_current_panel(event);, class_='simple-link'), - )) + simple_overlay_title(self.title, self.overlay, container) self.create_func(self.overlay.view.book, container, self.handle_activate) def handle_activate(self, dest, frag): @@ -444,7 +465,11 @@ class Overlay: return self.container.style.display is not 'none' def update_visibility(self): - self.container.style.display = 'block' if self.panels.length else 'none' + if self.panels.length: + self.container.style.display = 'block' + elif self.container.style.display is 'block': + self.container.style.display = 'none' + self.view.focus_iframe() def container_clicked(self, evt): if self.panels.length and jstype(self.panels[-1].on_container_click) is 'function': @@ -523,6 +548,24 @@ class Overlay: self.panels.push(TOCOverlay(self, create_goto_panel.bind(None, self.view.currently_showing.bookpos), _('Go to…'))) self.show_current_panel() + def show_metadata(self): + self.hide_current_panel() + + def show_metadata_overlay(mi, overlay, container): + container.appendChild(E.div(class_=BD_CLASS_NAME, style='padding: 1ex 1em')) + table = E.table(class_='metadata') + container.lastChild.appendChild(table) + render_metadata(mi, table) + + self.panels.push(SimpleOverlay(self, show_metadata_overlay.bind(None, self.view.book.metadata), self.view.book.metadata.title)) + self.show_current_panel() + + def show_ask_for_location(self): + self.hide_current_panel() + self.panels.push(SimpleOverlay( + self, create_location_overlay.bind(None, self.view.currently_showing.bookpos), _('Go to location…'))) + self.show_current_panel() + def show_search(self): self.hide() self.view.show_search() diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 1ae52c8ffe..5c89ea3154 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -7,10 +7,9 @@ from gettext import gettext as _ import read_book.iframe # noqa from ajax import ajax_send -from book_list.book_details import CLASS_NAME as BD_CLASS_NAME, render_metadata from book_list.globals import get_session_data from book_list.theme import get_color -from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id +from dom import add_extra_css, build_rule, set_css, svgicon, unique_id from iframe_comm import IframeWrapper from modals import error_dialog, warning_dialog from read_book.content_popup import ContentPopupOverlay @@ -30,7 +29,6 @@ from read_book.toc import get_current_toc_nodes, update_visible_toc_nodes from read_book.touch import set_left_margin_handler, set_right_margin_handler from session import get_device_uuid, get_interface_data from utils import html_escape, is_ios, parse_url_params, username_key -from widgets import create_button add_extra_css(def(): sel = '.book-side-margin' @@ -74,73 +72,6 @@ def show_controls_help(): )) -def setup_metadata_overlay(title): - container = document.getElementById('book-metadata-overlay') - clear(container) - container.style.display = 'block' - container.style.backgroundColor = get_color('window-background') - container.appendChild(E.div( - style='padding: 1ex 1em; border-bottom: solid 1px currentColor; display:flex; justify-content: space-between;', - E.h2(title), - E.div(svgicon('close'), style='cursor:pointer', class_='simple-link', onclick=def(event): - event.preventDefault() - event.stopPropagation() - document.getElementById('book-metadata-overlay').style.display = 'none' - ) - ) - ) - return container - - -def show_metadata_overlay(mi): - container = setup_metadata_overlay(mi.title) - container.appendChild(E.div(class_=BD_CLASS_NAME, style='padding: 1ex 1em')) - table = E.table(class_='metadata') - container.lastChild.appendChild(table) - render_metadata(mi, table) - - -def show_location_overlay(current_cfi): - container = setup_metadata_overlay(_('Go to location…')) - container_id = container.id - if current_cfi: - container.appendChild(E.div( - style='margin: 1rem; display: flex; align-items: baseline', - E.input( - type='text', readonly='readonly', value=_('Currently at: {}').format(current_cfi), name='current_location', - style='border-width: 0; background-color: transparent; outline: none; flex-grow: 10; font-family: inherit' - ), - create_button(_('Copy'), action=def(): - src = document.querySelector(f'#{container_id} [name=current_location]') - orig = src.value - src.value = current_cfi - src.focus() - src.select() - try: - document.execCommand('copy') - finally: - src.value = orig - src.blur() - ) - )) - container.appendChild(E.div( - style='margin: 1rem;', - E.div( - style='display: flex; align-items: baseline', - E.label(_('Go to:'), style='margin-right: 1rem'), - E.input(name='newloc', type='text', style='flex-grow: 10; margin-right: 1rem'), E.span(' '), - create_button(_('Go'), action=def(): - src = document.querySelector(f'#{container_id} [name=newloc]') - if src.value: - if ui_operations.goto_bookpos(src.value): - document.getElementById(container_id).style.display = 'none' - else: - error_dialog(_('No such location'), _( - 'No location {} found').format(src.value)) - ) - ) - )) - # }}} def margin_elem(sd, which, id, onclick): @@ -193,7 +124,6 @@ class View: E.div(style='position: absolute; top:0; left:0; width: 100%; pointer-events:none; display:none', id='book-search-overlay'), # search overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='book-content-popup-overlay'), # content popup overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='book-overlay'), # main overlay - E.div(style='position: absolute; top:0; left:0; width: 100%; min-height: 100%; display:none', id='book-metadata-overlay'), # book metadata overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='controls-help-overlay'), # controls help overlay ) ) @@ -317,6 +247,10 @@ class View: self.overlay.hide() self.search_overlay.hide() self.content_popup_overlay.hide() + self.focus_iframe() + + def focus_iframe(self): + self.iframe.contentWindow.focus() def show_chrome(self): self.show_chrome_counter += 1 @@ -509,13 +443,6 @@ class View: name = self.book.manifest.spine[0 if start else self.book.manifest.spine.length - 1] self.show_name(name, initial_position={'type':'frac', 'frac':0 if start else 1, 'replace_history':False}) - def show_book_metadata(self): - mi = self.book.metadata - show_metadata_overlay(mi) - - def ask_for_location(self): - show_location_overlay(self.currently_showing.bookpos) - def on_scroll_to_anchor(self, data): self.show_name(data.name, initial_position={'type':'anchor', 'anchor':data.frag, 'replace_history':False})