2016-12-30 15:04:26 +05:30

146 lines
5.3 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import hash_literals
from complete import create_search_bar
from dom import set_css, svgicon, ensure_id
from elementmaker import E
from gettext import gettext as _
from modals import error_dialog
from widgets import create_tree, find_text_in_tree, scroll_tree_item_into_view
from read_book.globals import toc_anchor_map, set_toc_anchor_map, current_spine_item, current_layout_mode
def update_visible_toc_nodes(visible_anchors):
update_visible_toc_nodes.data = visible_anchors
update_visible_toc_nodes.data = {}
def iter_toc_nodes(node, callback):
if callback(node):
return
for child in node.children:
if callback(child):
return
def get_highlighted_toc_nodes(toc, spine, parent_map, id_map):
data = update_visible_toc_nodes.data
ans = {}
if data.has_visible:
ans = data.visible_anchors
else:
if data.before:
ans[data.before] = True
else:
nodes_before = v'[]'
iter_toc_nodes(toc, def(node):
if node.dest is current_spine_item():
return True
nodes_before.push(node)
)
if nodes_before.length:
ans[nodes_before[-1].id] = True
for node_id in Object.keys(ans):
pid = parent_map[node_id]
while pid:
ans[pid] = True
pid = parent_map[pid]
return ans
def create_toc_tree(toc, onclick):
parent_map, id_map = {}, {}
def process_node(node, parent):
id_map[node.id] = node
parent_map[node.id] = parent
for c in node.children:
process_node(c, node)
process_node(toc)
highlighted_toc_nodes = get_highlighted_toc_nodes(toc, parent_map, id_map)
def populate_data(node, li, a):
li.dataset.tocDest = node.dest or ''
li.dataset.tocFrag = node.frag or ''
title = node.title or ''
if highlighted_toc_nodes[node.id]:
a.appendChild(E.b(E.i(title)))
else:
a.textContent = title
return create_tree(toc, populate_data, onclick)
def do_search(text):
container = document.getElementById(this)
a = find_text_in_tree(container, text)
if not text:
return
if not a:
return error_dialog(_('No matches found'), _(
'The text "{}" was not found in the Table of Contents').format(text))
scroll_tree_item_into_view(a)
def create_toc_panel(book, container, onclick, onclose):
container.appendChild(E.div(
style='display: flex; justify-content: space-between; padding: 1ex 1em; border-bottom: solid 1px currentColor',
E.h2(_('Table of Contents')),
E.div(svgicon('close'), style='cursor:pointer', onclick=def(event):event.preventDefault(), event.stopPropagation(), onclose(event);, class_='simple-link'),
))
def handle_click(event, li):
if event.button is 0:
onclick(li.dataset.tocDest, li.dataset.tocFrag)
toc_panel = create_toc_tree(book.manifest.toc, handle_click)
toc_panel_id = ensure_id(toc_panel)
set_css(container, display='flex', flex_direction='column')
set_css(toc_panel, flex_grow='10')
container.appendChild(toc_panel)
search_button = E.div(class_='simple-link', svgicon('search'))
t = _('Search Table of Contents')
search_bar = create_search_bar(do_search.bind(toc_panel_id), 'search-book-toc', button=search_button, placeholder=t)
set_css(search_bar, flex_grow='10', margin_right='1em')
container.appendChild(E.div(style='margin: 1ex 1em; display: flex;', search_bar, search_button))
def current_toc_anchor_map(tam, anchor_funcs):
current_map = toc_anchor_map()
if not (current_map and current_map.layout_mode is current_layout_mode() and current_map.width is window.innerWidth and current_map.height is window.innerHeight):
name = current_spine_item().name
am = {}
anchors = v'[]'
for anchor in (tam[name] or v'[]'):
val = anchor_funcs.pos_for_elem()
if anchor.frag:
elem = document.getElementById(anchor.frag)
if elem:
val = anchor_funcs.pos_for_elem(elem)
am[anchor.id] = val
anchors.push(anchor.id)
anchors.sort(def (a, b): anchor_funcs.cmp(am[a], am[b]);)
sort_map = {aid: i for i, aid in enumerate(anchors)}
current_map = {'layout_mode': current_layout_mode, 'width': window.innerWidth, 'height': window.innerHeight, 'pos_map': am, 'sort_map':sort_map}
set_toc_anchor_map(current_map)
return current_map
def update_visible_toc_anchors(toc_anchor_map, anchor_funcs):
tam = current_toc_anchor_map(toc_anchor_map, anchor_funcs)
before = after = None
visible_anchors = {}
has_visible = False
for anchor_id in tam.pos_map:
pos = tam.pos_map[anchor_id]
visibility = anchor_funcs.visibility(pos)
if visibility < 0:
before = anchor_id
elif visibility is 0:
has_visible = True
visible_anchors[anchor_id] = True
elif visibility > 0:
after = anchor_id
break
return {'visible_anchors':visible_anchors, 'has_visible':has_visible, 'before':before, 'after':after}