jspdf-autotable
Version:
Generate pdf tables with javascript (jsPDF plugin)
1,474 lines (1,224 loc) • 880 kB
JavaScript
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
}(function () { 'use strict';
/** @license
* jsPDF - PDF Document creation from JavaScript
* Version 1.5.3 Built on 2018-12-27T14:11:42.696Z
* CommitID d93d28db14
*
* Copyright (c) 2010-2016 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF
* 2010 Aaron Spike, https://github.com/acspike
* 2012 Willow Systems Corporation, willow-systems.com
* 2012 Pablo Hess, https://github.com/pablohess
* 2012 Florian Jenett, https://github.com/fjenett
* 2013 Warren Weckesser, https://github.com/warrenweckesser
* 2013 Youssef Beddad, https://github.com/lifof
* 2013 Lee Driscoll, https://github.com/lsdriscoll
* 2013 Stefan Slonevskiy, https://github.com/stefslon
* 2013 Jeremy Morel, https://github.com/jmorel
* 2013 Christoph Hartmann, https://github.com/chris-rock
* 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
* 2014 James Makes, https://github.com/dollaruw
* 2014 Diego Casorran, https://github.com/diegocr
* 2014 Steven Spungin, https://github.com/Flamenco
* 2014 Kenneth Glassey, https://github.com/Gavvers
*
* Licensed under the MIT License
*
* Contributor(s):
* siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
* kim3er, mfo, alnorth, Flamenco
*/
function _typeof(obj) {
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
/**
* JavaScript Polyfill functions for jsPDF
* Collected from public resources by
* https://github.com/diegocr
*/
(function (global) {
if (_typeof(global.console) !== "object") {
// Console-polyfill. MIT license.
// https://github.com/paulmillr/console-polyfill
// Make it safe to do console.log() always.
global.console = {};
var con = global.console;
var prop, method;
var dummy = function dummy() {};
var properties = ['memory'];
var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
while (prop = properties.pop()) {
if (!con[prop]) con[prop] = {};
}
while (method = methods.pop()) {
if (!con[method]) con[method] = dummy;
}
}
var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
if (typeof global.btoa === 'undefined') {
global.btoa = function (data) {
// discuss at: http://phpjs.org/functions/base64_encode/
// original by: Tyler Akins (http://rumkin.com)
// improved by: Bayron Guevara
// improved by: Thunder.m
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// improved by: Rafal Kukawski (http://kukawski.pl)
// bugfixed by: Pellentesque Malesuada
// example 1: base64_encode('Kevin van Zonneveld');
// returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
var o1,
o2,
o3,
h1,
h2,
h3,
h4,
bits,
i = 0,
ac = 0,
enc = '',
tmp_arr = [];
if (!data) {
return data;
}
do {
// pack three octets into four hexets
o1 = data.charCodeAt(i++);
o2 = data.charCodeAt(i++);
o3 = data.charCodeAt(i++);
bits = o1 << 16 | o2 << 8 | o3;
h1 = bits >> 18 & 0x3f;
h2 = bits >> 12 & 0x3f;
h3 = bits >> 6 & 0x3f;
h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string
tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
} while (i < data.length);
enc = tmp_arr.join('');
var r = data.length % 3;
return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
};
}
if (typeof global.atob === 'undefined') {
global.atob = function (data) {
// discuss at: http://phpjs.org/functions/base64_decode/
// original by: Tyler Akins (http://rumkin.com)
// improved by: Thunder.m
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// input by: Aman Gupta
// input by: Brett Zamir (http://brett-zamir.me)
// bugfixed by: Onno Marsman
// bugfixed by: Pellentesque Malesuada
// bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
// returns 1: 'Kevin van Zonneveld'
var o1,
o2,
o3,
h1,
h2,
h3,
h4,
bits,
i = 0,
ac = 0,
dec = '',
tmp_arr = [];
if (!data) {
return data;
}
data += '';
do {
// unpack four hexets into three octets using index points in b64
h1 = b64.indexOf(data.charAt(i++));
h2 = b64.indexOf(data.charAt(i++));
h3 = b64.indexOf(data.charAt(i++));
h4 = b64.indexOf(data.charAt(i++));
bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
o1 = bits >> 16 & 0xff;
o2 = bits >> 8 & 0xff;
o3 = bits & 0xff;
if (h3 == 64) {
tmp_arr[ac++] = String.fromCharCode(o1);
} else if (h4 == 64) {
tmp_arr[ac++] = String.fromCharCode(o1, o2);
} else {
tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
}
} while (i < data.length);
dec = tmp_arr.join('');
return dec;
};
}
if (!Array.prototype.map) {
Array.prototype.map = function (fun
/*, thisArg */
) {
if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError();
var t = Object(this),
len = t.length >>> 0,
res = new Array(len);
var thisArg = arguments.length > 1 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
// NOTE: Absolute correctness would demand Object.defineProperty
// be used. But this method is fairly new, and failure is
// possible only if Object.prototype or Array.prototype
// has a property |i| (very unlikely), so use a less-correct
// but more portable alternative.
if (i in t) res[i] = fun.call(thisArg, t[i], i, t);
}
return res;
};
}
if (!Array.isArray) {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (fun, thisArg) {
if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError();
var t = Object(this),
len = t.length >>> 0;
for (var i = 0; i < len; i++) {
if (i in t) fun.call(thisArg, t[i], i, t);
}
};
} // https://tc39.github.io/ecma262/#sec-array.prototype.find
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function value(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
} // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1]; // 5. Let k be 0.
var k = 0; // 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
} // e. Increase k by 1.
k++;
} // 7. Return undefined.
return undefined;
},
configurable: true,
writable: true
});
}
if (!Object.keys) {
Object.keys = function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !{
toString: null
}.propertyIsEnumerable('toString'),
dontEnums = ['toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (_typeof(obj) !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError();
}
var result = [],
prop,
i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}();
}
if (typeof Object.assign != 'function') {
Object.assign = function (target) {
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
target = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source != null) {
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
}
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
if (!String.prototype.trimLeft) {
String.prototype.trimLeft = function () {
return this.replace(/^\s+/g, "");
};
}
if (!String.prototype.trimRight) {
String.prototype.trimRight = function () {
return this.replace(/\s+$/g, "");
};
}
Number.isInteger = Number.isInteger || function (value) {
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
};
})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function('return this')()); // `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
/**
* Creates new jsPDF document object instance.
* @name jsPDF
* @class
* @param orientation {string/Object} Orientation of the first page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l").<br />
* Can also be an options object.
* @param unit {string} Measurement unit to be used when coordinates are specified.<br />
* Possible values are "pt" (points), "mm" (Default), "cm", "in" or "px".
* @param format {string/Array} The format of the first page. Can be:<ul><li>a0 - a10</li><li>b0 - b10</li><li>c0 - c10</li><li>dl</li><li>letter</li><li>government-letter</li><li>legal</li><li>junior-legal</li><li>ledger</li><li>tabloid</li><li>credit-card</li></ul><br />
* Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array, e.g. [595.28, 841.89]
* @returns {jsPDF} jsPDF-instance
* @description
* If the first parameter (orientation) is an object, it will be interpreted as an object of named parameters
* ```
* {
* orientation: 'p',
* unit: 'mm',
* format: 'a4',
* hotfixes: [] // an array of hotfix strings to enable
* }
* ```
*/
var jsPDF = function (global) {
/**
* jsPDF's Internal PubSub Implementation.
* Backward compatible rewritten on 2014 by
* Diego Casorran, https://github.com/diegocr
*
* @class
* @name PubSub
* @ignore
*/
function PubSub(context) {
if (_typeof(context) !== 'object') {
throw new Error('Invalid Context passed to initialize PubSub (jsPDF-module)');
}
var topics = {};
this.subscribe = function (topic, callback, once) {
once = once || false;
if (typeof topic !== 'string' || typeof callback !== 'function' || typeof once !== 'boolean') {
throw new Error('Invalid arguments passed to PubSub.subscribe (jsPDF-module)');
}
if (!topics.hasOwnProperty(topic)) {
topics[topic] = {};
}
var token = Math.random().toString(35);
topics[topic][token] = [callback, !!once];
return token;
};
this.unsubscribe = function (token) {
for (var topic in topics) {
if (topics[topic][token]) {
delete topics[topic][token];
if (Object.keys(topics[topic]).length === 0) {
delete topics[topic];
}
return true;
}
}
return false;
};
this.publish = function (topic) {
if (topics.hasOwnProperty(topic)) {
var args = Array.prototype.slice.call(arguments, 1),
tokens = [];
for (var token in topics[topic]) {
var sub = topics[topic][token];
try {
sub[0].apply(context, args);
} catch (ex) {
if (global.console) {
console.error('jsPDF PubSub Error', ex.message, ex);
}
}
if (sub[1]) tokens.push(token);
}
if (tokens.length) tokens.forEach(this.unsubscribe);
}
};
this.getTopics = function () {
return topics;
};
}
/**
* @constructor
* @private
*/
function jsPDF(orientation, unit, format, compressPdf) {
var options = {};
var filters = [];
var userUnit = 1.0;
if (_typeof(orientation) === 'object') {
options = orientation;
orientation = options.orientation;
unit = options.unit || unit;
format = options.format || format;
compressPdf = options.compress || options.compressPdf || compressPdf;
filters = options.filters || (compressPdf === true ? ['FlateEncode'] : filters);
userUnit = typeof options.userUnit === "number" ? Math.abs(options.userUnit) : 1.0;
}
unit = unit || 'mm';
orientation = ('' + (orientation || 'P')).toLowerCase();
var putOnlyUsedFonts = options.putOnlyUsedFonts || true;
var usedFonts = {};
var API = {
internal: {},
__private__: {}
};
API.__private__.PubSub = PubSub;
var pdfVersion = '1.3';
var getPdfVersion = API.__private__.getPdfVersion = function () {
return pdfVersion;
};
var setPdfVersion = API.__private__.setPdfVersion = function (value) {
pdfVersion = value;
}; // Size in pt of various paper formats
var pageFormats = {
'a0': [2383.94, 3370.39],
'a1': [1683.78, 2383.94],
'a2': [1190.55, 1683.78],
'a3': [841.89, 1190.55],
'a4': [595.28, 841.89],
'a5': [419.53, 595.28],
'a6': [297.64, 419.53],
'a7': [209.76, 297.64],
'a8': [147.40, 209.76],
'a9': [104.88, 147.40],
'a10': [73.70, 104.88],
'b0': [2834.65, 4008.19],
'b1': [2004.09, 2834.65],
'b2': [1417.32, 2004.09],
'b3': [1000.63, 1417.32],
'b4': [708.66, 1000.63],
'b5': [498.90, 708.66],
'b6': [354.33, 498.90],
'b7': [249.45, 354.33],
'b8': [175.75, 249.45],
'b9': [124.72, 175.75],
'b10': [87.87, 124.72],
'c0': [2599.37, 3676.54],
'c1': [1836.85, 2599.37],
'c2': [1298.27, 1836.85],
'c3': [918.43, 1298.27],
'c4': [649.13, 918.43],
'c5': [459.21, 649.13],
'c6': [323.15, 459.21],
'c7': [229.61, 323.15],
'c8': [161.57, 229.61],
'c9': [113.39, 161.57],
'c10': [79.37, 113.39],
'dl': [311.81, 623.62],
'letter': [612, 792],
'government-letter': [576, 756],
'legal': [612, 1008],
'junior-legal': [576, 360],
'ledger': [1224, 792],
'tabloid': [792, 1224],
'credit-card': [153, 243]
};
var getPageFormats = API.__private__.getPageFormats = function () {
return pageFormats;
};
var getPageFormat = API.__private__.getPageFormat = function (value) {
return pageFormats[value];
};
if (typeof format === "string") {
format = getPageFormat(format);
}
format = format || getPageFormat('a4');
var f2 = API.f2 = API.__private__.f2 = function (number) {
if (isNaN(number)) {
throw new Error('Invalid argument passed to jsPDF.f2');
}
return number.toFixed(2); // Ie, %.2f
};
var f3 = API.__private__.f3 = function (number) {
if (isNaN(number)) {
throw new Error('Invalid argument passed to jsPDF.f3');
}
return number.toFixed(3); // Ie, %.3f
};
var fileId = '00000000000000000000000000000000';
var getFileId = API.__private__.getFileId = function () {
return fileId;
};
var setFileId = API.__private__.setFileId = function (value) {
value = value || "12345678901234567890123456789012".split('').map(function () {
return "ABCDEF0123456789".charAt(Math.floor(Math.random() * 16));
}).join('');
fileId = value;
return fileId;
};
/**
* @name setFileId
* @memberOf jsPDF
* @function
* @instance
* @param {string} value GUID.
* @returns {jsPDF}
*/
API.setFileId = function (value) {
setFileId(value);
return this;
};
/**
* @name getFileId
* @memberOf jsPDF
* @function
* @instance
*
* @returns {string} GUID.
*/
API.getFileId = function () {
return getFileId();
};
var creationDate;
var convertDateToPDFDate = API.__private__.convertDateToPDFDate = function (parmDate) {
var result = '';
var tzoffset = parmDate.getTimezoneOffset(),
tzsign = tzoffset < 0 ? '+' : '-',
tzhour = Math.floor(Math.abs(tzoffset / 60)),
tzmin = Math.abs(tzoffset % 60),
timeZoneString = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join('');
result = ['D:', parmDate.getFullYear(), padd2(parmDate.getMonth() + 1), padd2(parmDate.getDate()), padd2(parmDate.getHours()), padd2(parmDate.getMinutes()), padd2(parmDate.getSeconds()), timeZoneString].join('');
return result;
};
var convertPDFDateToDate = API.__private__.convertPDFDateToDate = function (parmPDFDate) {
var year = parseInt(parmPDFDate.substr(2, 4), 10);
var month = parseInt(parmPDFDate.substr(6, 2), 10) - 1;
var date = parseInt(parmPDFDate.substr(8, 2), 10);
var hour = parseInt(parmPDFDate.substr(10, 2), 10);
var minutes = parseInt(parmPDFDate.substr(12, 2), 10);
var seconds = parseInt(parmPDFDate.substr(14, 2), 10);
var timeZoneHour = parseInt(parmPDFDate.substr(16, 2), 10);
var timeZoneMinutes = parseInt(parmPDFDate.substr(20, 2), 10);
var resultingDate = new Date(year, month, date, hour, minutes, seconds, 0);
return resultingDate;
};
var setCreationDate = API.__private__.setCreationDate = function (date) {
var tmpCreationDateString;
var regexPDFCreationDate = /^D:(20[0-2][0-9]|203[0-7]|19[7-9][0-9])(0[0-9]|1[0-2])([0-2][0-9]|3[0-1])(0[0-9]|1[0-9]|2[0-3])(0[0-9]|[1-5][0-9])(0[0-9]|[1-5][0-9])(\+0[0-9]|\+1[0-4]|\-0[0-9]|\-1[0-1])\'(0[0-9]|[1-5][0-9])\'?$/;
if (typeof date === "undefined") {
date = new Date();
}
if (_typeof(date) === "object" && Object.prototype.toString.call(date) === "[object Date]") {
tmpCreationDateString = convertDateToPDFDate(date);
} else if (regexPDFCreationDate.test(date)) {
tmpCreationDateString = date;
} else {
throw new Error('Invalid argument passed to jsPDF.setCreationDate');
}
creationDate = tmpCreationDateString;
return creationDate;
};
var getCreationDate = API.__private__.getCreationDate = function (type) {
var result = creationDate;
if (type === "jsDate") {
result = convertPDFDateToDate(creationDate);
}
return result;
};
/**
* @name setCreationDate
* @memberOf jsPDF
* @function
* @instance
* @param {Object} date
* @returns {jsPDF}
*/
API.setCreationDate = function (date) {
setCreationDate(date);
return this;
};
/**
* @name getCreationDate
* @memberOf jsPDF
* @function
* @instance
* @param {Object} type
* @returns {Object}
*/
API.getCreationDate = function (type) {
return getCreationDate(type);
};
var padd2 = API.__private__.padd2 = function (number) {
return ('0' + parseInt(number)).slice(-2);
};
var outToPages = !1; // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
var pages = [];
var content = [];
var currentPage;
var content_length = 0;
var customOutputDestination;
var setOutputDestination = API.__private__.setCustomOutputDestination = function (destination) {
customOutputDestination = destination;
};
var resetOutputDestination = API.__private__.resetCustomOutputDestination = function (destination) {
customOutputDestination = undefined;
};
var out = API.__private__.out = function (string) {
var writeArray;
string = typeof string === "string" ? string : string.toString();
if (typeof customOutputDestination === "undefined") {
writeArray = outToPages ? pages[currentPage] : content;
} else {
writeArray = customOutputDestination;
}
writeArray.push(string);
if (!outToPages) {
content_length += string.length + 1;
}
return writeArray;
};
var write = API.__private__.write = function (value) {
return out(arguments.length === 1 ? value.toString() : Array.prototype.join.call(arguments, ' '));
};
var getArrayBuffer = API.__private__.getArrayBuffer = function (data) {
var len = data.length,
ab = new ArrayBuffer(len),
u8 = new Uint8Array(ab);
while (len--) {
u8[len] = data.charCodeAt(len);
}
return ab;
};
var standardFonts = [['Helvetica', "helvetica", "normal", 'WinAnsiEncoding'], ['Helvetica-Bold', "helvetica", "bold", 'WinAnsiEncoding'], ['Helvetica-Oblique', "helvetica", "italic", 'WinAnsiEncoding'], ['Helvetica-BoldOblique', "helvetica", "bolditalic", 'WinAnsiEncoding'], ['Courier', "courier", "normal", 'WinAnsiEncoding'], ['Courier-Bold', "courier", "bold", 'WinAnsiEncoding'], ['Courier-Oblique', "courier", "italic", 'WinAnsiEncoding'], ['Courier-BoldOblique', "courier", "bolditalic", 'WinAnsiEncoding'], ['Times-Roman', "times", "normal", 'WinAnsiEncoding'], ['Times-Bold', "times", "bold", 'WinAnsiEncoding'], ['Times-Italic', "times", "italic", 'WinAnsiEncoding'], ['Times-BoldItalic', "times", "bolditalic", 'WinAnsiEncoding'], ['ZapfDingbats', "zapfdingbats", "normal", null], ['Symbol', "symbol", "normal", null]];
var getStandardFonts = API.__private__.getStandardFonts = function (data) {
return standardFonts;
};
var activeFontSize = options.fontSize || 16;
/**
* Sets font size for upcoming text elements.
*
* @param {number} size Font size in points.
* @function
* @instance
* @returns {jsPDF}
* @memberOf jsPDF
* @name setFontSize
*/
var setFontSize = API.__private__.setFontSize = API.setFontSize = function (size) {
activeFontSize = size;
return this;
};
/**
* Gets the fontsize for upcoming text elements.
*
* @function
* @instance
* @returns {number}
* @memberOf jsPDF
* @name getFontSize
*/
var getFontSize = API.__private__.getFontSize = API.getFontSize = function () {
return activeFontSize;
};
var R2L = options.R2L || false;
/**
* Set value of R2L functionality.
*
* @param {boolean} value
* @function
* @instance
* @returns {jsPDF} jsPDF-instance
* @memberOf jsPDF
* @name setR2L
*/
var setR2L = API.__private__.setR2L = API.setR2L = function (value) {
R2L = value;
return this;
};
/**
* Get value of R2L functionality.
*
* @function
* @instance
* @returns {boolean} jsPDF-instance
* @memberOf jsPDF
* @name getR2L
*/
var getR2L = API.__private__.getR2L = API.getR2L = function (value) {
return R2L;
};
var zoomMode; // default: 1;
var setZoomMode = API.__private__.setZoomMode = function (zoom) {
var validZoomModes = [undefined, null, 'fullwidth', 'fullheight', 'fullpage', 'original'];
if (/^\d*\.?\d*\%$/.test(zoom)) {
zoomMode = zoom;
} else if (!isNaN(zoom)) {
zoomMode = parseInt(zoom, 10);
} else if (validZoomModes.indexOf(zoom) !== -1) {
zoomMode = zoom;
} else {
throw new Error('zoom must be Integer (e.g. 2), a percentage Value (e.g. 300%) or fullwidth, fullheight, fullpage, original. "' + zoom + '" is not recognized.');
}
};
var getZoomMode = API.__private__.getZoomMode = function () {
return zoomMode;
};
var pageMode; // default: 'UseOutlines';
var setPageMode = API.__private__.setPageMode = function (pmode) {
var validPageModes = [undefined, null, 'UseNone', 'UseOutlines', 'UseThumbs', 'FullScreen'];
if (validPageModes.indexOf(pmode) == -1) {
throw new Error('Page mode must be one of UseNone, UseOutlines, UseThumbs, or FullScreen. "' + pmode + '" is not recognized.');
}
pageMode = pmode;
};
var getPageMode = API.__private__.getPageMode = function () {
return pageMode;
};
var layoutMode; // default: 'continuous';
var setLayoutMode = API.__private__.setLayoutMode = function (layout) {
var validLayoutModes = [undefined, null, 'continuous', 'single', 'twoleft', 'tworight', 'two'];
if (validLayoutModes.indexOf(layout) == -1) {
throw new Error('Layout mode must be one of continuous, single, twoleft, tworight. "' + layout + '" is not recognized.');
}
layoutMode = layout;
};
var getLayoutMode = API.__private__.getLayoutMode = function () {
return layoutMode;
};
/**
* Set the display mode options of the page like zoom and layout.
*
* @name setDisplayMode
* @memberOf jsPDF
* @function
* @instance
* @param {integer|String} zoom You can pass an integer or percentage as
* a string. 2 will scale the document up 2x, '200%' will scale up by the
* same amount. You can also set it to 'fullwidth', 'fullheight',
* 'fullpage', or 'original'.
*
* Only certain PDF readers support this, such as Adobe Acrobat.
*
* @param {string} layout Layout mode can be: 'continuous' - this is the
* default continuous scroll. 'single' - the single page mode only shows one
* page at a time. 'twoleft' - two column left mode, first page starts on
* the left, and 'tworight' - pages are laid out in two columns, with the
* first page on the right. This would be used for books.
* @param {string} pmode 'UseOutlines' - it shows the
* outline of the document on the left. 'UseThumbs' - shows thumbnails along
* the left. 'FullScreen' - prompts the user to enter fullscreen mode.
*
* @returns {jsPDF}
*/
var setDisplayMode = API.__private__.setDisplayMode = API.setDisplayMode = function (zoom, layout, pmode) {
setZoomMode(zoom);
setLayoutMode(layout);
setPageMode(pmode);
return this;
};
var documentProperties = {
'title': '',
'subject': '',
'author': '',
'keywords': '',
'creator': ''
};
var getDocumentProperty = API.__private__.getDocumentProperty = function (key) {
if (Object.keys(documentProperties).indexOf(key) === -1) {
throw new Error('Invalid argument passed to jsPDF.getDocumentProperty');
}
return documentProperties[key];
};
var getDocumentProperties = API.__private__.getDocumentProperties = function (properties) {
return documentProperties;
};
/**
* Adds a properties to the PDF document.
*
* @param {Object} A property_name-to-property_value object structure.
* @function
* @instance
* @returns {jsPDF}
* @memberOf jsPDF
* @name setDocumentProperties
*/
var setDocumentProperties = API.__private__.setDocumentProperties = API.setProperties = API.setDocumentProperties = function (properties) {
// copying only those properties we can render.
for (var property in documentProperties) {
if (documentProperties.hasOwnProperty(property) && properties[property]) {
documentProperties[property] = properties[property];
}
}
return this;
};
var setDocumentProperty = API.__private__.setDocumentProperty = function (key, value) {
if (Object.keys(documentProperties).indexOf(key) === -1) {
throw new Error('Invalid arguments passed to jsPDF.setDocumentProperty');
}
return documentProperties[key] = value;
};
var objectNumber = 0; // 'n' Current object number
var offsets = []; // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
var fonts = {}; // collection of font objects, where key is fontKey - a dynamically created label for a given font.
var fontmap = {}; // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
var activeFontKey; // will be string representing the KEY of the font as combination of fontName + fontStyle
var k; // Scale factor
var page = 0;
var pagesContext = [];
var additionalObjects = [];
var events = new PubSub(API);
var hotfixes = options.hotfixes || [];
var newObject = API.__private__.newObject = function () {
var oid = newObjectDeferred();
newObjectDeferredBegin(oid, true);
return oid;
}; // Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data
var newObjectDeferred = API.__private__.newObjectDeferred = function () {
objectNumber++;
offsets[objectNumber] = function () {
return content_length;
};
return objectNumber;
};
var newObjectDeferredBegin = function newObjectDeferredBegin(oid, doOutput) {
doOutput = typeof doOutput === 'boolean' ? doOutput : false;
offsets[oid] = content_length;
if (doOutput) {
out(oid + ' 0 obj');
}
return oid;
}; // Does not output the object until after the pages have been output.
// Returns an object containing the objectId and content.
// All pages have been added so the object ID can be estimated to start right after.
// This does not modify the current objectNumber; It must be updated after the newObjects are output.
var newAdditionalObject = API.__private__.newAdditionalObject = function () {
var objId = newObjectDeferred();
var obj = {
objId: objId,
content: ''
};
additionalObjects.push(obj);
return obj;
};
var rootDictionaryObjId = newObjectDeferred();
var resourceDictionaryObjId = newObjectDeferred(); /////////////////////
// Private functions
/////////////////////
var decodeColorString = API.__private__.decodeColorString = function (color) {
var colorEncoded = color.split(' ');
if (colorEncoded.length === 2 && (colorEncoded[1] === 'g' || colorEncoded[1] === 'G')) {
// convert grayscale value to rgb so that it can be converted to hex for consistency
var floatVal = parseFloat(colorEncoded[0]);
colorEncoded = [floatVal, floatVal, floatVal, 'r'];
}
var colorAsRGB = '#';
for (var i = 0; i < 3; i++) {
colorAsRGB += ('0' + Math.floor(parseFloat(colorEncoded[i]) * 255).toString(16)).slice(-2);
}
return colorAsRGB;
};
var encodeColorString = API.__private__.encodeColorString = function (options) {
var color;
if (typeof options === "string") {
options = {
ch1: options
};
}
var ch1 = options.ch1;
var ch2 = options.ch2;
var ch3 = options.ch3;
var ch4 = options.ch4;
var precision = options.precision;
var letterArray = options.pdfColorType === "draw" ? ['G', 'RG', 'K'] : ['g', 'rg', 'k'];
if (typeof ch1 === "string" && ch1.charAt(0) !== '#') {
var rgbColor = new RGBColor(ch1);
if (rgbColor.ok) {
ch1 = rgbColor.toHex();
} else if (!/^\d*\.?\d*$/.test(ch1)) {
throw new Error('Invalid color "' + ch1 + '" passed to jsPDF.encodeColorString.');
}
} //convert short rgb to long form
if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{3}$/.test(ch1)) {
ch1 = '#' + ch1[1] + ch1[1] + ch1[2] + ch1[2] + ch1[3] + ch1[3];
}
if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{6}$/.test(ch1)) {
var hex = parseInt(ch1.substr(1), 16);
ch1 = hex >> 16 & 255;
ch2 = hex >> 8 & 255;
ch3 = hex & 255;
}
if (typeof ch2 === "undefined" || typeof ch4 === "undefined" && ch1 === ch2 && ch2 === ch3) {
// Gray color space.
if (typeof ch1 === "string") {
color = ch1 + " " + letterArray[0];
} else {
switch (options.precision) {
case 2:
color = f2(ch1 / 255) + " " + letterArray[0];
break;
case 3:
default:
color = f3(ch1 / 255) + " " + letterArray[0];
}
}
} else if (typeof ch4 === "undefined" || _typeof(ch4) === "object") {
// assume RGBA
if (ch4 && !isNaN(ch4.a)) {
//TODO Implement transparency.
//WORKAROUND use white for now, if transparent, otherwise handle as rgb
if (ch4.a === 0) {
color = ['1.000', '1.000', '1.000', letterArray[1]].join(" ");
return color;
}
} // assume RGB
if (typeof ch1 === "string") {
color = [ch1, ch2, ch3, letterArray[1]].join(" ");
} else {
switch (options.precision) {
case 2:
color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), letterArray[1]].join(" ");
break;
default:
case 3:
color = [f3(ch1 / 255), f3(ch2 / 255), f3(ch3 / 255), letterArray[1]].join(" ");
}
}
} else {
// assume CMYK
if (typeof ch1 === 'string') {
color = [ch1, ch2, ch3, ch4, letterArray[2]].join(" ");
} else {
switch (options.precision) {
case 2:
color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), f2(ch4 / 255), letterArray[2]].join(" ");
break;
case 3:
default:
color = [f3(ch1 / 255), f3(ch2 / 255), f3(ch3 / 255), f3(ch4 / 255), letterArray[2]].join(" ");
}
}
}
return color;
};
var getFilters = API.__private__.getFilters = function () {
return filters;
};
var putStream = API.__private__.putStream = function (options) {
options = options || {};
var data = options.data || '';
var filters = options.filters || getFilters();
var alreadyAppliedFilters = options.alreadyAppliedFilters || [];
var addLength1 = options.addLength1 || false;
var valueOfLength1 = data.length;
var processedData = {};
if (filters === true) {
filters = ['FlateEncode'];
}
var keyValues = options.additionalKeyValues || [];
if (typeof jsPDF.API.processDataByFilters !== 'undefined') {
processedData = jsPDF.API.processDataByFilters(data, filters);
} else {
processedData = {
data: data,
reverseChain: []
};
}
var filterAsString = processedData.reverseChain + (Array.isArray(alreadyAppliedFilters) ? alreadyAppliedFilters.join(' ') : alreadyAppliedFilters.toString());
if (processedData.data.length !== 0) {
keyValues.push({
key: 'Length',
value: processedData.data.length
});
if (addLength1 === true) {
keyValues.push({
key: 'Length1',
value: valueOfLength1
});
}
}
if (filterAsString.length != 0) {
//if (filters.length === 0 && alreadyAppliedFilters.length === 1 && typeof alreadyAppliedFilters !== "undefined") {
if (filterAsString.split('/').length - 1 === 1) {
keyValues.push({
key: 'Filter',
value: filterAsString
});
} else {
keyValues.push({
key: 'Filter',
value: '[' + filterAsString + ']'
});
}
}
out('<<');
for (var i = 0; i < keyValues.length; i++) {
out('/' + keyValues[i].key + ' ' + keyValues[i].value);
}
out('>>');
if (processedData.data.length !== 0) {
out('stream');
out(processedData.data);
out('endstream');
}
};
var putPage = API.__private__.putPage = function (page) {
var mediaBox = page.mediaBox;
var pageNumber = page.number;
var data = page.data;
var pageObjectNumber = page.objId;
var pageContentsObjId = page.contentsObjId;
newObjectDeferredBegin(pageObjectNumber, true);
var wPt = pagesContext[currentPage].mediaBox.topRightX - pagesContext[currentPage].mediaBox.bottomLeftX;
var hPt = pagesContext[currentPage].mediaBox.topRightY - pagesContext[currentPage].mediaBox.bottomLeftY;
out('<</Type /Page');
out('/Parent ' + page.rootDictionaryObjId + ' 0 R');
out('/Resources ' + page.resourceDictionaryObjId + ' 0 R');
out('/MediaBox [' + parseFloat(f2(page.mediaBox.bottomLeftX)) + ' ' + parseFloat(f2(page.mediaBox.bottomLeftY)) + ' ' + f2(page.mediaBox.topRightX) + ' ' + f2(page.mediaBox.topRightY) + ']');
if (page.cropBox !== null) {
out('/CropBox [' + f2(page.cropBox.bottomLeftX) + ' ' + f2(page.cropBox.bottomLeftY) + ' ' + f2(page.cropBox.topRightX) + ' ' + f2(page.cropBox.topRightY) + ']');
}
if (page.bleedBox !== null) {
out('/BleedBox [' + f2(page.bleedBox.bottomLeftX) + ' ' + f2(page.bleedBox.bottomLeftY) + ' ' + f2(page.bleedBox.topRightX) + ' ' + f2(page.bleedBox.topRightY) + ']');
}
if (page.trimBox !== null) {
out('/TrimBox [' + f2(page.trimBox.bottomLeftX) + ' ' + f2(page.trimBox.bottomLeftY) + ' ' + f2(page.trimBox.topRightX) + ' ' + f2(page.trimBox.topRightY) + ']');
}
if (page.artBox !== null) {
out('/ArtBox [' + f2(page.artBox.bottomLeftX) + ' ' + f2(page.artBox.bottomLeftY) + ' ' + f2(page.artBox.topRightX) + ' ' + f2(page.artBox.topRightY) + ']');
}
if (typeof page.userUnit === "number" && page.userUnit !== 1.0) {
out('/UserUnit ' + page.userUnit);
}
events.publish('putPage', {
objId: pageObjectNumber,
pageContext: pagesContext[pageNumber],
pageNumber: pageNumber,
page: data
});
out('/Contents ' + pageContentsObjId + ' 0 R');
out('>>');
out('endobj'); // Page content
var pageContent = data.join('\n');
newObjectDeferredBegin(pageContentsObjId, true);
putStream({
data: pageContent,
filters: getFilters()
});
out('endobj');
return pageObjectNumber;
};
var putPages = API.__private__.putPages = function () {
var n,
i,
pageObjectNumbers = [];
for (n = 1; n <= page; n++) {
pagesContext[n].objId = newObjectDeferred();
pagesContext[n].contentsObjId = newObjectDeferred();
}
for (n = 1; n <= page; n++) {
pageObjectNumbers.push(putPage({
number: n,
data: pages[n],
objId: pagesContext[n].objId,
contentsObjId: pagesContext[n].contentsObjId,
mediaBox: pagesContext[n].mediaBox,
cropBox: pagesContext[n].cropBox,
bleedBox: pagesContext[n].bleedBox,
trimBox: pagesContext[n].trimBox,
artBox: pagesContext[n].artBox,
userUnit: pagesContext[n].userUnit,
rootDictionaryObjId: rootDictionaryObjId,
resourceDictionaryObjId: resourceDictionaryObjId
}));
}
newObjectDeferredBegin(rootDictionaryObjId, true);
out('<</Type /Pages');
var kids = '/Kids [';
for (i = 0; i < page; i++) {
kids += pageObjectNumbers[i] + ' 0 R ';
}
out(kids + ']');
out('/Count ' + page);
out('>>');
out('endobj');
events.publish('postPutPages');
};
var putFont = function putFont(font) {
events.publish('putFont', {
font: font,
out: out,
newObject: newObject,
putStream: putStream
});
if (font.isAlreadyPutted !== true) {
font.objectNumber = newObject();
out('<<');
out('/Type /Font');
out('/BaseFont /' + font.postScriptName);
out('/Subtype /Type1');
if (typeof font.encoding === 'string') {
out('/Encoding /' + font.encoding);
}
out('/FirstChar 32');
out('/LastChar 255');
out('>>');
out('endobj');
}
};
var putFonts = function putFonts() {
for (var fontKey in fonts) {
if (fonts.hasOwnProperty(fontKey)) {
if (putOnlyUsedFonts === false || putOnlyUsedFonts === true && usedFonts.hasOwnProperty(fontKey)) {
putFont(fonts[fontKey]);
}
}
}
};
var putResourceDictionary = function putResourceDictionary() {
out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
out('/Font <<'); // Do this for each font, the '1' bit is the index of the font
for (var fontKey in fonts) {
if (fonts.hasOwnProperty(fontKey)) {
if (putOnlyUsedFonts === false || putOnlyUsedFonts === true && usedFonts.hasOwnProperty(fontKey)) {
out('/' + fontKey + ' ' + fonts[fontKey].objectNumber + ' 0 R');
}
}
}
out('>>');
out('/XObject <<');
events.publish('putXobjectDict');
out('>>');
};
var putResources = function putResources() {
putFonts();
events.publish('putResources');
newObjectDeferredBegin(resourceDictionaryObjId, true);
out('<<');
putResourceDictionary();
out('>>');
out('endobj');
events.publish('postPutResources');
};
var putAdditionalObjects = function putAdditionalObjects() {
events.publish('putAdditionalObjects');
for (var i = 0; i < additionalObjects.length; i++) {
var obj = additionalObjects[i];
newObjectDeferredBegin(obj.objId, true);
out(obj.content);
out('endobj');
}
events.publish('postPutAdditionalObjects');
};
var addToFontDictionary = function addToFontDictionary(fontKey, fontName, fontStyle) {
// this is mapping structure for quick font key lookup.
// returns the KEY of the font (ex: "F1") for a given
// pair of font name and type (ex: "Arial". "Italic")
if (!fontmap.hasOwnProperty(fontName)) {
fontmap[fontName] = {};
}
fontmap[fontName][fontStyle] = fontKey;
};
var addFont = function addFont(postScriptName, fontName, fontStyle, encoding, isStandardFont) {
isStandardFont = isStandardFont || false;
var fontKey = 'F' + (Object.keys(fonts).length + 1).toString(10),
// This is FontObject
font = {
'id': fontKey,
'postScriptName': postScriptName,
'fontName': fontName,
'fontStyle': fontStyle,
'encoding': encoding,
'isStandardFont': isStandardFont,
'metadata': {}
};
var instance = this;
events.publish('addFont', {
font: font,
instance: instance
});
if (fontKey !== undefined) {
fonts[fontKey] = font;
addToFontDictionary(fontKey, fontName, fontStyle);
}
return fontKey;
};
var addFonts = function addFonts(arrayOfFonts) {
for (var i = 0, l = standardFonts.length; i < l; i++) {
var fontKey = addFont(arrayOfFonts[i][0], arrayOfFonts[i][1], arrayOfFonts[i][2], standardFonts[i][3], true);
usedFonts[fontKey] = true; // adding aliases for standard fonts, this time matching the capitalization
var parts = arrayOfFonts[i][0].split('-');
addToFontDictionary(fontKey, parts[0], parts[1] || '');
}
events.publish('addFonts', {
fonts: fonts,
dictionary: fontmap
});
};
var SAFE = function __safeCall(fn) {
fn.foo = function __safeCallWrapper() {
try {
return fn.apply(this, arguments);
} catch (e) {
var stack = e.stack || '';
if (~stack.indexOf(' at ')) stack = stack.split(" at ")[1];
var m = "Error in function " + stack.split("\n")[0].split('<')[0] + ": " + e.message;
if (global.console) {
global.console.error(m, e);
if (global.alert) alert(m);
} else {
throw new Error(m);
}
}
};
fn.foo.bar = fn;
return fn.foo;
};
var to8bitStream = function to8bitStream(text, flags) {
/**
* PDF 1.3 spec:
* "For text strings encoded in Unicode, the first two bytes must be 254 followed by
* 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
* with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
* to be a meaningful beginning of a word or phrase.) The remainder of the
* string consists of Unicode character codes, according to the UTF-16 encoding
* specified in the Unicode standard, version 2.0. Commonly used Unicode values
* are represented as 2 bytes per character, with the high-order byte appearing first
* in the string."
*
* In other words, if there are chars in a string with char code above 255, we
* recode the string to UCS2 BE - string doubles in length and BOM is prepended.