project files added
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 loicminghetti
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
# TouchPDF
|
||||
TouchPDF is a simple web PDF viewer for jQuery. It is based on the pdf.js library and support mobile gestures for swiping pages and zooming.
|
||||
|
||||
## Features
|
||||
- Use finger to swipe to next or previous page
|
||||
- Pinch to zoom in and out
|
||||
- Follow links to document sections or external URLs
|
||||
- Add colorful tabs for quick access to bookmarked pages
|
||||
- Loads directly in your DOM, without iFrame
|
||||
|
||||
## Supported browsers
|
||||
Firefox, Chrome, Opera, IE >= 9, Safari, Android Browser
|
||||
|
||||
## Demo
|
||||
Check out the online demo at: http://touchpdf.net/demo/index.htm
|
||||
|
||||
## Getting started
|
||||
|
||||
###Get the jQuery plugin
|
||||
To get a local copy of the plugin, clone it using git:
|
||||
````bash
|
||||
$ git clone git:// github.com/loicminghetti/touchpdf.git touchpdf
|
||||
$ cd touchpdf
|
||||
````
|
||||
Note: you need to start a local web server as some browsers don't allow opening PDF files for a file:// url.
|
||||
|
||||
###Usage
|
||||
Add the following to your document's `<head>`
|
||||
````html
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
<script type="text/javascript" src="jquery.min.js"></script>
|
||||
<script type="text/javascript" src="pdf.compatibility.js"></script>
|
||||
<script type="text/javascript" src="pdf.js"></script>
|
||||
<script type="text/javascript" src="jquery.touchSwipe.js"></script>
|
||||
<script type="text/javascript" src="jquery.panzoom.js"></script>
|
||||
<script type="text/javascript" src="jquery.mousewheel.js"></script>
|
||||
<script type="text/javascript" src="jquery.touchPDF.js"></script>
|
||||
<link href="jquery.touchPDF.css" rel="stylesheet" media="screen" />
|
||||
````
|
||||
|
||||
Add an empty div in your document that will contain the PDF viewer
|
||||
````html
|
||||
<div id="myPDF"></div>
|
||||
````
|
||||
|
||||
Load a PDF file by adding the following script at the end of your document
|
||||
````html
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$("#myPDF").pdf( { source: "yourfile.pdf" } );
|
||||
});
|
||||
</script>
|
||||
````
|
||||
|
||||
You ca also add bookmarks tabs to your PDF display:
|
||||
````javascript
|
||||
$(function() {
|
||||
$("#myPDF").pdf( {
|
||||
source: "demo.pdf",
|
||||
tabs: [
|
||||
{title: "Tab 1", page: 2, color: "orange"},
|
||||
{title: "Tab 2", page: 3, color: "green"},
|
||||
{title: "Tab 3", page: 5, color: "blue"},
|
||||
]
|
||||
});
|
||||
});
|
||||
````
|
||||
|
||||
###Viewer options
|
||||
|
||||
Option | Type | Default | Description
|
||||
------ | ---- | ------- | ----------------------
|
||||
source | *string* | " " | Path of PDF file to display.
|
||||
title | *string* | "TouchPDF" | Title of the PDF to be displayed in the toolbar.
|
||||
tabs | *array* | [ ] | Array of tabs to display on the side. See below for syntax.
|
||||
tabsColor | *string* | "beige" | Default background color for all tabs. Available colors are "green", "yellow", "orange", "brown", "blue", "white", "black" and you can define your own colors with CSS.
|
||||
disableZoom | *boolean* | false | Disable zooming of PDF document. By default, PDF can be zoomed using scroll, two fingers pinch, +/- keys, and toolbar buttons.
|
||||
disableSwipe | *boolean* | false | Disable swipe to next/prev page of PDF document. By default, PDF can be swiped using one finger.
|
||||
disableLinks | *boolean* | false | Disable all internal and external links on PDF document..
|
||||
disableKeys | *boolean* | false | Disable the arrow keys for next/previous page and +/- for zooming (if zooming is enabled).
|
||||
redrawOnWindowResize | *boolean* | true | Force resize of PDF viewer on window resize.
|
||||
pdfScale | *float* | 1 | Defines the ratio between your PDF page size and the tabs size.
|
||||
quality | *float* | 2 | Set quality ratio for loaded PDF pages. Set at 2 for sharp display when user zooms up to 200%.
|
||||
showToolbar | *boolean* | true | Show a toolbar on top of the document with title, page number and buttons for next/prev pages and zooming.
|
||||
loaded | *function* | null | A handler triggered when PDF document is loaded (before display of first page).
|
||||
changed | *function* | null | A handler triggered each time a new page is displayed.
|
||||
loadingHTML | *string* | "Loading PDF" | Text or HTML displayed on white page shown before document is loaded.
|
||||
loadingHeight | *int* | 841 | Height in px of white page shown before document is loaded (default is A4 height).
|
||||
loadingWidth | *int* | 595 | Width in px of white page shown before document is loaded (default is A4 width).
|
||||
|
||||
###Tab attributes
|
||||
|
||||
Each tab must be defined using a json object with the following attributes:
|
||||
|
||||
Attribute | Type | Default | Description
|
||||
--------- | ---- | ------- | ----------------------
|
||||
title | *string* | *Mandatory* | Text to display on the tab. Text of less than 3 characters will be displayed horizontaly, longer text will be displayed verticaly.
|
||||
page | *int* | *Mandatory* | PDF document page number to link to. Page numbering starts at 1.
|
||||
color | *string* | As defined in viewer | Set a different color to the tab. See above for available colors.
|
||||
offset | *int* | 0 | Pill up tabs with a small offset so that the user knows there are hidden tabs behind. Starts at 0.
|
||||
top | *int* | undefined | Align tab from the top of the PDF document, by a given number of pixels. By default, tabs are positioned one after the other.
|
||||
bottom | *int* | undefined | Align tab from the bottom of the PDF document, by a given number of pixels.
|
||||
height | *int* | undefined | Set a specific height to the tab. By default, tab height will depend on the number of characters in the title.
|
||||
|
||||
## Credit
|
||||
|
||||
This plugin heavily relies on the following great open source work:
|
||||
|
||||
- PDF.js by Mozilla https://mozilla.github.io/pdf.js/
|
||||
- PanZoom jQuery plugin by Timmy Willison https://github.com/timmywil/jquery.panzoom
|
||||
- TouchSwipe jQuery plugin by Matt Bryson https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
|
||||
|
||||
## Getting help
|
||||
|
||||
If you need help you can contact me
|
||||
|
||||
**Enjoy and feel free to contribute!**
|
||||
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
<meta charset="UTF-8">
|
||||
<title>TouchPDF</title>
|
||||
<link href="../jquery.touchPDF.css" rel="stylesheet" media="screen" />
|
||||
<style>
|
||||
body , html{
|
||||
background-color: #404040;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="myPDF" style="height: 95%; width: 95%; margin: auto;"></div>
|
||||
|
||||
|
||||
<script type="text/javascript" src="../pdf.compatibility.js"></script>
|
||||
<script type="text/javascript" src="../pdf.js"></script>
|
||||
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="../jquery.touchSwipe.js"></script>
|
||||
<script type="text/javascript" src="../jquery.touchPDF.js"></script>
|
||||
<script type="text/javascript" src="../jquery.panzoom.js"></script>
|
||||
<script type="text/javascript" src="../jquery.mousewheel.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
$(function() {
|
||||
$("#myPDF").pdf( {
|
||||
source: "demo.pdf",
|
||||
tabs: [
|
||||
{title: "Section 1", page: 2, color: "orange"},
|
||||
{title: "Section 2", page: 3, color: "green"},
|
||||
{title: "Section 3", page: 5, color: "blue"},
|
||||
]
|
||||
} );
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,201 @@
|
||||
/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
|
||||
* Licensed under the MIT License (LICENSE.txt).
|
||||
*
|
||||
* Version: 3.1.9
|
||||
*
|
||||
* Requires: jQuery 1.2.2+
|
||||
*/
|
||||
|
||||
(function (factory) {
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS style for Browserify
|
||||
module.exports = factory;
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
|
||||
var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
|
||||
toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
|
||||
['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
|
||||
slice = Array.prototype.slice,
|
||||
nullLowestDeltaTimeout, lowestDelta;
|
||||
|
||||
if ( $.event.fixHooks ) {
|
||||
for ( var i = toFix.length; i; ) {
|
||||
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
|
||||
}
|
||||
}
|
||||
|
||||
var special = $.event.special.mousewheel = {
|
||||
version: '3.1.9',
|
||||
|
||||
setup: function() {
|
||||
if ( this.addEventListener ) {
|
||||
for ( var i = toBind.length; i; ) {
|
||||
this.addEventListener( toBind[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = handler;
|
||||
}
|
||||
// Store the line height and page height for this particular element
|
||||
$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
|
||||
$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
if ( this.removeEventListener ) {
|
||||
for ( var i = toBind.length; i; ) {
|
||||
this.removeEventListener( toBind[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = null;
|
||||
}
|
||||
},
|
||||
|
||||
getLineHeight: function(elem) {
|
||||
return parseInt($(elem)['offsetParent' in $.fn ? 'offsetParent' : 'parent']().css('fontSize'), 10);
|
||||
},
|
||||
|
||||
getPageHeight: function(elem) {
|
||||
return $(elem).height();
|
||||
},
|
||||
|
||||
settings: {
|
||||
adjustOldDeltas: true
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.extend({
|
||||
mousewheel: function(fn) {
|
||||
return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
|
||||
},
|
||||
|
||||
unmousewheel: function(fn) {
|
||||
return this.unbind('mousewheel', fn);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function handler(event) {
|
||||
var orgEvent = event || window.event,
|
||||
args = slice.call(arguments, 1),
|
||||
delta = 0,
|
||||
deltaX = 0,
|
||||
deltaY = 0,
|
||||
absDelta = 0;
|
||||
event = $.event.fix(orgEvent);
|
||||
event.type = 'mousewheel';
|
||||
|
||||
// Old school scrollwheel delta
|
||||
if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
|
||||
if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
|
||||
if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
|
||||
if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
|
||||
|
||||
// Firefox < 17 horizontal scrolling related to DOMMouseScroll event
|
||||
if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
|
||||
deltaX = deltaY * -1;
|
||||
deltaY = 0;
|
||||
}
|
||||
|
||||
// Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
|
||||
delta = deltaY === 0 ? deltaX : deltaY;
|
||||
|
||||
// New school wheel delta (wheel event)
|
||||
if ( 'deltaY' in orgEvent ) {
|
||||
deltaY = orgEvent.deltaY * -1;
|
||||
delta = deltaY;
|
||||
}
|
||||
if ( 'deltaX' in orgEvent ) {
|
||||
deltaX = orgEvent.deltaX;
|
||||
if ( deltaY === 0 ) { delta = deltaX * -1; }
|
||||
}
|
||||
|
||||
// No change actually happened, no reason to go any further
|
||||
if ( deltaY === 0 && deltaX === 0 ) { return; }
|
||||
|
||||
// Need to convert lines and pages to pixels if we aren't already in pixels
|
||||
// There are three delta modes:
|
||||
// * deltaMode 0 is by pixels, nothing to do
|
||||
// * deltaMode 1 is by lines
|
||||
// * deltaMode 2 is by pages
|
||||
if ( orgEvent.deltaMode === 1 ) {
|
||||
var lineHeight = $.data(this, 'mousewheel-line-height');
|
||||
delta *= lineHeight;
|
||||
deltaY *= lineHeight;
|
||||
deltaX *= lineHeight;
|
||||
} else if ( orgEvent.deltaMode === 2 ) {
|
||||
var pageHeight = $.data(this, 'mousewheel-page-height');
|
||||
delta *= pageHeight;
|
||||
deltaY *= pageHeight;
|
||||
deltaX *= pageHeight;
|
||||
}
|
||||
|
||||
// Store lowest absolute delta to normalize the delta values
|
||||
absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
|
||||
|
||||
if ( !lowestDelta || absDelta < lowestDelta ) {
|
||||
lowestDelta = absDelta;
|
||||
|
||||
// Adjust older deltas if necessary
|
||||
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
|
||||
lowestDelta /= 40;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust older deltas if necessary
|
||||
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
|
||||
// Divide all the things by 40!
|
||||
delta /= 40;
|
||||
deltaX /= 40;
|
||||
deltaY /= 40;
|
||||
}
|
||||
|
||||
// Get a whole, normalized value for the deltas
|
||||
delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
|
||||
deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
|
||||
deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
|
||||
|
||||
// Add information to the event object
|
||||
event.deltaX = deltaX;
|
||||
event.deltaY = deltaY;
|
||||
event.deltaFactor = lowestDelta;
|
||||
// Go ahead and set deltaMode to 0 since we converted to pixels
|
||||
// Although this is a little odd since we overwrite the deltaX/Y
|
||||
// properties with normalized deltas.
|
||||
event.deltaMode = 0;
|
||||
|
||||
// Add event and delta to the front of the arguments
|
||||
args.unshift(event, delta, deltaX, deltaY);
|
||||
|
||||
// Clearout lowestDelta after sometime to better
|
||||
// handle multiple device types that give different
|
||||
// a different lowestDelta
|
||||
// Ex: trackpad = 3 and mouse wheel = 120
|
||||
if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
|
||||
nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
|
||||
|
||||
return ($.event.dispatch || $.event.handle).apply(this, args);
|
||||
}
|
||||
|
||||
function nullLowestDelta() {
|
||||
lowestDelta = null;
|
||||
}
|
||||
|
||||
function shouldAdjustOldDeltas(orgEvent, absDelta) {
|
||||
// If this is an older event and the delta is divisable by 120,
|
||||
// then we are assuming that the browser is treating this as an
|
||||
// older mouse wheel event and that we should divide the deltas
|
||||
// by 40 to try and get a more usable deltaFactor.
|
||||
// Side note, this actually impacts the reported scroll distance
|
||||
// in older browsers and can cause scrolling to be slower than native.
|
||||
// Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
|
||||
return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
|
||||
}
|
||||
|
||||
}));
|
||||
+1242
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,209 @@
|
||||
.touchPDF {
|
||||
overflow: hidden;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
font-family: arial, verdana, sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.touchPDF,
|
||||
.touchPDF *,
|
||||
.touchPDF *:before,
|
||||
.touchPDF *:after {
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
|
||||
.touchPDF > .pdf-outerdiv {
|
||||
position: relative;
|
||||
-webkit-transform-origin: 0 0 0;
|
||||
-ms-transform-origin: 0 0 0;
|
||||
transform-origin: 0 0 0;
|
||||
}
|
||||
|
||||
.touchPDF > .pdf-outerdiv > div {
|
||||
position: absolute;
|
||||
top : 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-toolbar {
|
||||
height: 0;
|
||||
color: white;
|
||||
padding: 5px 0;
|
||||
text-align: right;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-toolbar > .pdf-title {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-toolbar > .pdf-button {
|
||||
display: inline-block;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-toolbar > .pdf-button > .pdf-page-count {
|
||||
display: inline-block;
|
||||
min-width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer {
|
||||
border: 0px solid #404040;
|
||||
box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.4);
|
||||
z-index: 2000;
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer > .pdf-drag {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer > .pdf-drag canvas {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer > .pdf-drag .pdf-annotations {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2500;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer > .pdf-loading {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
z-index: 3000;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
color: #CCCCCC;
|
||||
}
|
||||
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer > .pdf-drag .pdf-annotations > .annotLink > a {
|
||||
font-size: 1em;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer > .pdf-drag .pdf-annotations > .annotLink > a {
|
||||
background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAA LAAAAAABAAEAAAIBRAA7") repeat scroll 0 0 rgba(0, 0, 0, 0);
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-viewer > .pdf-drag .pdf-annotations > .annotLink > a:hover {
|
||||
background: none repeat scroll 0 0 #ff0;
|
||||
box-shadow: 0 2px 10px #ff0;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 0px 2px 1px rgba(0, 0, 0, 0.5);
|
||||
border-style: solid;
|
||||
border-color: #404040;
|
||||
border-width: 1px 0 1px 1px;
|
||||
border-radius: 12px 0 0 12px;
|
||||
background-color: #FAE5A7;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.right {
|
||||
border-radius: 0 12px 12px 0;
|
||||
border-width: 1px 1px 1px 0;
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab, .touchPDF > .pdf-outerdiv > .pdf-tabs > .tab:hover {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab span, .touchPDF > .pdf-outerdiv > .pdf-tabs > .tab:hover span {
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
left: 10px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
text-align: center;
|
||||
line-height: 12px;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.right span {
|
||||
top: 17px;
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.large {
|
||||
height: 140px;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.large span {
|
||||
top: auto;
|
||||
bottom: -20px;
|
||||
-webkit-transform-origin: 0 0 0;
|
||||
-ms-transform-origin: 0 0 0;
|
||||
transform-origin: 0 0 0;
|
||||
-webkit-transform:rotate(270deg);
|
||||
-ms-transform:rotate(270deg);
|
||||
transform: rotate(270deg);
|
||||
width: 140px;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.large.right span {
|
||||
-webkit-transform-origin: 100% 0 0;
|
||||
-ms-transform-origin: 100% 0 0;
|
||||
transform-origin: 100% 0 0;
|
||||
-webkit-transform:rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
|
||||
}
|
||||
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.beige {
|
||||
background-color: #FAE5A7;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.green {
|
||||
background-color: #79B550;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.blue {
|
||||
background-color: #2A9892;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.brown {
|
||||
background-color: #9C8852;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.yellow {
|
||||
background-color: #EBB600;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.orange {
|
||||
background-color: #EBA500;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.white {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.touchPDF > .pdf-outerdiv > .pdf-tabs > .tab.black {
|
||||
background-color: #000000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,774 @@
|
||||
/*
|
||||
* @fileOverview TouchPDF - jQuery Plugin
|
||||
* @version 0.4
|
||||
*
|
||||
* @author Loic Minghetti http://www.loicminghetti.net
|
||||
* @see https://github.com/loicminghetti/TouchPDF-Jquery-Plugin
|
||||
* @see http://plugins.jquery.com/project/touchPDF
|
||||
*
|
||||
* Copyright (c) 2014 Loic Minghetti
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* See (http://jquery.com/).
|
||||
* @name $
|
||||
* @class
|
||||
* See the jQuery Library (http://jquery.com/) for full details. This just
|
||||
* documents the function and classes that are added to jQuery by this plug-in.
|
||||
*/
|
||||
|
||||
/**
|
||||
* See (http://jquery.com/)
|
||||
* @name fn
|
||||
* @class
|
||||
* See the jQuery Library (http://jquery.com/) for full details. This just
|
||||
* documents the function and classes that are added to jQuery by this plug-in.
|
||||
* @memberOf $
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
//Constants
|
||||
var EMPTY = "empty",
|
||||
INIT = "init",
|
||||
LOADING = "loading",
|
||||
LOADED = "loaded",
|
||||
ZOOMEDIN = "zoomedin",
|
||||
DRAGGING = "dragging",
|
||||
RENDERING = "rendering",
|
||||
|
||||
PLUGIN_NS = 'TouchPDF',
|
||||
|
||||
TOOLBAR_HEIGHT = 30,
|
||||
BORDER_WIDTH = 1,
|
||||
TAB_SPACING = -2,
|
||||
TAB_WIDTH = 41,
|
||||
TAB_OFFSET_WIDTH = 10;
|
||||
|
||||
|
||||
/**
|
||||
* The default configuration, and available options to configure touchPDF with.
|
||||
* You can set the default values by updating any of the properties prior to instantiation.
|
||||
* @name $.fn.pdf.defaults
|
||||
* @namespace
|
||||
* @property {string} [source=""] Path of PDF file to display
|
||||
* @property {string} [title="TouchPDF"] Title of the PDF to be displayed in the toolbar
|
||||
* @property {array} [tabs=[]] Array of tabs to display on the side. See doc for syntax.
|
||||
* @property {string} [tabsColor="beige" Default background color for all tabs. Available colors are "green", "yellow", "orange", "brown", "blue", "white", "black" and you can define your own colors with CSS.
|
||||
* @property {boolean} [disableZoom=false] Disable zooming of PDF document. By default, PDF can be zoomed using scroll, two fingers pinch, +/- keys, and toolbar buttons
|
||||
* @property {boolean} [disableSwipe=false] Disable swipe to next/prev page of PDF document. By default, PDF can be swiped using one finger
|
||||
* @property {boolean} [disableLinks=false] Disable all internal and external links on PDF document
|
||||
* @property {boolean} [disableKeys=false] Disable the arrow keys for next/previous page and +/- for zooming (if zooming is enabled)
|
||||
* @property {boolean} [redrawOnWindowResize=true] Force resize of PDF viewer on window resize
|
||||
* @property {float} [pdfScale=1] Defines the ratio between your PDF page size and the tabs size
|
||||
* @property {float} [quality=2] Set quality ratio for loaded PDF pages. Set at 2 for sharp display when user zooms up to 200%
|
||||
* @property {boolean} [showToolbar=true] Show a toolbar on top of the document with title, page number and buttons for next/prev pages and zooming
|
||||
* @property {function} [loaded=null] A handler triggered when PDF document is loaded (before display of first page)
|
||||
* @property {function} [changed=null] A handler triggered each time a new page is displayed
|
||||
* @property {string} [loadingHTML="Loading PDF"] Text or HTML displayed on white page shown before document is loaded
|
||||
* @property {function} [loadingHeight=841] Height in px of white page shown before document is loaded
|
||||
* @property {function} [loadingWidth=595] Width in px of white page shown before document is loaded
|
||||
*/
|
||||
var defaults = {
|
||||
source: null,
|
||||
title: "TouchPDF",
|
||||
tabs: [],
|
||||
tabsColor: "beige",
|
||||
disableZoom: false,
|
||||
disableSwipe: false,
|
||||
disableLinks: false,
|
||||
disableKeys: false,
|
||||
pdfScale: 1,
|
||||
quality: 2,
|
||||
redrawOnWindowResize: true,
|
||||
showToolbar: true,
|
||||
loaded: null,
|
||||
changed: null,
|
||||
loadingHeight: 841,
|
||||
loadingWidth: 595,
|
||||
loadingHTML: "Loading PDF"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load a PDF file in a div
|
||||
* The TouchPDF plugin can be instantiated via this method, or methods within
|
||||
* @see TouchPDF
|
||||
* @class
|
||||
* @param {Mixed} method If the current DOMNode is a TouchPDF object, and <code>method</code> is a TouchPDF method, then
|
||||
* the <code>method</code> is executed, and any following arguments are passed to the TouchPDF method.
|
||||
* If <code>method</code> is an object, then the TouchPDF class is instantiated on the current DOMNode, passing the
|
||||
* configuration properties defined in the object. See TouchPDF
|
||||
*/
|
||||
$.fn.pdf = function (method) {
|
||||
var $this = $(this),
|
||||
plugin = $this.data(PLUGIN_NS);
|
||||
|
||||
//Check if we are already instantiated and trying to execute a method
|
||||
if (plugin && typeof method === 'string') {
|
||||
if (plugin[method]) {
|
||||
return plugin[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
||||
} else {
|
||||
$.error('Method ' + method + ' does not exist on jQuery.pdf');
|
||||
}
|
||||
}
|
||||
//Else not instantiated and trying to pass init object (or nothing)
|
||||
else if (!plugin && (typeof method === 'object' || !method)) {
|
||||
return init.apply(this, arguments);
|
||||
}
|
||||
|
||||
return $this;
|
||||
};
|
||||
|
||||
//Expose our defaults so a user could override the plugin defaults
|
||||
$.fn.pdf.defaults = defaults;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the plugin for each DOM element matched
|
||||
* This creates a new instance of the main TouchPDF class for each DOM element, and then
|
||||
* saves a reference to that instance in the elements data property.
|
||||
* @internal
|
||||
*/
|
||||
function init(options) {
|
||||
//Prep and extend the options
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
options = $.extend({}, $.fn.pdf.defaults, options);
|
||||
|
||||
//For each element instantiate the plugin
|
||||
return this.each(function () {
|
||||
var $this = $(this);
|
||||
|
||||
//Check we havent already initialised the plugin
|
||||
var plugin = $this.data(PLUGIN_NS);
|
||||
if (!plugin) {
|
||||
plugin = new TouchPDF(this, options);
|
||||
$this.data(PLUGIN_NS, plugin);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Main TouchPDF Plugin Class.
|
||||
* Do not use this to construct your TouchPDF object, use the jQuery plugin method $.fn.pdf(); {@link $.fn.pdf}
|
||||
* @private
|
||||
* @name TouchPDF
|
||||
* @param {DOMNode} element The HTML DOM object to apply to plugin to
|
||||
* @param {Object} options The options to configure the plugin with. @link {$.fn.pdf.defaults}
|
||||
* @see $.fn.pdf.defaults
|
||||
* @see $.fn.pdf
|
||||
* @class
|
||||
*/
|
||||
function TouchPDF(element, options) {
|
||||
|
||||
|
||||
// Current phase of pdf loading
|
||||
var state = EMPTY;
|
||||
// Number of pages
|
||||
var totalPages = 0;
|
||||
// Page to be displayed
|
||||
var pageNum = 0;
|
||||
// Page currently rendering
|
||||
var pageNumRendering = 0;
|
||||
// jQuery wrapped element for this instance
|
||||
var $element = $(element);
|
||||
// PDF canvas
|
||||
var canvas = null;
|
||||
// jQuery wrapped PDF annotation layer
|
||||
var $annotations = null;
|
||||
// PDF.JS object
|
||||
var pdfDoc = null;
|
||||
|
||||
var scale = 1;
|
||||
|
||||
var ctx = false;
|
||||
|
||||
var pagesRefMap = [];
|
||||
|
||||
var plugin = this;
|
||||
|
||||
var tabWidth = 0;
|
||||
var $drag = null, $viewer = null;
|
||||
|
||||
var linksDisabled = false;
|
||||
|
||||
initDom();
|
||||
load();
|
||||
|
||||
|
||||
//
|
||||
//Public methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Go to specific page of PDF file
|
||||
* @function
|
||||
* @name $.fn.pdf#goto
|
||||
* @return {DOMNode} The Dom element that was registered with TouchPDF
|
||||
* @example $("#element").pdf("goto", 10);
|
||||
*/
|
||||
this.goto = function (number) {
|
||||
goto(number);
|
||||
return $element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Go to previous page of PDF file, until first page
|
||||
* @function
|
||||
* @name $.fn.pdf#previous
|
||||
* @return {DOMNode} The Dom element that was registered with TouchPDF
|
||||
* @example $("#element").pdf("previous");
|
||||
*/
|
||||
this.previous = function () {
|
||||
goto(pageNum-1);
|
||||
return $element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Go to next page of PDF file, until end of pdf
|
||||
* @function
|
||||
* @name $.fn.pdf#next
|
||||
* @return {DOMNode} The Dom element that was registered with TouchPDF
|
||||
* @example $("#element").pdf("next");
|
||||
*/
|
||||
this.next = function () {
|
||||
goto(pageNum+1);
|
||||
return $element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Force redraw of pdf (height, width and zoom)
|
||||
* @function
|
||||
* @name $.fn.pdf#redraw
|
||||
* @return {DOMNode} The Dom element that was registered with TouchPDF
|
||||
* @example $("#element").pdf("redraw");
|
||||
*/
|
||||
this.redraw = function () {
|
||||
redraw();
|
||||
return $element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy the pdf container completely.
|
||||
* @function
|
||||
* @name $.fn.pdf#destroy
|
||||
* @example $("#element").pdf("destroy");
|
||||
*/
|
||||
this.destroy = function () {
|
||||
$element.empty().removeClass("touchPDF");
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current page number (may not be rendered yet)
|
||||
* @function
|
||||
* @name $.fn.pdf#getPageNumber
|
||||
* @return {int} Current page number, 0 if PDF is not loaded
|
||||
* @example $("#element").pdf("getPageNumber");
|
||||
*/
|
||||
this.getPageNumber = function () {
|
||||
return pageNum;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the total number of pages of loaded PDF
|
||||
* @function
|
||||
* @name $.fn.pdf#getTotalPages
|
||||
* @return {int} The number of pages, 0 if PDF is not loaded
|
||||
* @example $("#element").pdf("getTotalPages");
|
||||
*/
|
||||
this.getTotalPages = function () {
|
||||
return totalPages;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Private methods
|
||||
//
|
||||
|
||||
|
||||
function goto(number) {
|
||||
if (state == EMPTY || state == INIT) return;
|
||||
if (number < 1) number = 1;
|
||||
if (number > totalPages) number = totalPages;
|
||||
if (number == 0) return;
|
||||
pageNum = number;
|
||||
renderPage();
|
||||
|
||||
// update tabs
|
||||
var z = 1;
|
||||
$element.find(".pdf-tabs .tab").each(function(i, a) {
|
||||
var $a = $(a);
|
||||
var aPageNum = $a.data("page");
|
||||
if ( aPageNum < number) {
|
||||
$a.removeClass("right");
|
||||
$a.css("z-index", 1000+z++);
|
||||
} else if (aPageNum == number) {
|
||||
$a.removeClass("right");
|
||||
$a.css("z-index", 1000+z++);
|
||||
} else {
|
||||
$a.addClass("right");
|
||||
$a.css("z-index", 1000-z++);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initDom() {
|
||||
if (state != EMPTY) return;
|
||||
$element.addClass("touchPDF").html(
|
||||
'<div class="pdf-outerdiv">'
|
||||
+ '<div class="pdf-tabs"></div>'
|
||||
+ '<div class="pdf-toolbar"></div>'
|
||||
+ '<div class="pdf-viewer">'
|
||||
+ '<div class="pdf-loading">'+options.loadingHTML+'</div>'
|
||||
+ '<div class="pdf-drag">'
|
||||
+ '<div class="pdf-canvas">'
|
||||
+ '<canvas></canvas>'
|
||||
+ '<div class="pdf-annotations"></div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>');
|
||||
|
||||
if (options.showToolbar) {
|
||||
|
||||
$element.find(".pdf-toolbar").html(
|
||||
'<div class="pdf-title">'+options.title+'</div>'
|
||||
+ '<div class="pdf-button"><button class="pdf-prev"><</button></div>'
|
||||
+ '<div class="pdf-button"><span class="pdf-page-count"></span></div>'
|
||||
+ '<div class="pdf-button"><button class="pdf-next">></button></div>'
|
||||
+ (options.disableZoom? '':'<div class="pdf-button"><button class="pdf-zoomin">+</button></div>'
|
||||
+ '<div class="pdf-button"><button class="pdf-zoomout">-</button></div>')
|
||||
);
|
||||
|
||||
$element.find(".pdf-toolbar > .pdf-title").on("click", function() {
|
||||
goto(1);
|
||||
});
|
||||
$element.find(".pdf-toolbar > .pdf-button > .pdf-prev").on("click", function() {
|
||||
goto(pageNum-1);
|
||||
});
|
||||
$element.find(".pdf-toolbar > .pdf-button > .pdf-next").on("click", function() {
|
||||
goto(pageNum+1);
|
||||
});
|
||||
}
|
||||
|
||||
$drag = $element.find(".pdf-drag");
|
||||
$viewer = $element.find(".pdf-viewer");
|
||||
|
||||
|
||||
if (!options.disableKeys) {
|
||||
$(window).keydown(function(event) {
|
||||
if (event.keyCode == 37) goto(pageNum-1);
|
||||
else if (event.keyCode == 39) goto(pageNum+1);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.redrawOnWindowResize) {
|
||||
var windowResizeTimeout = false;
|
||||
$( window ).resize(function() {
|
||||
clearTimeout(windowResizeTimeout);
|
||||
windowResizeTimeout = setTimeout(function() {
|
||||
redraw();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
if (!options.disableZoom) {
|
||||
|
||||
$drag.panzoom({
|
||||
contain: 'invert',
|
||||
minScale: 1,
|
||||
disablePan: true,
|
||||
increment: 0.25,
|
||||
maxScale: 2,
|
||||
onChange: function() {
|
||||
linksDisabled = true;
|
||||
$drag.panzoom("option", "disablePan", false);
|
||||
state = ZOOMEDIN;
|
||||
},
|
||||
onEnd: function() {
|
||||
setTimeout(function() {
|
||||
linksDisabled = false;
|
||||
if ($drag.panzoom("getMatrix")[0] == 1) zoomReset();
|
||||
}, 1);
|
||||
}
|
||||
|
||||
});
|
||||
$drag.panzoom('enable');
|
||||
|
||||
$drag.parent().on('mousewheel.focal', function( e ) {
|
||||
e.preventDefault();
|
||||
var delta = e.delta || e.originalEvent.wheelDelta;
|
||||
var direction = delta ? delta < 0 : e.originalEvent.deltaY > 0;
|
||||
if (direction) zoomOut(e);
|
||||
else zoomIn(e);
|
||||
});
|
||||
|
||||
if (options.showToolbar) {
|
||||
$element.find(".pdf-toolbar > .pdf-button > .pdf-zoomin").on("click", function() {
|
||||
zoomIn();
|
||||
});
|
||||
$element.find(".pdf-toolbar > .pdf-button > .pdf-zoomout").on("click", function() {
|
||||
zoomOut();
|
||||
});
|
||||
}
|
||||
|
||||
if (!options.disableLinks) {
|
||||
// enable links while zoomed in
|
||||
var touchlink = null;
|
||||
$drag.on('touchstart', "a", function( e ) {
|
||||
touchlink = this;
|
||||
setTimeout(function() {
|
||||
touchlink = null;
|
||||
}, 100);
|
||||
});
|
||||
$drag.on('touchend', "a", function( e ) {
|
||||
if (this == touchlink) {
|
||||
e.stopImmediatePropagation();
|
||||
this.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!options.disableSwipe) {
|
||||
$viewer.swipe( {
|
||||
swipe:function(event, direction, distance, duration, fingerCount, fingerData) {
|
||||
if (state != LOADED) return;
|
||||
linksDisabled = true;
|
||||
setTimeout(function() {linksDisabled = false;}, 1);
|
||||
if (direction == "right") goto(pageNum-1);
|
||||
else if (direction == "left") goto(pageNum+1);
|
||||
},
|
||||
threshold:50,
|
||||
excludedElements: ".noSwipe"
|
||||
});
|
||||
}
|
||||
|
||||
canvas = $element.find("canvas")[0];
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
$annotations = $element.find(".pdf-annotations");
|
||||
|
||||
state = INIT;
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
function zoomIn (focal) {
|
||||
if (options.disableZoom) return;
|
||||
if (state != ZOOMEDIN && state != LOADED) return;
|
||||
state = ZOOMEDIN;
|
||||
$drag.panzoom('zoom', false, {
|
||||
increment: 0.25,
|
||||
animate: true,
|
||||
focal: focal
|
||||
});
|
||||
linksDisabled = false;
|
||||
}
|
||||
|
||||
function zoomOut(focal) {
|
||||
if (options.disableZoom) return;
|
||||
if (state != ZOOMEDIN) return;
|
||||
$drag.panzoom('zoom', true, {
|
||||
increment: 0.25,
|
||||
animate: true,
|
||||
focal: focal
|
||||
});
|
||||
linksDisabled = false;
|
||||
|
||||
if ($drag.panzoom("getMatrix")[0] == 1) zoomReset();
|
||||
}
|
||||
function zoomReset() {
|
||||
if (options.disableZoom) return;
|
||||
$drag.panzoom('reset');
|
||||
linksDisabled = false;
|
||||
$drag.panzoom("option", "disablePan", true);
|
||||
state = LOADED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously downloads PDF.
|
||||
*/
|
||||
function load () {
|
||||
if (state != INIT) return;
|
||||
state = LOADING;
|
||||
|
||||
PDFJS.getDocument(options.source).then(function (pdfDoc_) {
|
||||
pdfDoc = pdfDoc_;
|
||||
totalPages = pdfDoc.numPages;
|
||||
if (totalPages < 1) return;
|
||||
|
||||
state = LOADED;
|
||||
if (options.loaded) options.loaded()
|
||||
goto(1);
|
||||
});
|
||||
|
||||
if (options.tabs && $.isArray(options.tabs)) {
|
||||
|
||||
var top = [];
|
||||
var maxOffset = 0;
|
||||
|
||||
$.each(options.tabs, function(i, tab) {
|
||||
if(tab.offset && tab.offset > maxOffset) maxOffset = tab.offset;
|
||||
});
|
||||
|
||||
tabWidth = TAB_WIDTH + TAB_OFFSET_WIDTH * maxOffset;
|
||||
|
||||
$.each(options.tabs, function(i, tab) {
|
||||
var offset = tab.offset || 0;
|
||||
if (top[offset] === undefined) {
|
||||
top[offset] = 5 + TOOLBAR_HEIGHT;
|
||||
}
|
||||
|
||||
var $a = $("<a>")
|
||||
.addClass("tab")
|
||||
.data("page", tab.page)
|
||||
.css("margin-left", offset*TAB_OFFSET_WIDTH+"px")
|
||||
.css("margin-right", (maxOffset-offset)*TAB_OFFSET_WIDTH+"px")
|
||||
.click(function() {
|
||||
if (tab.page == pageNumRendering) goto(tab.page-1);
|
||||
else goto(tab.page)
|
||||
});
|
||||
var $span = $("<span>")
|
||||
.html(tab.title)
|
||||
.appendTo($a);
|
||||
|
||||
if (tab.bottom !== undefined) {
|
||||
$a.css("bottom", tab.bottom);
|
||||
} else {
|
||||
if (tab.top !== undefined) top[offset] = tab.top + TOOLBAR_HEIGHT;
|
||||
$a.css("top", top[offset]);
|
||||
}
|
||||
|
||||
if (tab.title.length > 2) $a.addClass("large");
|
||||
if (!tab.color) tab.color = options.tabsColor;
|
||||
$a.addClass(tab.color);
|
||||
if (tab.height) {
|
||||
$a.css("height", tab.height);
|
||||
$span.css("width", tab.height);
|
||||
}
|
||||
|
||||
$element.find(".pdf-tabs").append($a);
|
||||
|
||||
if (tab.bottom === undefined) top[offset] += $a.height() + TAB_SPACING;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page info from document, resize canvas accordingly, and render page.
|
||||
* @param num Page number.
|
||||
*/
|
||||
function renderPage () {
|
||||
if (state != LOADED && state != ZOOMEDIN) return;
|
||||
if (pageNum == pageNumRendering) return;
|
||||
|
||||
zoomReset();
|
||||
state = RENDERING;
|
||||
pageNumRendering = pageNum;
|
||||
updatePageCount();
|
||||
|
||||
// Using promise to fetch the page
|
||||
pdfDoc.getPage(pageNumRendering).then(function(page) {
|
||||
var viewport = page.getViewport(options.pdfScale*options.quality);
|
||||
canvas.height = viewport.height;
|
||||
canvas.width = viewport.width;
|
||||
$(".pdf-canvas").css("transform", "scale("+(1/options.quality)+")").css("transform-origin", "top left");
|
||||
|
||||
// Render PDF page into canvas context
|
||||
var renderTask = page.render({
|
||||
canvasContext: ctx,
|
||||
viewport: viewport
|
||||
});
|
||||
|
||||
if (!options.disableLinks) {
|
||||
renderAnnotations(page, viewport);
|
||||
}
|
||||
|
||||
// Wait for rendering to finish
|
||||
renderTask.promise.then(function () {
|
||||
state = LOADED;
|
||||
if (pageNumRendering != pageNum) {
|
||||
// New page rendering is pending
|
||||
renderPage();
|
||||
}
|
||||
});
|
||||
|
||||
redraw();
|
||||
$element.find(".pdf-loading").hide();
|
||||
$element.find(".pdf-tabs").css("visibility", "visible");
|
||||
$element.find("canvas").css("visibility", "visible");
|
||||
|
||||
if (options.changed) options.changed();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function redraw() {
|
||||
|
||||
if (state == INIT) {
|
||||
var pdfHeight = options.loadingHeight;
|
||||
var pdfWidth = options.loadingWidth;
|
||||
|
||||
} else {
|
||||
var pdfHeight = canvas.height / options.quality;
|
||||
var pdfWidth = canvas.width / options.quality;
|
||||
}
|
||||
var winHeight = $element.height();
|
||||
var winWidth = $element.width();
|
||||
|
||||
|
||||
scale = Math.min( winHeight / (pdfHeight + TOOLBAR_HEIGHT + BORDER_WIDTH*2), winWidth / (pdfWidth + tabWidth*2 + BORDER_WIDTH*2) );
|
||||
if (scale > 1) scale = 1;
|
||||
|
||||
$element.find(".pdf-outerdiv")
|
||||
.css("transform", "scale("+scale+")")
|
||||
.css("width", pdfWidth + BORDER_WIDTH*2)
|
||||
.css("height", pdfHeight + TOOLBAR_HEIGHT + BORDER_WIDTH*2)
|
||||
.css("padding", "0 "+tabWidth+"px")
|
||||
.css("left", (winWidth - scale*(pdfWidth + tabWidth*2 + BORDER_WIDTH*2))/2);
|
||||
|
||||
$element.find(".pdf-toolbar")
|
||||
.css("width", pdfWidth)
|
||||
.css("height", TOOLBAR_HEIGHT)
|
||||
.css("left", tabWidth + BORDER_WIDTH);
|
||||
|
||||
$viewer
|
||||
.css("width", pdfWidth)
|
||||
.css("height", pdfHeight)
|
||||
.css("left", tabWidth)
|
||||
.css("top", TOOLBAR_HEIGHT)
|
||||
.css("border-width", BORDER_WIDTH);
|
||||
|
||||
$drag
|
||||
.css("width", pdfWidth)
|
||||
.css("height", pdfHeight);
|
||||
|
||||
if (!options.disableZoom) {
|
||||
$drag.panzoom('resetDimensions');
|
||||
}
|
||||
|
||||
if (!options.disableSwipe) {
|
||||
$viewer.swipe("option", "threshold", 75*scale);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function updatePageCount() {
|
||||
if (state == EMPTY || state == INIT) return;
|
||||
$element.find(".pdf-page-count").html(pageNum + " / " + totalPages);
|
||||
}
|
||||
|
||||
function getPageIndex(destRef) {
|
||||
var defer = $.Deferred();
|
||||
|
||||
if (pagesRefMap[destRef.num + ' ' + destRef.gen + ' R']) {
|
||||
defer.resolve(pagesRefMap[destRef.num + ' ' + destRef.gen + ' R']);
|
||||
|
||||
} else {
|
||||
pdfDoc.getPageIndex(destRef).then(function (pageIndex) {
|
||||
pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] = pageIndex + 1;
|
||||
defer.resolve(pageIndex + 1);
|
||||
});
|
||||
}
|
||||
return defer.promise();
|
||||
}
|
||||
|
||||
function renderAnnotations(page, viewport) {
|
||||
if (state != RENDERING) return;
|
||||
|
||||
$annotations.empty();
|
||||
|
||||
page.getAnnotations().then(function (annotationsData) {
|
||||
|
||||
viewport = viewport.clone({dontFlip: true});
|
||||
|
||||
$.each(annotationsData, function(i, data) {
|
||||
if (!data || !data.hasHtml || data.subtype !== 'Link' || (!data.dest && !data.url)) return;
|
||||
|
||||
var $el = $(PDFJS.AnnotationUtils.getHtmlElement(data, page.commonObjs));
|
||||
var rect = data.rect;
|
||||
var view = page.view;
|
||||
rect = PDFJS.Util.normalizeRect([
|
||||
rect[0],
|
||||
view[3] - rect[1] + view[1],
|
||||
rect[2],
|
||||
view[3] - rect[3] + view[1]
|
||||
]);
|
||||
$el.css("left", rect[0] + 'px')
|
||||
.css("top", rect[1] + 'px')
|
||||
.css("position", 'absolute');
|
||||
|
||||
var transform = viewport.transform;
|
||||
var transformStr = 'matrix(' + transform.join(',') + ')';
|
||||
$el.css('transform', transformStr);
|
||||
var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px';
|
||||
$el.css('transformOrigin', transformOriginStr);
|
||||
|
||||
var link = $el.find("a")
|
||||
.on('mousedown', function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
if (data.url) {
|
||||
|
||||
link.addClass("externalLink")
|
||||
.attr("href", data.url)
|
||||
.attr("target", "_blank");
|
||||
|
||||
} else if (data.dest) {
|
||||
|
||||
link.addClass("internalLink")
|
||||
.data("dest", data.dest)
|
||||
.on('click', function(e) {
|
||||
if (state != LOADED && state != ZOOMEDIN) return false;
|
||||
if (linksDisabled) return false;
|
||||
var dest = $(this).data("dest");
|
||||
|
||||
if (dest instanceof Array) {
|
||||
getPageIndex(dest[0]).then( function ( num ) {
|
||||
if (state != LOADED && state != ZOOMEDIN) return;
|
||||
goto(num);
|
||||
});
|
||||
} else {
|
||||
pdfDoc.getDestination($(this).data("dest")).then(function(destRefs) {
|
||||
if (!(destRefs instanceof Array)) return; // invalid destination
|
||||
getPageIndex(destRefs[0]).then( function ( num ) {
|
||||
if (state != LOADED && state != ZOOMEDIN) return;
|
||||
if (linksDisabled) return;
|
||||
goto(num);
|
||||
});
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
$annotations.append($el);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
})(jQuery );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,577 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
/* Copyright 2012 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* globals VBArray, PDFJS */
|
||||
|
||||
'use strict';
|
||||
|
||||
// Initializing PDFJS global object here, it case if we need to change/disable
|
||||
// some PDF.js features, e.g. range requests
|
||||
if (typeof PDFJS === 'undefined') {
|
||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
// Checking if the typed arrays are supported
|
||||
// Support: iOS<6.0 (subarray), IE<10, Android<4.0
|
||||
(function checkTypedArrayCompatibility() {
|
||||
if (typeof Uint8Array !== 'undefined') {
|
||||
// Support: iOS<6.0
|
||||
if (typeof Uint8Array.prototype.subarray === 'undefined') {
|
||||
Uint8Array.prototype.subarray = function subarray(start, end) {
|
||||
return new Uint8Array(this.slice(start, end));
|
||||
};
|
||||
Float32Array.prototype.subarray = function subarray(start, end) {
|
||||
return new Float32Array(this.slice(start, end));
|
||||
};
|
||||
}
|
||||
|
||||
// Support: Android<4.1
|
||||
if (typeof Float64Array === 'undefined') {
|
||||
window.Float64Array = Float32Array;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function subarray(start, end) {
|
||||
return new TypedArray(this.slice(start, end));
|
||||
}
|
||||
|
||||
function setArrayOffset(array, offset) {
|
||||
if (arguments.length < 2) {
|
||||
offset = 0;
|
||||
}
|
||||
for (var i = 0, n = array.length; i < n; ++i, ++offset) {
|
||||
this[offset] = array[i] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
function TypedArray(arg1) {
|
||||
var result, i, n;
|
||||
if (typeof arg1 === 'number') {
|
||||
result = [];
|
||||
for (i = 0; i < arg1; ++i) {
|
||||
result[i] = 0;
|
||||
}
|
||||
} else if ('slice' in arg1) {
|
||||
result = arg1.slice(0);
|
||||
} else {
|
||||
result = [];
|
||||
for (i = 0, n = arg1.length; i < n; ++i) {
|
||||
result[i] = arg1[i];
|
||||
}
|
||||
}
|
||||
|
||||
result.subarray = subarray;
|
||||
result.buffer = result;
|
||||
result.byteLength = result.length;
|
||||
result.set = setArrayOffset;
|
||||
|
||||
if (typeof arg1 === 'object' && arg1.buffer) {
|
||||
result.buffer = arg1.buffer;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
window.Uint8Array = TypedArray;
|
||||
window.Int8Array = TypedArray;
|
||||
|
||||
// we don't need support for set, byteLength for 32-bit array
|
||||
// so we can use the TypedArray as well
|
||||
window.Uint32Array = TypedArray;
|
||||
window.Int32Array = TypedArray;
|
||||
window.Uint16Array = TypedArray;
|
||||
window.Float32Array = TypedArray;
|
||||
window.Float64Array = TypedArray;
|
||||
})();
|
||||
|
||||
// URL = URL || webkitURL
|
||||
// Support: Safari<7, Android 4.2+
|
||||
(function normalizeURLObject() {
|
||||
if (!window.URL) {
|
||||
window.URL = window.webkitURL;
|
||||
}
|
||||
})();
|
||||
|
||||
// Object.defineProperty()?
|
||||
// Support: Android<4.0, Safari<5.1
|
||||
(function checkObjectDefinePropertyCompatibility() {
|
||||
if (typeof Object.defineProperty !== 'undefined') {
|
||||
var definePropertyPossible = true;
|
||||
try {
|
||||
// some browsers (e.g. safari) cannot use defineProperty() on DOM objects
|
||||
// and thus the native version is not sufficient
|
||||
Object.defineProperty(new Image(), 'id', { value: 'test' });
|
||||
// ... another test for android gb browser for non-DOM objects
|
||||
var Test = function Test() {};
|
||||
Test.prototype = { get id() { } };
|
||||
Object.defineProperty(new Test(), 'id',
|
||||
{ value: '', configurable: true, enumerable: true, writable: false });
|
||||
} catch (e) {
|
||||
definePropertyPossible = false;
|
||||
}
|
||||
if (definePropertyPossible) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty = function objectDefineProperty(obj, name, def) {
|
||||
delete obj[name];
|
||||
if ('get' in def) {
|
||||
obj.__defineGetter__(name, def['get']);
|
||||
}
|
||||
if ('set' in def) {
|
||||
obj.__defineSetter__(name, def['set']);
|
||||
}
|
||||
if ('value' in def) {
|
||||
obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
|
||||
this.__defineGetter__(name, function objectDefinePropertyGetter() {
|
||||
return value;
|
||||
});
|
||||
return value;
|
||||
});
|
||||
obj[name] = def.value;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
// No XMLHttpRequest#response?
|
||||
// Support: IE<11, Android <4.0
|
||||
(function checkXMLHttpRequestResponseCompatibility() {
|
||||
var xhrPrototype = XMLHttpRequest.prototype;
|
||||
var xhr = new XMLHttpRequest();
|
||||
if (!('overrideMimeType' in xhr)) {
|
||||
// IE10 might have response, but not overrideMimeType
|
||||
// Support: IE10
|
||||
Object.defineProperty(xhrPrototype, 'overrideMimeType', {
|
||||
value: function xmlHttpRequestOverrideMimeType(mimeType) {}
|
||||
});
|
||||
}
|
||||
if ('responseType' in xhr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The worker will be using XHR, so we can save time and disable worker.
|
||||
PDFJS.disableWorker = true;
|
||||
|
||||
Object.defineProperty(xhrPrototype, 'responseType', {
|
||||
get: function xmlHttpRequestGetResponseType() {
|
||||
return this._responseType || 'text';
|
||||
},
|
||||
set: function xmlHttpRequestSetResponseType(value) {
|
||||
if (value === 'text' || value === 'arraybuffer') {
|
||||
this._responseType = value;
|
||||
if (value === 'arraybuffer' &&
|
||||
typeof this.overrideMimeType === 'function') {
|
||||
this.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Support: IE9
|
||||
if (typeof VBArray !== 'undefined') {
|
||||
Object.defineProperty(xhrPrototype, 'response', {
|
||||
get: function xmlHttpRequestResponseGet() {
|
||||
if (this.responseType === 'arraybuffer') {
|
||||
return new Uint8Array(new VBArray(this.responseBody).toArray());
|
||||
} else {
|
||||
return this.responseText;
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Object.defineProperty(xhrPrototype, 'response', {
|
||||
get: function xmlHttpRequestResponseGet() {
|
||||
if (this.responseType !== 'arraybuffer') {
|
||||
return this.responseText;
|
||||
}
|
||||
var text = this.responseText;
|
||||
var i, n = text.length;
|
||||
var result = new Uint8Array(n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
result[i] = text.charCodeAt(i) & 0xFF;
|
||||
}
|
||||
return result.buffer;
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
// window.btoa (base64 encode function) ?
|
||||
// Support: IE<10
|
||||
(function checkWindowBtoaCompatibility() {
|
||||
if ('btoa' in window) {
|
||||
return;
|
||||
}
|
||||
|
||||
var digits =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
|
||||
window.btoa = function windowBtoa(chars) {
|
||||
var buffer = '';
|
||||
var i, n;
|
||||
for (i = 0, n = chars.length; i < n; i += 3) {
|
||||
var b1 = chars.charCodeAt(i) & 0xFF;
|
||||
var b2 = chars.charCodeAt(i + 1) & 0xFF;
|
||||
var b3 = chars.charCodeAt(i + 2) & 0xFF;
|
||||
var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
|
||||
var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
|
||||
var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
|
||||
buffer += (digits.charAt(d1) + digits.charAt(d2) +
|
||||
digits.charAt(d3) + digits.charAt(d4));
|
||||
}
|
||||
return buffer;
|
||||
};
|
||||
})();
|
||||
|
||||
// window.atob (base64 encode function)?
|
||||
// Support: IE<10
|
||||
(function checkWindowAtobCompatibility() {
|
||||
if ('atob' in window) {
|
||||
return;
|
||||
}
|
||||
|
||||
// https://github.com/davidchambers/Base64.js
|
||||
var digits =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
window.atob = function (input) {
|
||||
input = input.replace(/=+$/, '');
|
||||
if (input.length % 4 === 1) {
|
||||
throw new Error('bad atob input');
|
||||
}
|
||||
for (
|
||||
// initialize result and counters
|
||||
var bc = 0, bs, buffer, idx = 0, output = '';
|
||||
// get next character
|
||||
buffer = input.charAt(idx++);
|
||||
// character found in table?
|
||||
// initialize bit storage and add its ascii value
|
||||
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
|
||||
// and if not first of each 4 characters,
|
||||
// convert the first 8 bits to one ascii character
|
||||
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
|
||||
) {
|
||||
// try to find character in table (0-63, not found => -1)
|
||||
buffer = digits.indexOf(buffer);
|
||||
}
|
||||
return output;
|
||||
};
|
||||
})();
|
||||
|
||||
// Function.prototype.bind?
|
||||
// Support: Android<4.0, iOS<6.0
|
||||
(function checkFunctionPrototypeBindCompatibility() {
|
||||
if (typeof Function.prototype.bind !== 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
Function.prototype.bind = function functionPrototypeBind(obj) {
|
||||
var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
|
||||
var bound = function functionPrototypeBindBound() {
|
||||
var args = headArgs.concat(Array.prototype.slice.call(arguments));
|
||||
return fn.apply(obj, args);
|
||||
};
|
||||
return bound;
|
||||
};
|
||||
})();
|
||||
|
||||
// HTMLElement dataset property
|
||||
// Support: IE<11, Safari<5.1, Android<4.0
|
||||
(function checkDatasetProperty() {
|
||||
var div = document.createElement('div');
|
||||
if ('dataset' in div) {
|
||||
return; // dataset property exists
|
||||
}
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'dataset', {
|
||||
get: function() {
|
||||
if (this._dataset) {
|
||||
return this._dataset;
|
||||
}
|
||||
|
||||
var dataset = {};
|
||||
for (var j = 0, jj = this.attributes.length; j < jj; j++) {
|
||||
var attribute = this.attributes[j];
|
||||
if (attribute.name.substring(0, 5) !== 'data-') {
|
||||
continue;
|
||||
}
|
||||
var key = attribute.name.substring(5).replace(/\-([a-z])/g,
|
||||
function(all, ch) {
|
||||
return ch.toUpperCase();
|
||||
});
|
||||
dataset[key] = attribute.value;
|
||||
}
|
||||
|
||||
Object.defineProperty(this, '_dataset', {
|
||||
value: dataset,
|
||||
writable: false,
|
||||
enumerable: false
|
||||
});
|
||||
return dataset;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
})();
|
||||
|
||||
// HTMLElement classList property
|
||||
// Support: IE<10, Android<4.0, iOS<5.0
|
||||
(function checkClassListProperty() {
|
||||
var div = document.createElement('div');
|
||||
if ('classList' in div) {
|
||||
return; // classList property exists
|
||||
}
|
||||
|
||||
function changeList(element, itemName, add, remove) {
|
||||
var s = element.className || '';
|
||||
var list = s.split(/\s+/g);
|
||||
if (list[0] === '') {
|
||||
list.shift();
|
||||
}
|
||||
var index = list.indexOf(itemName);
|
||||
if (index < 0 && add) {
|
||||
list.push(itemName);
|
||||
}
|
||||
if (index >= 0 && remove) {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
element.className = list.join(' ');
|
||||
return (index >= 0);
|
||||
}
|
||||
|
||||
var classListPrototype = {
|
||||
add: function(name) {
|
||||
changeList(this.element, name, true, false);
|
||||
},
|
||||
contains: function(name) {
|
||||
return changeList(this.element, name, false, false);
|
||||
},
|
||||
remove: function(name) {
|
||||
changeList(this.element, name, false, true);
|
||||
},
|
||||
toggle: function(name) {
|
||||
changeList(this.element, name, true, true);
|
||||
}
|
||||
};
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'classList', {
|
||||
get: function() {
|
||||
if (this._classList) {
|
||||
return this._classList;
|
||||
}
|
||||
|
||||
var classList = Object.create(classListPrototype, {
|
||||
element: {
|
||||
value: this,
|
||||
writable: false,
|
||||
enumerable: true
|
||||
}
|
||||
});
|
||||
Object.defineProperty(this, '_classList', {
|
||||
value: classList,
|
||||
writable: false,
|
||||
enumerable: false
|
||||
});
|
||||
return classList;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
})();
|
||||
|
||||
// Check console compatibility
|
||||
// In older IE versions the console object is not available
|
||||
// unless console is open.
|
||||
// Support: IE<10
|
||||
(function checkConsoleCompatibility() {
|
||||
if (!('console' in window)) {
|
||||
window.console = {
|
||||
log: function() {},
|
||||
error: function() {},
|
||||
warn: function() {}
|
||||
};
|
||||
} else if (!('bind' in console.log)) {
|
||||
// native functions in IE9 might not have bind
|
||||
console.log = (function(fn) {
|
||||
return function(msg) { return fn(msg); };
|
||||
})(console.log);
|
||||
console.error = (function(fn) {
|
||||
return function(msg) { return fn(msg); };
|
||||
})(console.error);
|
||||
console.warn = (function(fn) {
|
||||
return function(msg) { return fn(msg); };
|
||||
})(console.warn);
|
||||
}
|
||||
})();
|
||||
|
||||
// Check onclick compatibility in Opera
|
||||
// Support: Opera<15
|
||||
(function checkOnClickCompatibility() {
|
||||
// workaround for reported Opera bug DSK-354448:
|
||||
// onclick fires on disabled buttons with opaque content
|
||||
function ignoreIfTargetDisabled(event) {
|
||||
if (isDisabled(event.target)) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
function isDisabled(node) {
|
||||
return node.disabled || (node.parentNode && isDisabled(node.parentNode));
|
||||
}
|
||||
if (navigator.userAgent.indexOf('Opera') !== -1) {
|
||||
// use browser detection since we cannot feature-check this bug
|
||||
document.addEventListener('click', ignoreIfTargetDisabled, true);
|
||||
}
|
||||
})();
|
||||
|
||||
// Checks if possible to use URL.createObjectURL()
|
||||
// Support: IE
|
||||
(function checkOnBlobSupport() {
|
||||
// sometimes IE loosing the data created with createObjectURL(), see #3977
|
||||
if (navigator.userAgent.indexOf('Trident') >= 0) {
|
||||
PDFJS.disableCreateObjectURL = true;
|
||||
}
|
||||
})();
|
||||
|
||||
// Checks if navigator.language is supported
|
||||
(function checkNavigatorLanguage() {
|
||||
if ('language' in navigator) {
|
||||
return;
|
||||
}
|
||||
PDFJS.locale = navigator.userLanguage || 'en-US';
|
||||
})();
|
||||
|
||||
(function checkRangeRequests() {
|
||||
// Safari has issues with cached range requests see:
|
||||
// https://github.com/mozilla/pdf.js/issues/3260
|
||||
// Last tested with version 6.0.4.
|
||||
// Support: Safari 6.0+
|
||||
var isSafari = Object.prototype.toString.call(
|
||||
window.HTMLElement).indexOf('Constructor') > 0;
|
||||
|
||||
// Older versions of Android (pre 3.0) has issues with range requests, see:
|
||||
// https://github.com/mozilla/pdf.js/issues/3381.
|
||||
// Make sure that we only match webkit-based Android browsers,
|
||||
// since Firefox/Fennec works as expected.
|
||||
// Support: Android<3.0
|
||||
var regex = /Android\s[0-2][^\d]/;
|
||||
var isOldAndroid = regex.test(navigator.userAgent);
|
||||
|
||||
// Range requests are broken in Chrome 39 and 40, https://crbug.com/442318
|
||||
var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent);
|
||||
|
||||
if (isSafari || isOldAndroid || isChromeWithRangeBug) {
|
||||
PDFJS.disableRange = true;
|
||||
PDFJS.disableStream = true;
|
||||
}
|
||||
})();
|
||||
|
||||
// Check if the browser supports manipulation of the history.
|
||||
// Support: IE<10, Android<4.2
|
||||
(function checkHistoryManipulation() {
|
||||
// Android 2.x has so buggy pushState support that it was removed in
|
||||
// Android 3.0 and restored as late as in Android 4.2.
|
||||
// Support: Android 2.x
|
||||
if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) {
|
||||
PDFJS.disableHistory = true;
|
||||
}
|
||||
})();
|
||||
|
||||
// Support: IE<11, Chrome<21, Android<4.4, Safari<6
|
||||
(function checkSetPresenceInImageData() {
|
||||
// IE < 11 will use window.CanvasPixelArray which lacks set function.
|
||||
if (window.CanvasPixelArray) {
|
||||
if (typeof window.CanvasPixelArray.prototype.set !== 'function') {
|
||||
window.CanvasPixelArray.prototype.set = function(arr) {
|
||||
for (var i = 0, ii = this.length; i < ii; i++) {
|
||||
this[i] = arr[i];
|
||||
}
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Old Chrome and Android use an inaccessible CanvasPixelArray prototype.
|
||||
// Because we cannot feature detect it, we rely on user agent parsing.
|
||||
var polyfill = false, versionMatch;
|
||||
if (navigator.userAgent.indexOf('Chrom') >= 0) {
|
||||
versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
||||
// Chrome < 21 lacks the set function.
|
||||
polyfill = versionMatch && parseInt(versionMatch[2]) < 21;
|
||||
} else if (navigator.userAgent.indexOf('Android') >= 0) {
|
||||
// Android < 4.4 lacks the set function.
|
||||
// Android >= 4.4 will contain Chrome in the user agent,
|
||||
// thus pass the Chrome check above and not reach this block.
|
||||
polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent);
|
||||
} else if (navigator.userAgent.indexOf('Safari') >= 0) {
|
||||
versionMatch = navigator.userAgent.
|
||||
match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//);
|
||||
// Safari < 6 lacks the set function.
|
||||
polyfill = versionMatch && parseInt(versionMatch[1]) < 6;
|
||||
}
|
||||
|
||||
if (polyfill) {
|
||||
var contextPrototype = window.CanvasRenderingContext2D.prototype;
|
||||
contextPrototype._createImageData = contextPrototype.createImageData;
|
||||
contextPrototype.createImageData = function(w, h) {
|
||||
var imageData = this._createImageData(w, h);
|
||||
imageData.data.set = function(arr) {
|
||||
for (var i = 0, ii = this.length; i < ii; i++) {
|
||||
this[i] = arr[i];
|
||||
}
|
||||
};
|
||||
return imageData;
|
||||
};
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
// Support: IE<10, Android<4.0, iOS
|
||||
(function checkRequestAnimationFrame() {
|
||||
function fakeRequestAnimationFrame(callback) {
|
||||
window.setTimeout(callback, 20);
|
||||
}
|
||||
|
||||
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
|
||||
if (isIOS) {
|
||||
// requestAnimationFrame on iOS is broken, replacing with fake one.
|
||||
window.requestAnimationFrame = fakeRequestAnimationFrame;
|
||||
return;
|
||||
}
|
||||
if ('requestAnimationFrame' in window) {
|
||||
return;
|
||||
}
|
||||
window.requestAnimationFrame =
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
fakeRequestAnimationFrame;
|
||||
})();
|
||||
|
||||
(function checkCanvasSizeLimitation() {
|
||||
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
|
||||
var isAndroid = /Android/g.test(navigator.userAgent);
|
||||
if (isIOS || isAndroid) {
|
||||
// 5MP
|
||||
PDFJS.maxCanvasPixels = 5242880;
|
||||
}
|
||||
})();
|
||||
|
||||
// Disable fullscreen support for certain problematic configurations.
|
||||
// Support: IE11+ (when embedded).
|
||||
(function checkFullscreenSupport() {
|
||||
var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 &&
|
||||
window.parent !== window);
|
||||
if (isEmbeddedIE) {
|
||||
PDFJS.disableFullscreen = true;
|
||||
}
|
||||
})();
|
||||
+8120
File diff suppressed because it is too large
Load Diff
+39612
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user