mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
EPUB CFI basically works. Now for the more comprehensive testing.
This commit is contained in:
parent
6f1824c2eb
commit
5fb8a6d833
@ -58,16 +58,6 @@ get_current_time = (target) -> # {{{
|
|||||||
fstr(ans)
|
fstr(ans)
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
set_current_time = (target, val) -> # {{{
|
|
||||||
if target.currentTime == undefined
|
|
||||||
return
|
|
||||||
if target.readyState == 4 or target.readyState == "complete"
|
|
||||||
target.currentTime = val
|
|
||||||
else
|
|
||||||
fn = -> target.currentTime = val
|
|
||||||
target.addEventListener("canplay", fn, false)
|
|
||||||
|
|
||||||
#}}}
|
|
||||||
|
|
||||||
class CanonicalFragmentIdentifier
|
class CanonicalFragmentIdentifier
|
||||||
|
|
||||||
@ -76,13 +66,23 @@ class CanonicalFragmentIdentifier
|
|||||||
|
|
||||||
constructor: () ->
|
constructor: () ->
|
||||||
|
|
||||||
|
set_current_time: (target, val) -> # {{{
|
||||||
|
if target.currentTime == undefined
|
||||||
|
return
|
||||||
|
if target.readyState == 4 or target.readyState == "complete"
|
||||||
|
target.currentTime = val
|
||||||
|
else
|
||||||
|
fn = -> target.currentTime = val
|
||||||
|
target.addEventListener("canplay", fn, false)
|
||||||
|
#}}}
|
||||||
|
|
||||||
encode: (doc, node, offset, tail) -> # {{{
|
encode: (doc, node, offset, tail) -> # {{{
|
||||||
cfi = tail or ""
|
cfi = tail or ""
|
||||||
|
|
||||||
# Handle the offset, if any
|
# Handle the offset, if any
|
||||||
switch node.nodeType
|
switch node.nodeType
|
||||||
when 1 # Element node
|
when 1 # Element node
|
||||||
if typeoff(offset) == 'number'
|
if typeof(offset) == 'number'
|
||||||
node = node.childNodes.item(offset)
|
node = node.childNodes.item(offset)
|
||||||
when 3, 4, 5, 6 # Text/entity/CDATA node
|
when 3, 4, 5, 6 # Text/entity/CDATA node
|
||||||
offset or= 0
|
offset or= 0
|
||||||
@ -136,7 +136,7 @@ class CanonicalFragmentIdentifier
|
|||||||
node = doc
|
node = doc
|
||||||
|
|
||||||
until cfi.length < 1 or error
|
until cfi.length < 1 or error
|
||||||
if ( (r = cfi.match(simple_node_regex)) is not null ) # Path step
|
if (r = cfi.match(simple_node_regex)) # Path step
|
||||||
target = parseInt(r[1])
|
target = parseInt(r[1])
|
||||||
assertion = r[2]
|
assertion = r[2]
|
||||||
if assertion
|
if assertion
|
||||||
@ -318,22 +318,31 @@ class CanonicalFragmentIdentifier
|
|||||||
try_list = [{start:0, end:0, a:0.5}, {start:0, end:1, a:1}, {start:-1, end:0, a:0}]
|
try_list = [{start:0, end:0, a:0.5}, {start:0, end:1, a:1}, {start:-1, end:0, a:0}]
|
||||||
else
|
else
|
||||||
try_list = [{start:0, end:0, a:0.5}, {start:-1, end:0, a:0}, {start:0, end:1, a:1}]
|
try_list = [{start:0, end:0, a:0.5}, {start:-1, end:0, a:0}, {start:0, end:1, a:1}]
|
||||||
k = 0
|
|
||||||
a = null
|
a = null
|
||||||
rects = null
|
rects = null
|
||||||
node_len = node.nodeValue.length
|
node_len = node.nodeValue.length
|
||||||
until rects or rects.length or k >= try_list.length
|
offset = r.offset
|
||||||
t = try_list[k++]
|
for i in [0, 1]
|
||||||
start_offset = r.offset + t.start
|
# Try reducing the offset by 1 if we get no match as if it refers to the position after the
|
||||||
end_offset = r.offset + t.end
|
# last character we wont get a match with getClientRects
|
||||||
a = t.a
|
offset = r.offset - i
|
||||||
if start_offset < 0 or end_offset >= node_len
|
if offset < 0
|
||||||
continue
|
offset = 0
|
||||||
range.setStart(node, start_offset)
|
k = 0
|
||||||
range.setEnd(node, end_offset)
|
until rects?.length or k >= try_list.length
|
||||||
rects = range.getClientRects()
|
t = try_list[k++]
|
||||||
|
start_offset = offset + t.start
|
||||||
|
end_offset = offset + t.end
|
||||||
|
a = t.a
|
||||||
|
if start_offset < 0 or end_offset >= node_len
|
||||||
|
continue
|
||||||
|
range.setStart(node, start_offset)
|
||||||
|
range.setEnd(node, end_offset)
|
||||||
|
rects = range.getClientRects()
|
||||||
|
if rects?.length
|
||||||
|
break
|
||||||
|
|
||||||
if not rects or not rects.length
|
if not rects?.length
|
||||||
log("Could not find caret position: rects: #{ rects } offset: #{ r.offset }")
|
log("Could not find caret position: rects: #{ rects } offset: #{ r.offset }")
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
@ -6,19 +6,59 @@
|
|||||||
Released under the GPLv3 License
|
Released under the GPLv3 License
|
||||||
###
|
###
|
||||||
|
|
||||||
|
log = (error) ->
|
||||||
|
if error
|
||||||
|
if window?.console?.log
|
||||||
|
window.console.log(error)
|
||||||
|
else if process?.stdout?.write
|
||||||
|
process.stdout.write(error + '\n')
|
||||||
|
|
||||||
viewport_top = (node) ->
|
viewport_top = (node) ->
|
||||||
$(node).offset().top - window.pageYOffset
|
$(node).offset().top - window.pageYOffset
|
||||||
|
|
||||||
viewport_left = (node) ->
|
viewport_left = (node) ->
|
||||||
$(node).offset().left - window.pageXOffset
|
$(node).offset().left - window.pageXOffset
|
||||||
|
|
||||||
window.onload = ->
|
show_cfi = (dont_seek) ->
|
||||||
h1 = document.getElementsByTagName('h1')[0]
|
if window.current_cfi
|
||||||
x = h1.scrollLeft + 150
|
pos = window.cfi.point(window.current_cfi)
|
||||||
y = viewport_top(h1) + h1.offsetHeight/2
|
ms = document.getElementById("marker").style
|
||||||
e = document.elementFromPoint x, y
|
if pos
|
||||||
if e.getAttribute('id') != 'first-h1'
|
ms.visibility = "visible"
|
||||||
alert 'Failed to find top h1'
|
ms.top = (pos.y - 30) + window.scrollY + "px"
|
||||||
return
|
ms.left = (pos.x - 1) + window.scrollX + "px"
|
||||||
alert window.cfi.at x, y
|
if not dont_seek
|
||||||
|
if typeof pos.time == "number"
|
||||||
|
window.cfi.set_current_time(pos.node, pos.time)
|
||||||
|
scrollTo(0, pos.y - 30)
|
||||||
|
null
|
||||||
|
|
||||||
|
RELOAD = true
|
||||||
|
|
||||||
|
mark_and_reload = (evt) ->
|
||||||
|
window.current_cfi = window.cfi.at(evt.clientX, evt.clientY)
|
||||||
|
if not RELOAD
|
||||||
|
show_cfi(true)
|
||||||
|
if window.current_cfi
|
||||||
|
fn = () ->
|
||||||
|
newloc = window.location.href.replace(/#.*$/, '') + "#epubcfi(#{ window.current_cfi })"
|
||||||
|
window.location.replace(newloc)
|
||||||
|
if RELOAD
|
||||||
|
window.location.reload()
|
||||||
|
|
||||||
|
setTimeout(fn, 1)
|
||||||
|
null
|
||||||
|
|
||||||
|
window.onload = ->
|
||||||
|
window.onscroll = show_cfi
|
||||||
|
window.onresize = show_cfi
|
||||||
|
document.onclick = mark_and_reload
|
||||||
|
for iframe in document.getElementsByTagName("iframe")
|
||||||
|
iframe.contentWindow.onscroll = show_cfi
|
||||||
|
r = location.hash.match(/#epubcfi\((.+)\)$/)
|
||||||
|
if r
|
||||||
|
window.current_cfi = r[1]
|
||||||
|
setTimeout(show_cfi, 1)
|
||||||
|
null
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 id="first-h1" style="border: solid 1px red">Testing CFI functionality</h1>
|
<h1 id="first-h1" style="border: solid 1px red">Testing CFI functionality</h1>
|
||||||
|
<img id="marker" style="position: absolute; visibility: hidden;" src="marker.png" alt="Marker" />
|
||||||
|
<p>0123</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
BIN
src/calibre/ebooks/oeb/display/test/marker.png
Normal file
BIN
src/calibre/ebooks/oeb/display/test/marker.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 751 B |
@ -10,7 +10,8 @@ __docformat__ = 'restructuredtext en'
|
|||||||
'''
|
'''
|
||||||
Utilities to help with developing coffeescript based apps
|
Utilities to help with developing coffeescript based apps
|
||||||
'''
|
'''
|
||||||
import time, SimpleHTTPServer, SocketServer, os, subprocess, cStringIO
|
import time, SimpleHTTPServer, SocketServer, os, subprocess
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
|||||||
self.send_header("Content-Length", bytes(len(raw)))
|
self.send_header("Content-Length", bytes(len(raw)))
|
||||||
self.send_header("Last-Modified", self.date_time_string(int(mtime)))
|
self.send_header("Last-Modified", self.date_time_string(int(mtime)))
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
return cStringIO.StringIO(raw)
|
return BytesIO(raw)
|
||||||
|
|
||||||
return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
|
return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user