diff --git a/imgsrc/srv/chevron-down.svg b/imgsrc/srv/chevron-down.svg new file mode 100644 index 0000000000..8177dc9bac --- /dev/null +++ b/imgsrc/srv/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/imgsrc/srv/chevron-up.svg b/imgsrc/srv/chevron-up.svg new file mode 100644 index 0000000000..563a644984 --- /dev/null +++ b/imgsrc/srv/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/pyj/complete.pyj b/src/pyj/complete.pyj index 5bfc245961..0a6cdf31e4 100644 --- a/src/pyj/complete.pyj +++ b/src/pyj/complete.pyj @@ -65,7 +65,7 @@ class EditWithComplete: self.completion_popup.set_all_items(items) -def create_search_bar(action, name, tooltip=None, placeholder=None, button=None, history_size=100): +def create_search_bar(action, name, tooltip=None, placeholder=None, button=None, history_size=100, associated_widgets=None): parent = E.div(style="display:flex") ewc = EditWithComplete(name, parent=parent, tooltip=tooltip, placeholder=placeholder, input_type='search') parent.lastChild.style.width = '100%' @@ -94,6 +94,9 @@ def create_search_bar(action, name, tooltip=None, placeholder=None, button=None, if button: ewc.add_associated_widget(button) button.addEventListener('click', trigger) + if associated_widgets is not None: + for w in associated_widgets: + ewc.add_associated_widget(w) return parent # }}} diff --git a/src/pyj/read_book/overlay.pyj b/src/pyj/read_book/overlay.pyj index fe4b5197a9..86e7285256 100644 --- a/src/pyj/read_book/overlay.pyj +++ b/src/pyj/read_book/overlay.pyj @@ -156,7 +156,7 @@ class MainOverlay: ), E.ul( - ac(_('Search'), _('Search for text in this book'), None, 'search'), + ac(_('Search'), _('Search for text in this book'), self.overlay.show_search, 'search'), ac(_('Go to'), _('Go to a specific location in the book'), self.overlay.show_goto, 'chevron-right'), ), @@ -349,6 +349,10 @@ class Overlay: self.panels.push(TOCOverlay(self, create_goto_panel, _('Go to…'))) self.show_current_panel() + def show_search(self): + self.hide() + self.view.show_search() + def show_prefs(self): self.panels = [PrefsOverlay(self)] self.show_current_panel() diff --git a/src/pyj/read_book/search.pyj b/src/pyj/read_book/search.pyj index 9857eeb0b7..d22f674799 100644 --- a/src/pyj/read_book/search.pyj +++ b/src/pyj/read_book/search.pyj @@ -2,10 +2,49 @@ # License: GPL v3 Copyright: 2017, Kovid Goyal from __python__ import hash_literals, bound_methods +from complete import create_search_bar +from dom import add_extra_css, build_rule, svgicon +from keycodes import get_key +from elementmaker import E +from gettext import gettext as _ +from book_list.theme import get_color + +CLASS_NAME = 'book-search-container' + +add_extra_css(def(): + sel = '.' + CLASS_NAME + style = build_rule(sel, text_align='right') + sel += ' > div ' + style += build_rule(sel, display='inline-flex', pointer_events='auto', background_color=get_color('window-background'), padding='1ex') + return style +) + + class SearchOverlay: def __init__(self, view): self.view = view + c = self.container + c.classList.add(CLASS_NAME) + next_button = E.div(class_='simple-link', svgicon('chevron-down'), title=_('Next match')) + prev_button = E.div(class_='simple-link', svgicon('chevron-up'), title=_('Previous match')) + prev_button.addEventListener('click', def(ev): self.find_previous();) + # We cannot use simple link for the close button as it causes the + # button to remain red when the search panel is re-opened + close_button = E.div(style='cursor:pointer', svgicon('close'), title=_('Close search bar')) + close_button.addEventListener('click', def(ev): window.setTimeout(self.hide, 0);) + c.appendChild(E.div( + svgicon('search'), '\xa0', + create_search_bar(self.find_next, 'search-in-book', placeholder=_('Search') + '…', button=next_button, associated_widgets=[prev_button, close_button]), + '\xa0', next_button, '\xa0', prev_button, '\xa0', close_button + )) + c.firstChild.addEventListener('keydown', self.onkeydown) + + def onkeydown(self, event): + k = get_key(event) + if k is 'escape': + self.hide() + event.preventDefault(), event.stopPropagation() @property def container(self): @@ -13,3 +52,14 @@ class SearchOverlay: def hide(self): self.container.style.display = 'none' + + def show(self): + c = self.container + c.style.display = 'block' + c.querySelector('input').focus() + + def find_next(self): + pass + + def find_previous(self): + pass diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 4a5384de0b..374e3b9420 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -68,7 +68,7 @@ class View: E.div(style='height:{}px; width:100%; padding: 0'.format(sd.get('margin_bottom', 20)), id='book-bottom-margin'), ), right_margin, - E.div(style='position: absolute; top:0; left:0; width: 100%; display:none', id='book-search-overlay'), # search overlay + 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-overlay'), # main overlay ) ) @@ -127,6 +127,10 @@ class View: self.search_overlay.hide() self.overlay.show() + def show_search(self): + self.overlay.hide() + self.search_overlay.show() + def set_margins(self): no_margins = self.currently_showing.name is self.book.manifest.title_page_name sd = get_session_data()