/*
* @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 method
is a TouchPDF method, then
* the method
is executed, and any following arguments are passed to the TouchPDF method.
* If method
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(
'