Implement internal links in the reader

This commit is contained in:
Kovid Goyal 2016-04-30 15:18:28 +05:30
parent 2d12abaa33
commit 804fca17e2
3 changed files with 47 additions and 9 deletions

View File

@ -8,7 +8,7 @@ from gettext import install
from read_book.globals import set_boss, set_current_spine_item, current_layout_mode, current_spine_item, set_layout_mode
from read_book.resources import finalize_resources, unserialize_html
from read_book.flow_mode import flow_to_scroll_fraction, flow_onwheel, flow_onkeydown, layout as flow_layout
from read_book.paged_mode import layout as paged_layout, scroll_to_fraction as paged_scroll_to_fraction, onwheel as paged_onwheel, onkeydown as paged_onkeydown
from read_book.paged_mode import layout as paged_layout, scroll_to_fraction as paged_scroll_to_fraction, onwheel as paged_onwheel, onkeydown as paged_onkeydown, scroll_to_elem
from read_book.settings import apply_settings
from utils import debounce
@ -76,11 +76,12 @@ class Boss:
self.handle_keydown = paged_onkeydown
self.to_scroll_fraction = paged_scroll_to_fraction
apply_settings(data.settings)
set_current_spine_item({'name':data.name, 'is_first':index is 0, 'is_last':index is spine.length - 1, 'initial_scroll_fraction':data.initial_scroll_fraction})
set_current_spine_item({'name':data.name, 'is_first':index is 0, 'is_last':index is spine.length - 1, 'initial_position':data.initial_position})
root_data = finalize_resources(self.book, data.name, data.resource_data)
unserialize_html(root_data, self.content_loaded)
def content_loaded(self):
self.connect_links()
document.documentElement.style.overflow = 'hidden'
window.addEventListener('scroll', debounce(self.update_cfi, 1000))
window.addEventListener('resize', debounce(self.onresize, 500))
@ -88,8 +89,12 @@ class Boss:
window.addEventListener('keydown', self.onkeydown)
self.do_layout()
csi = current_spine_item()
if csi.initial_scroll_fraction is not None:
self.to_scroll_fraction(csi.initial_scroll_fraction)
if csi.initial_position:
ipos = csi.initial_position
if ipos.type is 'frac':
self.to_scroll_fraction(ipos.frac)
elif ipos.type is 'anchor':
self.scroll_to_anchor(ipos.anchor)
def update_cfi(self):
pass # TODO: Update CFI
@ -112,6 +117,32 @@ class Boss:
data = self.gcm_to_parent.encrypt(JSON.stringify(data))
window.parent.postMessage(data, '*')
def connect_links(self):
link_attr = 'data-' + self.book.manifest.link_uid
for a in document.body.querySelectorAll('a[{}]'.format(link_attr)):
a.addEventListener('click', self.link_activated)
def link_activated(self, evt):
link_attr = 'data-' + self.book.manifest.link_uid
try:
data = JSON.parse(evt.currentTarget.getAttribute(link_attr))
except:
return
name, frag = data.name, data.frag
if name is current_spine_item().name:
self.scroll_to_anchor(frag)
else:
self.send_message('scroll_to_anchor', name=name, frag=frag)
def scroll_to_anchor(self, frag):
if frag:
elem = document.getElementById(frag)
if not elem:
c = document.getElementsByName(frag)
if c and c.length:
elem = c[0]
if elem:
scroll_to_elem(elem)
def init():
script = document.getElementById('bootstrap')

View File

@ -361,6 +361,9 @@ def jump_to_anchor(name):
elem = elems[0]
if not elem:
return
scroll_to_elem(elem)
def scroll_to_elem(elem):
# TODO: Re-enable this once you have added mathjax support
# if window.mathjax?.math_present
# # MathJax links to children of SVG tags and scrollIntoView doesn't

View File

@ -61,6 +61,7 @@ class View:
'error': self.on_iframe_error,
'next_spine_item': self.on_next_spine_item,
'goto_doc_boundary': self.goto_doc_boundary,
'scroll_to_anchor': self.on_scroll_to_anchor,
}
self.currently_showing = {'spine':0, 'cfi':None}
@ -150,7 +151,7 @@ class View:
# TODO: Check for last open position of book
self.show_name(book.manifest.spine[1])
def show_name(self, name, initial_scroll_fraction=None, cfi=None):
def show_name(self, name, initial_position=None, cfi=None):
if self.currently_showing.loading:
return
sd = get_session_data()
@ -160,13 +161,16 @@ class View:
'read_mode': sd.get('read_mode'),
'cols_per_screen': sd.get('cols_per_screen'),
}
self.currently_showing = {'name':name, 'cfi':cfi, 'settings':settings, 'initial_scroll_fraction':initial_scroll_fraction, 'loading':True}
self.currently_showing = {'name':name, 'cfi':cfi, 'settings':settings, 'initial_position':initial_position, 'loading':True}
self.set_margins(name is self.book.manifest.title_page_name)
load_resources(self.ui.db, self.book, name, self.loaded_resources, self.show_spine_item)
def goto_doc_boundary(self, data):
name = self.book.manifest.spine[0 if data.start else self.book.manifest.spine.length - 1]
self.show_name(name, initial_scroll_fraction=0 if data.start else 1)
self.show_name(name, initial_position={'type':'frac', 'frac':0 if data.start else 1})
def on_scroll_to_anchor(self, data):
self.show_name(data.name, initial_position={'type':'anchor', 'anchor':data.frag})
def on_next_spine_item(self, data):
spine = self.book.manifest.spine
@ -175,7 +179,7 @@ class View:
if idx is 0:
return
idx = min(spine.length - 1, max(idx - 1, 0))
self.show_name(spine[idx], initial_scroll_fraction=1)
self.show_name(spine[idx], initial_position={'type':'frac', 'frac':1})
else:
if idx is spine.length - 1:
return
@ -193,7 +197,7 @@ class View:
self.currently_showing.loading = False
self.send_message('display',
resource_data=resource_data, book=self.book, name=self.currently_showing.name,
initial_scroll_fraction=self.currently_showing.initial_scroll_fraction,
initial_position=self.currently_showing.initial_position,
settings=self.currently_showing.settings,
)
self.encrypted_communications = True