1
0
mirror of https://github.com/pdf2htmlEX/pdf2htmlEX.git synced 2024-07-08 19:00:33 +00:00
pdf2htmlEX/share/pdf2htmlEX.js.in

625 lines
19 KiB
JavaScript
Raw Normal View History

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';
2013-09-30 07:50:15 +00:00
/* The namespace */
2012-09-23 09:26:12 +00:00
var pdf2htmlEX = (function(){
2013-10-05 08:11:03 +00:00
var pdf2htmlEX = new Object();
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@',
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-09-30 07:50:15 +00:00
2013-10-05 08:11:03 +00:00
var DEFAULT_CONFIG = {
// id of the element to put the pages in
2013-10-05 08:20:28 +00:00
container_id : 'page-container',
2013-10-05 08:11:03 +00:00
// id of the element for sidebar (to open and close)
2013-10-05 08:20:28 +00:00
sidebar_id : 'sidebar',
2013-10-05 08:11:03 +00:00
// id of the element for outline
2013-10-05 08:20:28 +00:00
outline_id : 'outline',
2013-10-05 08:11:03 +00:00
// class for the loading indicator
loading_indicator_cls : 'loading_indicator_cls',
// How many page shall we preload that are below the last visible page
preload_pages : 3,
// Smooth zoom is enabled when the number of pages shown is less than the threshold
// Otherwise page content is hidden and redrawn after a delay (function schedule_render).
// 0: disable smooth zoom optimizations (less CPU usage but flickering on zoom)
smooth_zoom_threshold : 4,
// how many ms should we wait before actually rendering the pages and after a scroll event
render_timeout : 100,
// zoom ratio step for each zoom in/out event
scale_step : 0.9,
2013-09-30 07:50:15 +00:00
2013-10-05 08:11:03 +00:00
__dummy__ : 'no comma'
};
2012-09-25 16:27:58 +00:00
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]];
};
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-09-30 07:50:15 +00:00
// page size
// Need to make rescale work when page_content_box is not loaded, yet
this.h = this.$p.height();
2013-06-13 15:00:42 +00:00
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
*/
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(){
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
}
},
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
this.$d.height(this.h * this.set_r);
this.$d.width(this.w * this.set_r);
2012-09-25 16:27:58 +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();
return !((off[1] > this.h) || (off[1] + this.$container.height() < 0));
2012-09-25 16:27:58 +00:00
},
/* return if this page or any neighbor of it is visible */
is_nearly_visible : function() {
var off = this.position();
/* I should use the height of the previous page or the next page here
* but since they are not easily available, just use '*2', which should be a good estimate in most cases
*/
return !((off[1] > this.h * 2) || (off[1] + this.$container.height() * 2 < 0));
},
2012-09-25 16:27:58 +00:00
/* return the coordinate of the top-left corner of container
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
pdf2htmlEX.Viewer = function(config) {
2013-10-05 08:11:03 +00:00
this.config = $.extend({}, DEFAULT_CONFIG, config);
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, {
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-10-05 08:11:03 +00:00
this.$sidebar = $('#'+this.config['sidebar_id']);
this.$outline = $('#'+this.config['outline_id']);
this.$container = $('#'+this.config['container_id']);
this.$loading_indicator = $('.'+this.config['loading_indicator_cls']);
2012-09-23 05:04:29 +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
this.find_pages();
2012-09-23 05:04:29 +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-10-06 11:53:37 +00:00
//this.register_key_handler();
// 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-07-16 15:42:02 +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-09-30 07:50:15 +00:00
/* don't use for(..in..) since $pl is more than an Array */
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);
new_pages[p.n] = p;
}
this.pages = new_pages;
},
2013-06-13 15:00:42 +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
if (this.pages_loading[idx])
2013-06-12 15:53:14 +00:00
return; // Page is already loading
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
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) {
this.pages_loading[idx] = true; // Set semaphore
2013-06-12 15:53:14 +00:00
$.ajax({
2013-06-12 15:53:14 +00:00
url: url,
dataType: 'text'
}).done(function(data){
2013-10-06 11:53:37 +00:00
_.pages[idx].$d.replaceWith(data);
2013-06-12 15:53:14 +00:00
2013-10-06 11:53:37 +00:00
var $new_pf = _.$container.find('#' + CSS_CLASS_NAMES['page_frame'] + page_no_hex);
_.pages[idx] = new Page($new_pf, _.$container);
_.pages[idx].hide();
_.pages[idx].rescale(_.scale);
_.schedule_render();
2013-06-12 15:53:14 +00:00
2013-10-06 11:53:37 +00:00
// disable background image dragging
$new_pf.find('.'+CSS_CLASS_NAMES['background_image']).on('dragstart', function(e){return false;});
2013-06-12 15:53:14 +00:00
2013-10-06 11:53:37 +00:00
// Reset loading token
delete _.pages_loading[idx];
2013-06-12 15:53:14 +00:00
2013-10-06 11:53:37 +00:00
if (successCallback) successCallback();
}
).fail(function(jqXHR, textStatus, errorThrown){
console.error('error loading page ' + idx + ': ' + textStatus);
// Reset loading token
delete _.pages_loading[idx];
if (errorCallback) errorCallback();
});
}
2013-06-12 15:53:14 +00:00
// Concurrent prefetch of the next pages
if (pages_to_preload === undefined)
2013-10-05 08:11:03 +00:00
pages_to_preload = this.config['preload_pages'];
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];
if(p.is_nearly_visible()){
2013-06-12 15:53:14 +00:00
if (p.loaded) {
p.show();
} else
this.load_page(p.n);
} else {
2012-09-25 11:29:59 +00:00
p.hide();
}
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.config['render_timeout']);
2012-09-23 09:26:12 +00:00
},
2013-10-06 11:53:37 +00:00
/*
* Handling key events, zooming, scrolling etc.
*/
register_key_handler: function () {
2012-09-23 09:26:12 +00:00
/*
* 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(_.config['scale_step'], e.detail), true);
2012-09-23 09:26:12 +00:00
}
});
$(window).on('keydown', function keydown(e) {
2013-10-06 11:53:37 +00:00
var handled = false;
var cmd = (evt.ctrlKey ? 1 : 0) |
(evt.altKey ? 2 : 0) |
(evt.shiftKey ? 4 : 0) |
(evt.metaKey ? 8 : 0);
var with_ctrl = (cmd == 9);
var with_alt = (cmd == 2);
switch (e.keyCode) {
case 61: // FF/Mac '='
case 107: // FF '+' and '='
case 187: // Chrome '+'
if(with_ctrl){
_.rescale(1.0 / _.config['scale_step'], true);
2013-10-06 11:53:37 +00:00
handled = true;
}
break;
case 173: // FF/Mac '-'
case 109: // FF '-'
case 189: // Chrome '-'
if(with_ctrl){
_.rescale(_.config['scale_step'], true);
2013-10-06 11:53:37 +00:00
handled = true;
}
break;
case 48: // '0'
if(with_ctrl){
2012-09-23 09:26:12 +00:00
_.rescale(0, false);
2013-10-06 11:53:37 +00:00
handled = true;
}
break;
case 33: // Page UP:
if (with_alt) { // alt-pageup -> scroll one page up
_.scroll_to(_.get_prev_page());
} else { // pageup -> scroll one screen up
_.$container.scrollTop(_.$container.scrollTop()-_.$container.height());
}
handled = true;
break;
case 34: // Page DOWN
if (with_alt) { // alt-pagedown -> scroll one page down
_.scroll_to(_.get_next_page());
} else { // pagedown -> scroll one screen down
_.$container.scrollTop(_.$container.scrollTop()+_.$container.height());
}
handled = true;
break;
case 35: // End
if (with_ctrl) {
_.$container.scrollTop(_.$container[0].scrollHeight);
handled = true;
}
break;
case 36: // Home
if (e.with_ctrl) {
_.$container.scrollTop(0);
handled = true;
}
break;
2012-09-22 16:17:30 +00:00
}
2013-10-06 11:53:37 +00:00
if(handled) {
2012-09-24 12:20:34 +00:00
e.preventDefault();
return;
2012-09-22 16:17:30 +00:00
}
2013-10-06 11:57:44 +00:00
});
},
// Find the first page that is at least half a page below the current position
get_next_page : function() {
2013-10-06 11:53:37 +00:00
var page_height = this.$container.height();
var pl = this.pages;
for(var i in pl) {
var page = pl[i];
var page_position = page.position();
if (page_position[1] < position[1] - page_height/2)
return page;
}
return undefined;
},
// Find the last page that is at least half a page above the current position
get_prev_page : function() {
2013-10-06 11:53:37 +00:00
var page_height = this.$container.height();
var pl = this.pages.slice().reverse();
for(var i in pl) {
var page = pl[i];
var page_position = page.position();
if (page_position[1] > position[1] + page_height/2)
return page;
}
return undefined;
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 15:42:02 +00:00
// Save offset of the active page
var active_page = this.get_active_page();
2013-09-30 07:50:15 +00:00
if(!active_page) return;
2013-07-16 15:42:02 +00:00
var prev_offset = active_page.$p.offset();
var old_scale = this.scale;
2013-09-30 07:50:15 +00:00
var pl = this.pages;
2013-07-16 15:42:02 +00:00
var prerendering_enabled = false;
2013-10-05 08:11:03 +00:00
if (this.config['smooth_zoom_threshold'] > 0) {
// 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;
2013-09-30 07:50:15 +00:00
while (pl[min_visible] && pl[min_visible].is_visible()) { --min_visible; }
++ min_visible;
while (pl[max_visible] && pl[max_visible].is_visible()) { ++max_visible; }
-- max_visible;
// If less then the threshold, enable prerendering on selected pages
2013-10-05 08:11:03 +00:00
if (max_visible - min_visible + 1 < this.config['smooth_zoom_threshold'])
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-25 11:29:59 +00:00
for(var i in pl) {
2013-09-30 07:50:15 +00:00
if (prerendering_enabled && i >= min_visible && i <= max_visible)
2013-07-17 07:47:13 +00:00
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;
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
this.$container.scrollLeft( this.$container.scrollLeft() + correction_left + offsetX );
2013-07-16 15:42:02 +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 () {
var active_page = this.get_active_page();
2013-09-30 07:50:15 +00:00
if(!active_page) return;
2013-07-16 15:42:02 +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-09-30 07:50:15 +00:00
if(!active_page) return;
2013-07-16 15:42:02 +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 () {
2013-10-06 11:53:37 +00:00
// get page that are on the center of the view //TODO better on top?!
var y_center = this.$container.offset().top + this.$container.height() / 2;
var pl = this.pages;
var last_page = -1;
for (var i in pl) {
if (pl[i].$p.offset().top > y_center)
break;
last_page = i;
}
return pl[last_page];
2013-07-16 15:42:02 +00:00
},
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];
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);
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
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-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]
2013-10-06 11:53:37 +00:00
,(detail[3] == null) ? cur_pos[1] : detail[3]];
2012-09-26 08:00:55 +00:00
ok = true;
break;
case 'Fit':
case 'FitB':
pos = [0,0];
ok = true;
break;
case 'FitH':
case 'FitBH':
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) {
var transform_and_scroll = function() {
2013-06-12 15:53:14 +00:00
pos = transform(target_page.ctm, pos);
if(upside_down) {
pos[1] = target_page.h - pos[1];
2013-06-12 15:53:14 +00:00
}
_.scroll_to(detail[0], pos);
};
if (target_page.loaded) {
transform_and_scroll();
2013-06-12 15:53:14 +00:00
} else {
// Scroll to the exact position once loaded.
_.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;
2013-10-06 11:53:37 +00:00
if(pos == undefined)
pos = [0,0];
2012-09-25 14:24:36 +00:00
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
})();