2013-03-31 09:41:38 +00:00
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab filetype=javascript : */
2012-09-22 14:47:44 +00:00
/ *
2013-05-02 08:25:39 +00:00
* pdf2htmlEX . js : a simple demo UI for pdf2htmlEX
2012-09-22 14:47:44 +00:00
*
* handles UI events / actions / effects
2013-05-02 08:25:39 +00:00
* Copyright 2012 , 2013 Lu Wang < coolwanglu @ gmail . com >
2012-09-22 14:47:44 +00:00
* /
2013-05-29 18:31:48 +00:00
'use strict' ;
2012-09-23 09:26:12 +00:00
var pdf2htmlEX = ( function ( ) {
2013-02-27 18:11:34 +00:00
var CSS _CLASS _NAMES = {
page _frame : '@CSS_PAGE_FRAME_CN@' ,
page _decoration : '@CSS_PAGE_DECORATION_CN@' ,
page _content _box : '@CSS_PAGE_CONTENT_BOX_CN@' ,
page _data : '@CSS_PAGE_DATA_CN@' ,
2013-03-01 06:02:11 +00:00
background _image : '@CSS_BACKGROUND_IMAGE_CN@' ,
2013-02-27 18:52:00 +00:00
link : '@CSS_LINK_CN@' ,
2013-02-27 18:11:34 +00:00
_ _dummy _ _ : 'no comma'
} ;
2013-06-13 10:39:52 +00:00
var DEFAULT _PAGES _TO _PRELOAD = 3 ;
2013-02-27 18:11:34 +00:00
2013-08-13 09:33:06 +00:00
// Smooth zoom is enabled when pages shown are less then SMOOTH_ZOOM_THRESHOLD. Otherwise page content is hidden and redrawn after a delay (function schedule_render).
var SMOOTH _ZOOM _THRESHOLD = 4 ; // 0: disable smooth zoom optimizations (less CPU usage but flickering on zoom)
2013-07-16 18:19:25 +00:00
2012-09-25 16:27:58 +00:00
var pdf2htmlEX = new Object ( ) ;
2012-09-23 09:26:12 +00:00
var EPS = 1e-6 ;
2012-09-25 11:29:59 +00:00
var invert = function ( ctm ) {
var det = ctm [ 0 ] * ctm [ 3 ] - ctm [ 1 ] * ctm [ 2 ] ;
var ictm = new Array ( ) ;
ictm [ 0 ] = ctm [ 3 ] / det ;
ictm [ 1 ] = - ctm [ 1 ] / det ;
ictm [ 2 ] = - ctm [ 2 ] / det ;
ictm [ 3 ] = ctm [ 0 ] / det ;
ictm [ 4 ] = ( ctm [ 2 ] * ctm [ 5 ] - ctm [ 3 ] * ctm [ 4 ] ) / det ;
ictm [ 5 ] = ( ctm [ 1 ] * ctm [ 4 ] - ctm [ 0 ] * ctm [ 5 ] ) / det ;
return ictm ;
} ;
var transform = function ( ctm , pos ) {
return [ ctm [ 0 ] * pos [ 0 ] + ctm [ 2 ] * pos [ 1 ] + ctm [ 4 ]
, ctm [ 1 ] * pos [ 0 ] + ctm [ 3 ] * pos [ 1 ] + ctm [ 5 ] ] ;
} ;
2012-09-25 13:56:48 +00:00
var Page = function ( page , container ) {
2013-01-28 15:58:00 +00:00
if ( page == undefined ) return ;
2012-09-25 11:29:59 +00:00
2013-06-12 15:53:14 +00:00
this . loaded = false ;
2013-07-16 15:42:02 +00:00
this . shown = false ;
2013-06-13 15:00:42 +00:00
this . $p = $ ( page ) ;
this . $container = $ ( container ) ;
2013-06-12 15:53:14 +00:00
2013-06-13 15:00:42 +00:00
this . n = parseInt ( this . $p . data ( 'page-no' ) , 16 ) ;
this . $b = $ ( '.' + CSS _CLASS _NAMES [ 'page_content_box' ] , this . $p ) ;
2013-08-08 22:52:07 +00:00
this . $d = this . $p . parent ( '.' + CSS _CLASS _NAMES [ 'page_decoration' ] ) ;
2013-06-12 15:53:14 +00:00
2013-06-13 15:00:42 +00:00
this . h = this . $p . height ( ) ; // Need to make rescale work when page_content_box is not loaded, yet
this . w = this . $p . width ( ) ;
2012-09-25 11:29:59 +00:00
2013-06-12 15:53:14 +00:00
// if page is loaded
2013-06-13 15:00:42 +00:00
if ( this . $b . length > 0 ) {
2013-06-12 15:53:14 +00:00
/ *
* scale ratios
*
* default _r : the first one
* set _r : last set
* cur _r : currently using
* /
2013-07-16 18:19:25 +00:00
this . default _r = this . set _r = this . cur _r = this . h / this . $b . height ( ) ;
2012-09-25 11:29:59 +00:00
2013-06-13 15:08:47 +00:00
this . data = $ ( $ ( '.' + CSS _CLASS _NAMES [ 'page_data' ] , this . $p ) [ 0 ] ) . data ( 'data' ) ;
2013-06-12 15:53:14 +00:00
this . ctm = this . data . ctm ;
this . ictm = invert ( this . ctm ) ;
this . loaded = true ;
}
2012-09-23 09:26:12 +00:00
} ;
2012-09-25 16:27:58 +00:00
$ . extend ( Page . prototype , {
2013-02-06 11:52:34 +00:00
/* hide & show are for contents, the page frame is still there */
2012-09-25 16:27:58 +00:00
hide : function ( ) {
2013-06-13 15:00:42 +00:00
this . $b . removeClass ( 'opened' ) ;
2013-07-16 15:42:02 +00:00
this . shown = false ;
2012-09-25 16:27:58 +00:00
} ,
show : function ( ) {
2013-07-16 18:19:25 +00:00
if ( this . loaded ) {
if ( Math . abs ( this . set _r - this . cur _r ) > EPS ) {
this . cur _r = this . set _r ;
this . $b . css ( 'transform' , 'scale(' + this . cur _r . toFixed ( 3 ) + ')' ) ;
}
if ( ! this . shown ) {
this . $b . addClass ( 'opened' ) ;
this . shown = true ;
}
2012-09-25 16:27:58 +00:00
}
} ,
2013-07-16 18:19:25 +00:00
rescale : function ( ratio , keep _shown ) {
2012-09-25 16:27:58 +00:00
if ( ratio == 0 ) {
this . set _r = this . default _r ;
} else {
this . set _r = ratio ;
}
2012-09-23 05:04:29 +00:00
2013-07-17 07:47:13 +00:00
if ( keep _shown )
this . show ( ) ; // Refresh content
else
this . hide ( ) ; // Wait for redraw
2012-09-25 13:56:48 +00:00
2013-07-16 18:19:25 +00:00
this . $d . height ( this . h * this . set _r ) ;
this . $d . width ( this . w * this . set _r ) ;
2012-09-25 16:27:58 +00:00
} ,
2013-05-02 08:45:00 +00:00
/* return if any part of this page is shown in the container */
2012-09-25 16:27:58 +00:00
is _visible : function ( ) {
var off = this . position ( ) ;
2013-07-16 18:19:25 +00:00
return ! ( ( off [ 1 ] > this . h ) || ( off [ 1 ] + this . $container . height ( ) < 0 ) ) ;
2012-09-25 16:27:58 +00:00
} ,
2013-05-02 08:45:00 +00:00
/* return if this page or any neighbor of it is visible */
is _nearly _visible : function ( ) {
var off = this . position ( ) ;
/ * I s h o u l d u s e t h e h e i g h t o f t h e p r e v i o u s p a g e o r t h e n e x t p a g e h e r e
* but since they are not easily available , just use '*2' , which should be a good estimate in most cases
* /
2013-07-16 18:19:25 +00:00
return ! ( ( off [ 1 ] > this . h * 2 ) || ( off [ 1 ] + this . $container . height ( ) * 2 < 0 ) ) ;
2013-05-02 08:45:00 +00:00
} ,
2012-09-25 16:27:58 +00:00
/ * r e t u r n t h e c o o r d i n a t e o f t h e t o p - l e f t c o r n e r o f c o n t a i n e r
2013-08-08 22:53:44 +00:00
* in our coordinate system
2012-09-25 16:27:58 +00:00
* /
position : function ( ) {
2013-06-13 15:00:42 +00:00
var off = this . $p . offset ( ) ;
var off _c = this . $container . offset ( ) ;
2012-09-25 16:27:58 +00:00
return [ off _c . left - off . left , off _c . top - off . top ] ;
}
} ) ;
2012-09-23 05:04:29 +00:00
2013-05-01 12:01:24 +00:00
pdf2htmlEX . Viewer = function ( config ) {
this . container _id = config [ 'container_id' ] ;
this . sidebar _id = config [ 'sidebar_id' ] ;
this . outline _id = config [ 'outline_id' ] ;
2013-09-28 05:20:45 +00:00
this . loading _indicator _cls = config [ 'loading_indicator_cls' ] ;
2013-06-13 10:39:52 +00:00
this . pages _to _preload = config [ 'pages_to_preload' ] || DEFAULT _PAGES _TO _PRELOAD ;
this . pages _loading = { } ;
2012-09-25 14:40:21 +00:00
this . init _before _loading _content ( ) ;
2012-09-23 05:04:29 +00:00
2012-09-25 14:40:21 +00:00
var _ = this ;
$ ( function ( ) { _ . init _after _loading _content ( ) ; } ) ;
} ;
2012-09-25 16:27:58 +00:00
$ . extend ( pdf2htmlEX . Viewer . prototype , {
2012-09-23 09:26:12 +00:00
/* Constants */
2013-05-01 09:14:29 +00:00
render _timeout : 100 ,
2012-09-23 09:26:12 +00:00
scale _step : 0.9 ,
2013-07-16 15:42:02 +00:00
scale : 1 ,
2012-09-23 05:04:29 +00:00
2012-09-23 09:26:12 +00:00
init _before _loading _content : function ( ) {
/*hide all pages before loading, will reveal only visible ones later */
this . pre _hide _pages ( ) ;
} ,
2013-06-13 15:00:42 +00:00
2012-09-23 09:26:12 +00:00
init _after _loading _content : function ( ) {
2013-06-13 15:00:42 +00:00
this . $sidebar = $ ( '#' + this . sidebar _id ) ;
this . $outline = $ ( '#' + this . outline _id ) ;
this . $container = $ ( '#' + this . container _id ) ;
2013-09-28 05:20:45 +00:00
this . $loading _indicator = $ ( '.' + this . loading _indicator _cls ) ;
2012-09-23 05:04:29 +00:00
2013-03-01 06:02:11 +00:00
// Open the outline if nonempty
2013-07-16 15:42:02 +00:00
if ( this . $outline . children ( ) . length > 0 ) {
2013-06-13 15:00:42 +00:00
this . $sidebar . addClass ( 'opened' ) ;
2013-01-28 14:11:42 +00:00
}
2013-06-12 15:53:14 +00:00
2013-05-02 08:09:42 +00:00
this . find _pages ( ) ;
2012-09-23 05:04:29 +00:00
2013-03-01 06:02:11 +00:00
// register schedule rendering
2012-09-23 09:26:12 +00:00
var _ = this ;
2013-06-13 15:00:42 +00:00
this . $container . scroll ( function ( ) { _ . schedule _render ( ) ; } ) ;
2012-09-23 05:04:29 +00:00
2013-07-16 15:42:02 +00:00
this . zoom _fixer ( ) ;
2012-09-25 11:29:59 +00:00
2013-03-01 06:02:11 +00:00
// handle links
2013-06-13 15:00:42 +00:00
this . $container . add ( this . $outline ) . on ( 'click' , '.' + CSS _CLASS _NAMES [ 'link' ] , this , this . link _handler ) ;
2012-09-23 05:04:29 +00:00
2012-09-23 09:26:12 +00:00
this . render ( ) ;
2013-05-02 08:09:42 +00:00
} ,
2013-07-16 15:42:02 +00:00
2013-05-02 08:09:42 +00:00
find _pages : function ( ) {
var new _pages = new Array ( ) ;
2013-06-13 15:00:42 +00:00
var $pl = $ ( '.' + CSS _CLASS _NAMES [ 'page_frame' ] , this . $container ) ;
2013-05-02 08:09:42 +00:00
/* don't use for(..in..) */
2013-06-13 15:00:42 +00:00
for ( var i = 0 , l = $pl . length ; i < l ; ++ i ) {
var p = new Page ( $pl [ i ] , this . $container ) ;
2013-05-02 08:09:42 +00:00
new _pages [ p . n ] = p ;
}
this . pages = new _pages ;
} ,
2013-06-13 15:00:42 +00:00
2013-06-13 10:39:52 +00:00
load _page : function ( idx , pages _to _preload , successCallback , errorCallback ) {
if ( idx >= this . pages . length )
return ; // Page does not exist
if ( this . pages [ idx ] . loaded )
2013-06-12 15:53:14 +00:00
return ; // Page is loaded
2013-06-13 10:39:52 +00:00
if ( this . pages _loading [ idx ] )
2013-06-12 15:53:14 +00:00
return ; // Page is already loading
2013-06-13 10:39:52 +00:00
var page _no _hex = idx . toString ( 16 ) ;
2013-06-13 15:00:42 +00:00
var $pf = this . $container . find ( '#' + CSS _CLASS _NAMES [ 'page_frame' ] + page _no _hex ) ;
2013-06-12 15:53:14 +00:00
if ( $pf . length == 0 )
return ; // Page does not exist
2013-09-28 05:20:45 +00:00
this . $loading _indicator . clone ( ) . show ( ) . appendTo ( $pf ) ;
2013-09-28 03:58:01 +00:00
2013-06-12 15:53:14 +00:00
var _ = this ;
var url = $pf . data ( 'page-url' ) ;
if ( url && url . length > 0 ) {
2013-06-13 10:39:52 +00:00
this . pages _loading [ idx ] = true ; // Set semaphore
2013-06-12 15:53:14 +00:00
2013-05-02 08:09:42 +00:00
$ . ajax ( {
2013-06-12 15:53:14 +00:00
url : url ,
2013-05-02 08:09:42 +00:00
dataType : 'text'
} ) . done ( function ( data ) {
2013-07-16 15:42:02 +00:00
_ . pages [ idx ] . $d . replaceWith ( data ) ;
2013-06-12 15:53:14 +00:00
2013-06-13 15:00:42 +00:00
var $new _pf = _ . $container . find ( '#' + CSS _CLASS _NAMES [ 'page_frame' ] + page _no _hex ) ;
_ . pages [ idx ] = new Page ( $new _pf , _ . $container ) ;
2013-07-16 18:19:25 +00:00
_ . pages [ idx ] . hide ( ) ;
2013-06-13 10:39:52 +00:00
_ . pages [ idx ] . rescale ( _ . scale ) ;
2013-06-12 15:53:14 +00:00
_ . schedule _render ( ) ;
// disable background image dragging
$new _pf . find ( '.' + CSS _CLASS _NAMES [ 'background_image' ] ) . on ( 'dragstart' , function ( e ) { return false ; } ) ;
// Reset loading token
2013-06-13 10:39:52 +00:00
delete _ . pages _loading [ idx ] ;
2013-06-12 15:53:14 +00:00
if ( successCallback ) successCallback ( ) ;
2013-06-13 10:39:52 +00:00
}
) . fail ( function ( jqXHR , textStatus , errorThrown ) {
console . error ( 'error loading page ' + idx + ': ' + textStatus ) ;
// Reset loading token
delete _ . pages _loading [ idx ] ;
if ( errorCallback ) errorCallback ( ) ;
} ) ;
2013-05-02 08:09:42 +00:00
}
2013-06-12 15:53:14 +00:00
// Concurrent prefetch of the next pages
if ( pages _to _preload === undefined )
2013-06-13 10:39:52 +00:00
pages _to _preload = this . pages _to _preload ;
2013-06-12 15:53:14 +00:00
if ( -- pages _to _preload > 0 )
_ . load _page ( idx + 1 , pages _to _preload ) ;
2012-09-23 09:26:12 +00:00
} ,
2013-06-13 15:00:42 +00:00
2012-09-23 09:26:12 +00:00
pre _hide _pages : function ( ) {
/* pages might have not been loaded yet, so add a CSS rule */
2013-02-27 18:11:34 +00:00
var s = '@media screen{.' + CSS _CLASS _NAMES [ 'page_content_box' ] + '{display:none;}}' ;
2012-09-25 11:29:59 +00:00
var n = document . createElement ( 'style' ) ;
n . type = 'text/css' ;
2012-09-23 09:26:12 +00:00
if ( n . styleSheet ) {
n . styleSheet . cssText = s ;
} else {
n . appendChild ( document . createTextNode ( s ) ) ;
}
2012-09-25 11:29:59 +00:00
document . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( n ) ;
2012-09-23 09:26:12 +00:00
} ,
hide _pages : function ( ) {
var pl = this . pages ;
2012-09-25 11:29:59 +00:00
for ( var i in pl )
2012-09-23 09:26:12 +00:00
pl [ i ] . hide ( ) ;
} ,
render : function ( ) {
/* hide (positional) invisible pages */
var pl = this . pages ;
2012-09-25 11:29:59 +00:00
for ( var i in pl ) {
2012-09-23 09:26:12 +00:00
var p = pl [ i ] ;
2013-05-02 08:45:00 +00:00
if ( p . is _nearly _visible ( ) ) {
2013-06-12 15:53:14 +00:00
if ( p . loaded ) {
p . show ( ) ;
} else
2013-06-13 10:39:52 +00:00
this . load _page ( p . n ) ;
2012-09-25 13:56:48 +00:00
} else {
2012-09-25 11:29:59 +00:00
p . hide ( ) ;
2012-09-25 13:56:48 +00:00
}
2012-09-22 14:47:44 +00:00
}
2012-09-23 09:26:12 +00:00
} ,
schedule _render : function ( ) {
if ( this . render _timer )
clearTimeout ( this . render _timer ) ;
var _ = this ;
this . render _timer = setTimeout ( function ( ) {
_ . render ( ) ;
} , this . render _timeout ) ;
} ,
zoom _fixer : function ( ) {
/ *
* When user try to zoom in /out using ctrl + +/ - or mouse wheel
* handle this and prevent the default behaviours
*
* Code credit to PDF . js
* /
var _ = this ;
// Firefox specific event, so that we can prevent browser from zooming
$ ( window ) . on ( 'DOMMouseScroll' , function ( e ) {
if ( e . ctrlKey ) {
e . preventDefault ( ) ;
_ . rescale ( Math . pow ( _ . scale _step , e . detail ) , true ) ;
}
} ) ;
$ ( window ) . on ( 'keydown' , function keydown ( e ) {
if ( e . ctrlKey || e . metaKey ) {
switch ( e . keyCode ) {
case 61 : // FF/Mac '='
case 107 : // FF '+' and '='
case 187 : // Chrome '+'
_ . rescale ( 1.0 / _ . scale _step , true ) ;
break ;
case 173 : // FF/Mac '-'
case 109 : // FF '-'
case 189 : // Chrome '-'
_ . rescale ( _ . scale _step , true ) ;
break ;
case 48 : // '0'
_ . rescale ( 0 , false ) ;
break ;
default :
return ;
}
2012-09-24 12:20:34 +00:00
e . preventDefault ( ) ;
2012-09-22 16:17:30 +00:00
}
2012-09-23 09:26:12 +00:00
} ) ;
} ,
2013-07-16 15:42:02 +00:00
rescale : function ( ratio , is _relative , offsetX , offsetY ) {
if ( ! offsetX )
offsetX = 0 ;
if ( ! offsetY )
offsetY = 0 ;
2013-07-16 18:19:25 +00:00
2013-07-16 15:42:02 +00:00
// Save offset of the active page
var active _page = this . get _active _page ( ) ;
var prev _offset = active _page . $p . offset ( ) ;
var old _scale = this . scale ;
2013-07-16 18:19:25 +00:00
var prerendering _enabled = false ;
2013-08-13 09:33:06 +00:00
if ( SMOOTH _ZOOM _THRESHOLD > 0 ) {
2013-07-16 18:19:25 +00:00
// Immediate rendering optimizations enabled to improve reactiveness while zooming
// Find out which pages are visible
var min _visible , max _visible ;
min _visible = max _visible = active _page . n ;
while ( min _visible > 0 && this . pages [ min _visible ] . is _visible ( ) ) { min _visible -- }
while ( max _visible < this . pages . length && this . pages [ max _visible ] . is _visible ( ) ) { max _visible ++ }
// If less then the threshold, enable prerendering on selected pages
2013-08-13 09:33:06 +00:00
if ( max _visible - min _visible - 2 < SMOOTH _ZOOM _THRESHOLD )
2013-07-16 18:19:25 +00:00
prerendering _enabled = true ;
}
2013-07-16 15:42:02 +00:00
// Set new scale
if ( is _relative )
this . scale *= ratio ;
else
this . scale = ratio ;
// Rescale pages
2012-09-23 09:26:12 +00:00
var pl = this . pages ;
2012-09-25 11:29:59 +00:00
for ( var i in pl ) {
2013-07-17 07:47:13 +00:00
if ( prerendering _enabled && i > min _visible && i < max _visible )
pl [ i ] . rescale ( this . scale , true ) ; // Force immediate refresh
else
pl [ i ] . rescale ( this . scale ) ; // Delayed refresh
2012-09-23 05:04:29 +00:00
}
2012-09-22 16:17:30 +00:00
2013-07-16 15:42:02 +00:00
// Correct container scroll to keep view aligned while zooming
var correction _top = active _page . $p . offset ( ) . top - prev _offset . top ;
2013-07-16 18:19:25 +00:00
this . $container . scrollTop ( this . $container . scrollTop ( ) + correction _top + offsetY ) ;
2013-07-16 15:42:02 +00:00
// Take the center of the view as a reference
var prev _center _x = this . $container . width ( ) / 2 - prev _offset . left ;
// Calculate the difference respect the center of the view after the zooming
var correction _left = prev _center _x * ( this . scale / old _scale - 1 ) + active _page . $p . offset ( ) . left - prev _offset . left ;
// Scroll the container accordingly to keep alignment to the initial reference
2013-07-16 18:19:25 +00:00
this . $container . scrollLeft ( this . $container . scrollLeft ( ) + correction _left + offsetX ) ;
2013-07-16 15:42:02 +00:00
2013-07-16 18:19:25 +00:00
// Delayed rendering for pages not already shown
2012-09-23 09:26:12 +00:00
this . schedule _render ( ) ;
} ,
2012-09-22 16:17:30 +00:00
2013-07-16 15:42:02 +00:00
fit _width : function ( ) {
2013-07-16 18:19:25 +00:00
var active _page = this . get _active _page ( ) ;
2013-07-16 15:42:02 +00:00
2013-07-16 18:19:25 +00:00
this . rescale ( this . $container . width ( ) / active _page . w , false ) ;
this . scroll _to ( active _page . n , [ 0 , 0 ] ) ;
2013-07-16 15:42:02 +00:00
} ,
fit _height : function ( ) {
var active _page = this . get _active _page ( ) ;
2013-07-16 18:19:25 +00:00
this . rescale ( this . $container . height ( ) / active _page . h , false ) ;
2013-07-16 15:42:02 +00:00
this . scroll _to ( active _page . n , [ 0 , 0 ] ) ;
} ,
get _active _page : function ( ) {
// get page that are on the center of the view //TODO better on top?!
2013-07-16 18:19:25 +00:00
var y _center = $ ( this . $container ) . offset ( ) . top + this . $container . height ( ) / 2 ;
2013-07-16 15:42:02 +00:00
for ( var i = 2 ; i < this . pages . length ; i ++ ) {
if ( this . pages [ i ] . $p . offset ( ) . top > y _center )
return this . pages [ i - 1 ] ;
}
return this . pages [ i - 1 ] ; // Last page
} ,
2012-09-25 11:29:59 +00:00
get _containing _page : function ( obj ) {
/* get the page obj containing obj */
2013-02-27 18:11:34 +00:00
var p = obj . closest ( '.' + CSS _CLASS _NAMES [ 'page_frame' ] ) [ 0 ] ;
2013-01-28 16:38:07 +00:00
return p && this . pages [ ( new Page ( p ) ) . n ] ;
2012-09-25 11:29:59 +00:00
} ,
2013-01-28 13:01:02 +00:00
link _handler : function ( e ) {
2012-09-25 11:29:59 +00:00
var _ = e . data ;
var t = $ ( e . currentTarget ) ;
2012-09-25 13:56:48 +00:00
2013-01-28 15:58:00 +00:00
var cur _pos = [ 0 , 0 ] ;
// cur_page might be undefined, e.g. from Outline
var cur _page = _ . get _containing _page ( t ) ;
if ( cur _page != undefined )
{
cur _pos = cur _page . position ( ) ;
//get the coordinates in default user system
2013-07-16 18:19:25 +00:00
cur _pos = transform ( cur _page . ictm , [ cur _pos [ 0 ] , cur _page . h - cur _pos [ 1 ] ] ) ;
2013-01-28 15:58:00 +00:00
}
2012-09-25 11:29:59 +00:00
var detail _str = t . attr ( 'data-dest-detail' ) ;
if ( detail _str == undefined ) return ;
var ok = false ;
2012-09-26 08:00:55 +00:00
var detail = JSON . parse ( detail _str ) ;
2012-09-25 11:29:59 +00:00
2012-09-26 08:00:55 +00:00
var target _page = _ . pages [ detail [ 0 ] ] ;
if ( target _page == undefined ) return ;
2012-09-25 13:56:48 +00:00
2012-09-26 08:00:55 +00:00
var pos = [ 0 , 0 ] ;
var upside _down = true ;
// TODO: zoom
// TODO: BBox
switch ( detail [ 1 ] ) {
case 'XYZ' :
pos = [ ( detail [ 2 ] == null ) ? cur _pos [ 0 ] : detail [ 2 ]
, ( detail [ 3 ] == null ) ? cur _pos [ 1 ] : detail [ 3 ] ] ;
ok = true ;
break ;
case 'Fit' :
case 'FitB' :
pos = [ 0 , 0 ] ;
ok = true ;
break ;
case 'FitH' :
case 'FitBH' :
2013-07-16 18:19:25 +00:00
pos = [ 0 , ( detail [ 2 ] == null ) ? cur _pos [ 1 ] : detail [ 2 ] ] ;
2012-09-26 08:00:55 +00:00
ok = true ;
break ;
case 'FitV' :
case 'FitBV' :
pos = [ ( detail [ 2 ] == null ) ? cur _pos [ 0 ] : detail [ 2 ] , 0 ] ;
ok = true ;
break ;
case 'FitR' :
/* locate the top-left corner of the rectangle */
pos = [ detail [ 2 ] , detail [ 5 ] ] ;
upside _down = false ;
ok = true ;
break ;
2012-09-25 11:29:59 +00:00
default :
2012-09-26 08:00:55 +00:00
ok = false ;
2012-09-25 11:29:59 +00:00
break ;
}
2012-09-26 08:00:55 +00:00
if ( ok ) {
2013-06-13 10:39:52 +00:00
var transform _and _scroll = function ( ) {
2013-06-12 15:53:14 +00:00
pos = transform ( target _page . ctm , pos ) ;
2013-06-13 10:39:52 +00:00
if ( upside _down ) {
2013-07-16 18:19:25 +00:00
pos [ 1 ] = target _page . h - pos [ 1 ] ;
2013-06-12 15:53:14 +00:00
}
_ . scroll _to ( detail [ 0 ] , pos ) ;
2013-07-16 18:19:25 +00:00
} ;
2013-06-13 10:39:52 +00:00
if ( target _page . loaded ) {
transform _and _scroll ( ) ;
2013-06-12 15:53:14 +00:00
} else {
// Scroll to the exact position once loaded.
2013-06-13 10:39:52 +00:00
_ . load _page ( target _page . n , 1 , function ( ) {
target _page = _ . pages [ target _page . n ] ; // Refresh reference
transform _and _scroll ( ) ;
2013-06-12 15:53:14 +00:00
} ) ;
// In the meantime page gets loaded, scroll approximately position for maximum responsiveness.
_ . scroll _to ( detail [ 0 ] , [ 0 , 0 ] ) ;
2012-09-26 08:00:55 +00:00
}
2012-09-25 11:29:59 +00:00
e . preventDefault ( ) ;
2012-09-26 08:00:55 +00:00
}
2012-09-25 14:24:36 +00:00
} ,
2012-09-26 08:00:55 +00:00
/* pos=[x,y], where (0,0) is the top-left corner */
2012-09-25 14:24:36 +00:00
scroll _to : function ( pageno , pos ) {
var target _page = this . pages [ pageno ] ;
if ( target _page == undefined ) return ;
var cur _target _pos = target _page . position ( ) ;
2013-06-13 15:00:42 +00:00
this . $container . scrollLeft ( this . $container . scrollLeft ( ) - cur _target _pos [ 0 ] + pos [ 0 ] ) ;
this . $container . scrollTop ( this . $container . scrollTop ( ) - cur _target _pos [ 1 ] + pos [ 1 ] ) ;
2012-09-25 14:24:36 +00:00
} ,
_ _last _member _ _ : 'no comma' /*,*/
2012-09-25 14:40:21 +00:00
} ) ;
return pdf2htmlEX ;
2012-09-23 09:26:12 +00:00
} ) ( ) ;