mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement internal links in the reader
This commit is contained in:
parent
2d12abaa33
commit
804fca17e2
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user