PageSourceSearch

https://conkana.jp/wp-content/plugins/dflip/assets/js/dflip.js?ver=1.2.61

js conkana.jp collected 2026-09-29 16:28:46 UTC 206,645 bytes, 7,238 lines download raw bytes

1/**
2 * @preserve
3 * Plugin Name: dflip
4 * Description: dflip - 3D & 2D FlipBook
5 *
6 * Author: Deepak Ghimire
7 * Author URI: http://codecanyon.net/user/deip?ref=deip
8 */
9
10'use strict';
11
12var DFLIP = DFLIP || {};
13
14// old fallback
15// use DFLIP instead of PRESENTATION as of v 1.1
16var PRESENTATION = DFLIP;
17
18(function dFlip(DFLIP, $) {
19
20	DFLIP.version = "1.2.61";
21
22	DFLIP.PAGE_MODE = {SINGLE: 1, DOUBLE: 2, AUTO: void 0};
23	DFLIP.DIRECTION = {LTR: 1, RTL: 2};
24
25	DFLIP.CORNERS = {TL: "tl", TR: "tr", BL: "bl", BR: "br", L: "l", R: "r", NONE: void 0};
26
27	DFLIP.SOURCE_TYPE = {IMAGE: "image", PDF: "pdf", HTML: "html"};
28	DFLIP.DISPLAY_TYPE = {WEBGL: "3D", HTML: "2D"};
29	DFLIP.PAGE_SIZE = {AUTO: 0, SINGLE: 1, DOUBLEINTERNAL: 2}
30
31
32
33	//defaults settings
34	var defaults = DFLIP.defaults = {
35
36		//sets if to use 3d or not (true|false)
37		webgl: true,
38
39		// if enable sound at start (true|false)
40		soundEnable: true,
41
42		// height of the container
43		// value(eg: 320) or percentage (eg: '50%')
44		// calculaton limit: minimum 320, max window height
45		height: '100%',
46
47		// set to true to show outline on open (true|false)
48		autoEnableOutline: false,
49
50		// set to true if PDF inbuilt outline is to be removed (true|false)
51		overwritePDFOutline: false,
52
53		// enableDownload of PDF files (true|false)
54		enableDownload: true,
55
56		// duration of page turn in milliseconds
57		duration: 800,
58
59		//direction of flipbook
60		//DFLIP.DIRECTION.LTR or 1	for left to right(default),
61		//DFLIP.DIRECTION.RTL or 2	for right to left,
62		direction: DFLIP.DIRECTION.LTR,
63
64		//set as
65		//DFLIP.PAGE_MODE.AUTO	 	for auto-detect(default),
66		//DFLIP.PAGE_MODE.SINGLE or 1 	for singleview,
67		//DFLIP.PAGE_MODE.DOUBLE or 2 	for doubleview,
68		pageMode: DFLIP.PAGE_MODE.AUTO,
69
70		//color value in hexadecimal
71		backgroundColor: "#777",
72
73		transparent: false, //true or false
74		hard: "none", //possible values are "hard", "none", "cover"
75
76		// texture settings
77		maxTextureSize: 1600,	//max page size to be rendered. for pdf files only
78		minTextureSize: 512,	//min page size to be rendered. for pdf files only
79
80		// icons for the buttons
81		icons: {
82			'altnext': 'ti-angle-right',
83			'altprev': 'ti-angle-left',
84			'next': 'ti-angle-right',
85			'prev': 'ti-angle-left',
86			'end': 'ti-angle-double-right',
87			'start': 'ti-angle-double-left',
88			'share': 'ti-sharethis',
89			'help': 'ti-help-alt',
90			'more': 'ti-more-alt',
91			'download': 'ti-download',
92			'zoomin': 'ti-zoom-in',
93			'zoomout': 'ti-zoom-out',
94			'fullscreen': 'ti-fullscreen',
95			'fitscreen': 'ti-arrows-corner',
96			'thumbnail': 'ti-layout-grid2',
97			'outline': 'ti-menu-alt',
98			'close': 'ti-close',
99			'doublepage': 'ti-book',
100			'singlepage': 'ti-file',
101			'sound': 'ti-volume',
102			'facebook': 'ti-facebook',
103			'google': 'ti-google',
104			'twitter': 'ti-twitter-alt',
105			'mail': 'ti-email'
106		},
107
108		// TRANSLATION text to be displayed
109		text: {
110
111			toggleSound: "Turn on/off Sound",
112			toggleThumbnails: "Toggle Thumbnails",
113			toggleOutline: "Toggle Outline/Bookmark",
114			previousPage: "Previous Page",
115			nextPage: "Next Page",
116			toggleFullscreen: "Toggle Fullscreen",
117			zoomIn: "Zoom In",
118			zoomOut: "Zoom Out",
119			toggleHelp: "Toggle Help",
120
121			singlePageMode: "Single Page Mode",
122			doublePageMode: "Double Page Mode",
123			downloadPDFFile: "Download PDF File",
124			gotoFirstPage: "Goto First Page",
125			gotoLastPage: "Goto Last Page",
126
127			share: "Share"
128		},
129
130		//valid controlnames:
131		//altPrev,pageNumber,altNext,outline,thumbnail,zoomIn,zoomOut,fullScreen,share
132		//more,download,pageMode,startPage,endPage,sound
133		allControls: "altPrev,pageNumber,altNext,outline,thumbnail,zoomIn,zoomOut,fullScreen,share,more,download,pageMode,startPage,endPage,sound",
134		mainControls: "altPrev,pageNumber,altNext,outline,thumbnail,zoomIn,zoomOut,fullScreen,share,more",
135		hideControls: "",
136
137		//set if the zoom changes on mouse scroll (true|false)
138		scrollWheel: true,
139
140		// callbacks
141		onCreate: function () {
142			// after flip book is created is fired
143		},
144		onCreateUI: function () {
145			// after ui created event is fired
146		},
147		onFlip: function () {
148			// after flip event is fired
149		},
150		beforeFlip: function () {
151			// before flip event is fired
152		},
153		onReady: function () {
154			// after flip book is completely loaded
155		},
156
157		zoomRatio: 1.5,
158		pageSize: DFLIP.PAGE_SIZE.AUTO,
159
160		/**
161		 * NON-OPTIONS AREA
162		 * These options are not supposed to be sent from options variable
163		 */
164		/**
165		 * dependency URLS (NON-OPTION):
166		 * Do not set them as options,
167		 * Refer to advance-examples
168		 */
169		//(NON-OPTION) source link for PDF.JS file
170		pdfjsSrc: "js/libs/pdf.min.js",
171		//(NON-OPTION) source link for PDFcompatibility.JS file
172		pdfjsCompatibilitySrc: "js/libs/compatibility.js",
173		//(NON-OPTION) source link for PDF.WORKER.JS file
174		pdfjsWorkerSrc: "js/libs/pdf.worker.min.js",
175		//(NON-OPTION) source link for THREE.JS file
176		threejsSrc: "js/libs/three.min.js",
177		//(NON-OPTION) source link for MOCKUP.JS file
178		mockupjsSrc: "js/libs/mockup.min.js",
179		//(NON-OPTION) File path to the trun sound
180		soundFile: "sound/turn2.mp3",
181
182		//(NON-OPTION) developer parameters
183		enableDebugLog: false,
184		canvasToBlob: true,
185
186
187		/**
188		 * Let them be, change at your risk
189		 */
190		// if texture fallback override is required
191		// note: if set to anything other than "blank" the first page is changed
192		// recommended : "blank"
193		textureLoadFallback: "blank", //"images/textures/white.jpg",
194		// controls the flexibility of the paper more value for more flexiblilty
195		stiffness: 3,
196		minTopOffset: 30,
197		// link to the images file that you want as background.
198		// supported files are jpgs,png. smaller files are preffered for performance
199		backgroundImage: "",//"images/textures/el.jpg",
200		// or any number like 5, 500. recommended: "auto"
201
202		pageRatio: void 0, 		//equals to width/height
203
204		defaultPageRatio: 210 / 297, //internal usage
205	};
206
207	var has3d = 'WebKitCSSMatrix' in window
208			|| (document.body && 'MozPerspective' in document.body.style),
209		hasMouse = 'onmousedown' in window,
210		hasTouch = 'ontouchstart' in window;
211
212	var utils = DFLIP.utils = {
213
214		drag: {
215			left: 0,
216			right: 1,
217			none: -1
218		},
219		mouseEvents: (hasMouse)
220			? {type: "mouse", start: "mousedown", move: "mousemove", end: "mouseup"}
221			: {type: "touch", start: "touchstart", move: "touchmove", end: "touchend"},
222
223		html: {
224			div: "<div/>",
225			img: "<img/>",
226			a: "<a>",
227			input: "<input type='text'/>"
228		},
229		//functions or so
230		toRad: function (deg) {
231			return deg * Math.PI / 180;
232		},
233
234		toDeg: function (rad) {
235			return rad * 180 / Math.PI;
236		},
237
238		transition: function (hasTransition, duration) {
239			return hasTransition ? duration / 1000 + "s ease-out" : "0s none";
240		},
241
242		display: function (hasDisplay) {
243			return hasDisplay ? "block" : "none";
244		},
245
246		resetTranslate: function () {
247			return translateStr(0, 0);
248		},
249
250		translateStr: function (x, y) {
251			return has3d ? ' translate3d(' + x + 'px,' + y + 'px, 0px) ' : ' translate(' + x + 'px, ' + y + 'px) ';
252		},
253
254		resetBoxShadow: function () {
255			return "rgba(0, 0, 0, 0) 0px 0px 20px";
256		},
257
258		rotateStr: function (deg) {
259			return ' rotateZ(' + deg + 'deg) ';
260		},
261
262		bg: function (src) {
263			return '#fff' + bgImage(src);
264		},
265
266		bgImage: function (src) {
267			return (src == void 0 || src == "blank" ? '' : ' url(' + src + ')');
268		},
269
270		src: function (src) {
271			return (src !== void 0 ? '' + src + '' : '');
272		},
273
274		limitAt: function (x, min, max) {
275			return x < min ? min : x > max ? max : x;
276		},
277
278		distOrigin: function (x, y) {
279			return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
280		},
281
282		distPoints: function (x1, y1, x2, y2) {
283			return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
284		},
285
286		angleByDistance: function (distance, fullWidth) {
287			var h = fullWidth / 2;
288			var d = limitAt(distance, 0, fullWidth);
289
290			var angle = d < h
291				? toDeg(Math.asin(d / h))
292				: 90 + toDeg(Math.asin((d - h) / h));
293
294			return angle;
295
296		},
297
298		log: function (args) {
299			if (defaults.enableDebugLog == true && window.console)
300				console.log(args);
301		},
302		lowerPowerOfTwo: function (value) {
303			return Math.pow(2, Math.floor(Math.log(value) / Math.LN2));
304		},
305		nearestPowerOfTwo: function (value) {
306			return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2));
307		},
308
309		extendOptions: function (defaults, options) {
310			return $.extend(true, {}, defaults, options);
311		},
312
313		getBasePage: function (pageNumber) {
314			return Math.floor(pageNumber / 2) * 2;
315		},
316
317		loadResources: function loadResources(resourceTag, src, callback) {
318			var doc = document,
319				element = doc.createElement(resourceTag),
320				refElement = doc.getElementsByTagName(resourceTag)[0];
321
322			element.async = true;
323			if (callback) {
324				element.addEventListener('load', function (e) {
325					callback(null, e);
326				}, false);
327			}
328
329			element.src = src;
330
331			refElement.parentNode.insertBefore(element, refElement);
332		},
333		getScript: function (source, callback, errorCallback) {
334			var script = document.createElement('script');
335			var prior = document.body.getElementsByTagName('script')[0];
336			script.async = 1;
337			script.setAttribute("data-cfasync", false);
338			prior.parentNode.insertBefore(script, prior);
339
340			function load(_, isAbort) {
341				if (script !== void 0) {
342					if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
343						//console.log("aborted loading :" + source);
344						script.onload = script.onreadystatechange = null;
345						script = void 0;
346						if (!isAbort) {
347							if (callback) callback();
348						}
349
350					}
351				}
352			};
353
354			script.addEventListener("load", load, false);
355			script.addEventListener("readystatechange", load, false);
356			script.addEventListener("complete", load, false);
357
358			if (errorCallback) {
359				script.addEventListener("error", errorCallback, false);
360			}
361			//script.onload = script.onreadystatechange = load;
362
363			script.src = source + (prefix.dom == "MS" ? ("?" + Math.random(1)) : "");
364		},
365
366		fixMouseEvent: function (event) {
367
368
369			if (event) {
370				var originalEvent = event.originalEvent || event;
371
372				//noinspection JSUnresolvedVariable
373				if (originalEvent.changedTouches && originalEvent.changedTouches.length > 0) {
374					var _event = $.event.fix(event);
375					//noinspection JSUnresolvedVariable
376					var touch = originalEvent.changedTouches[0];
377					_event.clientX = touch.clientX;
378					_event.clientY = touch.clientY;
379					_event.pageX = touch.pageX;
380					_event.pageY = touch.pageY;
381					_event.movementX = touch.movementX;
382					_event.movementY = touch.movementY;
383					return _event;
384				}
385				else {
386					return event;
387				}
388			}
389			else {
390				return event;
391			}
392
393		},
394
395		//self Execution
396		hasWebgl: (function () {
397			try {
398				var canvas = document.createElement('canvas');
399				//noinspection JSUnresolvedVariable
400				return !!( window.WebGLRenderingContext && ( canvas.getContext('webgl') || canvas.getContext('experimental-webgl') ) );
401			} catch (e) {
402				return false;
403			}
404		})(),
405		isMobile: (function () {
406			var check = false;
407			(function (a) {
408				if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4)))check = true
409			})(navigator.userAgent || navigator.vendor || window.opera);
410			return check;
411		})(),
412		prefix: (function () {
413			var styles = window.getComputedStyle(document.documentElement, ''),
414				pre = (Array.prototype.slice
415					.call(styles)
416					.join('')
417					.match(/-(moz|webkit|ms)-/))[1],
418				dom = ('WebKit|Moz|MS').match(new RegExp('(' + pre + ')', 'i'))[1];
419			return {
420				dom: dom,
421				lowercase: pre,
422				css: '-' + pre + '-',
423				js: pre[0].toUpperCase() + pre.substr(1)
424			};
425		})(),
426
427		__extends: (window && window.__extends) || function (child, parent) {
428			for (var key in parent)
429				if (parent.hasOwnProperty(key)) child[key] = parent[key];
430			function Ctor() {
431				this.constructor = child;
432			}
433
434			Ctor.prototype = parent.prototype;
435			child.prototype = new Ctor();
436			child.__super = parent.prototype;
437			return child;
438		}
439
440	};
441
442	//caching the utils
443
444	var SOURCE_TYPE = DFLIP.SOURCE_TYPE,
445		DISPLAY_TYPE = DFLIP.DISPLAY_TYPE,
446
447		drag = utils.drag,
448		mouseEvents = utils.mouseEvents,
449		html = utils.html,
450
451		toRad = utils.toRad,
452		toDeg = utils.toDeg,
453		transition = utils.transition,
454		translateStr = utils.translateStr,
455		resetBoxShadow = utils.resetBoxShadow,
456		rotateStr = utils.rotateStr,
457
458		bg = utils.bg,
459		bgImage = utils.bgImage,
460		src = utils.src,
461
462		limitAt = utils.limitAt,
463		distOrigin = utils.distOrigin,
464		distPoints = utils.distPoints,
465		angleByDistance = utils.angleByDistance,
466		log = utils.log,
467		nearestPowerOfTwo = utils.nearestPowerOfTwo,
468		extendOptions = utils.extendOptions,
469		getBasePage = utils.getBasePage,
470		getScript = utils.getScript,
471		fixMouseEvent = utils.fixMouseEvent,
472		prefix = utils.prefix,
473		isMobile = utils.isMobile,
474		hasWebgl = utils.hasWebgl,
475		__extends = utils.__extends;
476
477	var extendDFlipOptions = function (options) {
478		return $.extend(true, {}, defaults, options);
479	};
480
481	//Creates ui for the flipbook
482	var createUI = function (container, object) {
483
484		var uiClass = "df-ui";
485		var wrapperClass = "df-ui-wrapper";
486		var buttonClass = uiClass + "-" + "btn";
487		var ui = object.ui = $(html.div, {'class': uiClass});
488		var options = object.options;
489
490		ui.dispose = function () {
491			container.find("." + buttonClass).each(function () {
492				$(this).off();
493			});
494			controls.remove();
495			sizeControls.remove();
496			prev.remove();
497			next.remove();
498			zoom.remove();
499			if (ui.shareBox) {
500				if (ui.shareBox.dispose)
501					ui.shareBox.dispose();
502				ui.shareBox = null;
503			}
504			document.removeEventListener('keyup', onKeyUp, false);
505			window.removeEventListener('click', closeMoreOptions, false);
506			object = null;
507		};
508
509		var validPage = function (pageNumber) {
510
511			if (isNaN(pageNumber)) pageNumber = object.target._activePage;
512			else if (pageNumber < 1) pageNumber = 1;
513			else if (pageNumber > object.target.pageCount) pageNumber = object.target.pageCount;
514			return pageNumber;
515
516		};
517
518		var next = ui.next = $(html.div, {
519
520			class: buttonClass + " " + uiClass + "-next " + options.icons['next'],
521			title: options.text.nextPage,
522			html: "<span>" + options.text.nextPage + "</span>"
523
524		}).on("click", function () {
525			object.next();
526		});
527
528		var prev = ui.prev = $(html.div, {
529
530			class: buttonClass + " " + uiClass + "-prev " + options.icons['prev'],
531			title: options.text.previousPage,
532			html: "<span>" + options.text.previousPage + "</span>"
533
534		}).on("click", function () {
535
536			object.prev();
537
538		});
539
540		var zoom = $(html.div, {
541			class: wrapperClass + " " + uiClass + "-zoom"
542		});
543
544		var zoomIn = ui.zoomIn = $(html.div, {
545
546			class: buttonClass + " " + uiClass + "-zoomin " + options.icons['zoomin'],
547			title: options.text.zoomIn,
548			html: "<span>" + options.text.zoomIn + "</span>"
549
550		}).on("click", function () {
551
552			object.zoom(true);
553			ui.update();
554			if (object.target.startPoint && object.target.pan)
555				object.target.pan(object.target.startPoint);
556
557		});
558
559		var zoomOut = ui.zoomOut = $(html.div, {
560
561			class: buttonClass + " " + uiClass + "-zoomout " + options.icons['zoomout'],
562			title: options.text.zoomOut,
563			html: "<span>" + options.text.zoomOut + "</span>"
564
565		}).on("click", function () {
566			object.zoom(false);
567			ui.update();
568			if (object.target.startPoint && object.target.pan)
569				object.target.pan(object.target.startPoint);
570		});
571		zoom.append(zoomIn).append(zoomOut);
572
573		var page = ui.pageNumber = $(html.div, {
574
575			class: buttonClass + " " + uiClass + "-page",
576
577		}).on("change", function () {
578
579			var pageNumber = parseInt((ui.pageInput.val()), 10);
580
581			pageNumber = validPage(pageNumber);
582			object.gotoPage(pageNumber);
583
584		}).on("keyup", function (event) {
585
586			if (event.keyCode == 13) {
587				var pageNumber = parseInt((ui.pageInput.val()), 10);
588
589				pageNumber = validPage(pageNumber);
590				if (pageNumber !== validPage(object.target._activePage || object._activePage))
591					object.gotoPage(pageNumber);
592			}
593
594		});
595
596		ui.pageInput = $('<input id="df_book_page_number" type="text"/>').appendTo(page);
597		ui.pageLabel = $('<label for="df_book_page_number"/>').appendTo(page);
598
599		var sizeControls = $(html.div, {
600			class: wrapperClass + " " + uiClass + "-size"
601		});
602
603		var help = $(html.div, {
604			class: buttonClass + " " + uiClass + "-help " + options.icons['help'],
605			title: options.text.toggleHelp,
606			html: "<span>" + options.text.toggleHelp + "</span>"
607		}).on("click", function () {
608
609		});
610
611
612		//Sound Button
613		var sound = ui.sound = $(html.div, {
614
615			class: buttonClass + " " + uiClass + "-sound " + options.icons['sound'],
616			title: options.text.toggleSound,
617			html: "<span>" + options.text.toggleSound + "</span>"
618
619		}).on("click", function () {
620
621			options.soundEnable = !options.soundEnable;
622			ui.updateSound();
623
624		});
625
626		//Updates sound on click of sound button
627		ui.updateSound = function () {
628
629			if (options.soundEnable == false || options.soundEnable == 'false')
630				sound.addClass("disabled");
631			else
632				sound.removeClass("disabled");
633
634		};
635
636		//immediate check
637		ui.updateSound();
638
639
640		//More button
641		var more = ui.more = $(html.div, {
642
643			class: buttonClass + " " + uiClass + "-more " + options.icons['more']
644
645		}).on("click", function (event) {
646			if (!more.hasClass("df-active")) {
647				$(this).addClass("df-active");
648				event.stopPropagation();
649			}
650		});
651
652		//closes moreoptions container
653		function closeMoreOptions(event) {
654			more.removeClass("df-active");
655		}
656
657		//register a click event on window to close the moreoptions
658		window.addEventListener('click', closeMoreOptions, false);
659
660		//more container that holds the moreoptions
661		var moreContainer = $(html.div, {
662			class: "more-container"
663		});
664		more.append(moreContainer);
665
666		if (typeof options.source == 'string' && options.enableDownload == true) {
667			var downloadClass = buttonClass + " " + uiClass + "-download " + options.icons['download'];
668			var download = ui.download = $('<a download target="_blank" class="' + downloadClass + '"><span>' + options.text.downloadPDFFile + '</span></a>');
669			download.attr("href", options.source).attr("title", options.text.downloadPDFFile);
670			//moreContainer.append(download);
671		}
672
673		var fullscreenEnabled = document.fullscreenEnabled
674			|| document.mozFullScreenEnabled
675			|| document.webkitFullscreenEnabled
676			|| document.msFullscreenEnabled;
677
678		if(!fullscreenEnabled){
679			container.addClass("df-custom-fullscreen");
680		}
681
682		var fullScreen = ui.fullScreen = $(html.div, {
683
684			class: buttonClass + " " + uiClass + "-fullscreen " + options.icons['fullscreen'],
685			title: options.text.toggleFullscreen,
686			html: "<span>" + options.text.toggleFullscreen + "</span>"
687
688		}).on("click", function () {
689
690			var fullscreenElement = document.fullscreenElement
691				|| document.mozFullScreenElement
692				|| document.webkitFullscreenElement
693				|| document.msFullscreenElement;
694
695
696
697			var container = object.container[0];
698
699			if (ui.isFullscreen != true) {
700
701				object.container.addClass("df-fullscreen");
702				if (container.requestFullscreen) {
703					container.requestFullscreen();
704				} else if (container.msRequestFullscreen) {
705					container.msRequestFullscreen();
706				} else if (container.mozRequestFullScreen) {
707					container.mozRequestFullScreen();
708				} else if (container.webkitRequestFullscreen) {
709					container.webkitRequestFullscreen();
710				}
711
712				ui.isFullscreen = true
713
714			}
715			else {
716
717				object.container.removeClass("df-fullscreen");
718				ui.isFullscreen = false;
719
720				if (document.exitFullscreen) {
721					document.exitFullscreen();
722				} else if (document.msExitFullscreen) {
723					document.msExitFullscreen();
724				} else if (document.mozCancelFullScreen) {
725					document.mozCancelFullScreen();
726				} else if (document.webkitExitFullscreen) {
727					document.webkitExitFullscreen();
728				}
729
730			}
731
732			setTimeout(function () {
733				$(window).trigger("resize");
734			}, 50);
735
736		});
737
738		var fit = ui.fit = $(html.div, {
739
740			class: buttonClass + " " + uiClass + "-fit " + options.icons['fitscreen']
741
742		}).on("click", function () {
743
744			$(this).toggleClass("df-button-fit-active");
745
746		});
747		sizeControls.append(fullScreen);
748
749		var controls = $(html.div, {
750			class: wrapperClass + " " + uiClass + "-controls" // todo : df-abs-h-center"
751		});
752
753		var shareBox = ui.shareBox = new DFLIP.Share(container, options);
754
755		var share = ui.share = $(html.div, {
756
757			class: buttonClass + " " + uiClass + "-share " + options.icons['share'],
758			title: options.text.share,
759			html: "<span>" + options.text.share + "</span>"
760
761		}).on("click", function (event) {
762			if (ui.shareBox.isOpen == true)
763				ui.shareBox.close();
764			else {
765				ui.shareBox.update(object.getURLHash());
766				ui.shareBox.show();
767			}
768		});
769
770		var start = ui.startPage = $(html.div, {
771
772			class: buttonClass + " " + uiClass + "-start " + options.icons['start'],
773			title: options.text.gotoFirstPage,
774			html: "<span>" + options.text.gotoFirstPage + "</span>"
775
776		}).on("click", function () {
777
778			object.start();
779
780		});
781
782
783		var end = ui.endPage = $(html.div, {
784
785			class: buttonClass + " " + uiClass + "-end " + options.icons['end'],
786			title: options.text.gotoLastPage,
787			html: "<span>" + options.text.gotoLastPage + "</span>"
788
789		}).on("click", function () {
790
791			object.end();
792
793		});
794
795		var pageModeButton = ui.pageMode = $(html.div, {
796
797			class: buttonClass + " " + uiClass + "-pagemode " + options.icons['singlepage'],
798			html: "<span>" + options.text.singlePageMode + "</span>"
799
800		}).on("click", function () {
801
802			var el = $(this);
803			object.setPageMode(!el.hasClass(options.icons['doublepage']));
804
805		});
806
807
808		object.setPageMode(object.target.pageMode == DFLIP.PAGE_MODE.SINGLE)
809		//moreContainer.append(pageModeButton).append(start).append(end).append(sound);
810
811		var altPrev = ui.altPrev = $(html.div, {
812
813			class: buttonClass + " " + uiClass + "-prev" + " " + uiClass + "-alt " + options.icons['prev'],
814			title: options.text.previousPage,
815			html: "<span>" + options.text.previousPage + "</span>"
816
817		}).on("click", function () {
818			object.prev();
819		});
820
821		var altNext = ui.altNext = $(html.div, {
822
823			class: buttonClass + " " + uiClass + "-next" + " " + uiClass + "-alt " + options.icons['next'],
824			title: options.text.nextPage,
825			html: "<span>" + options.text.nextPage + "</span>"
826
827		}).on("click", function () {
828			object.next();
829		});
830
831		var thumbnail = ui.thumbnail = $(html.div, {
832
833			class: buttonClass + " " + uiClass + "-thumbnail " + options.icons['thumbnail'],
834			title: options.text.toggleThumbnails,
835			html: "<span>" + options.text.toggleThumbnails + "</span>"
836
837		}).on("click", function () {
838			var $this = $(this);
839			if (object.target.thumbContainer) {
840				var thumbContainer = object.target.thumbContainer;
841				thumbContainer.toggleClass("df-thumb-visible");
842				$this.toggleClass("df-active");
843			}
844			else {
845				object.contentProvider.initThumbs();
846				$this.toggleClass("df-active");
847			}
848			if ($this.hasClass("df-active")) {
849				$this.siblings(".df-active").trigger("click");
850			}
851			ui.update(true);
852		});
853
854		var outline = ui.outline = $(html.div, {
855
856			class: buttonClass + " " + uiClass + "-outline " + options.icons['outline'],
857			title: options.text.toggleOutline,
858			html: "<span>" + options.text.toggleOutline + "</span>"
859
860		}).on("click", function () {
861			var $this = $(this);
862			if (object.target.outlineContainer) {
863				var outlineContainer = object.target.outlineContainer;
864				$this.toggleClass("df-active");
865				outlineContainer.toggleClass("df-outline-visible");
866				if ($this.hasClass("df-active")) {
867					$this.siblings(".df-active").trigger("click");
868				}
869				ui.update(true);
870			}
871		});
872
873		/**
874		 * Controls position and pplace ment is determined by options.maincrontrols and options.hidecontrols
875		 */
876		var allControls = options.allControls.replace(/ /g, '').split(','),
877			mainControls = "," + options.mainControls.replace(/ /g, '') + ",",
878			hideControls = "," + options.hideControls.replace(/ /g, '') + ",";
879
880		//if controls name is available in morecontrols it will be added into maincontrols else it will be added to morecontrols. if added in hide it will not be added in any
881		for (var controlCount = 0; controlCount < allControls.length; controlCount++) {
882			//if hidden skip
883			var controlName = allControls[controlCount];
884			if (hideControls.indexOf("," + controlName + ",") < 0) {
885				var control = ui[controlName];
886				if (control !== void 0) {
887					if (mainControls.indexOf("," + controlName + ",") > -1)
888						controls.append(control);
889					else if (controlName !== 'more' && controlName !== 'pageNumber')
890						moreContainer.append(control);
891				}
892			}
893		}
894
895		container.append(controls).append(prev).append(next).append(zoom);
896
897		//container.append(ui);
898
899		var ctrlDown = false, shiftDown = false, altDown = false;
900		var shiftKey = 16, ctrlKey = 17, altKey = 18, sKey = 83, vKey = 86, cKey = 67, eKey = 69, gKey = 71, nKey = 78, oKey = 79, deleteKey = 46, rightKey = 39, leftKey = 37;
901
902		document.addEventListener('keyup', onKeyUp, false);
903
904		function onKeyUp(event) {
905			switch (event.keyCode) {
906				case shiftKey:
907					shiftDown = false;
908					break;
909				case ctrlKey:
910					ctrlDown = false;
911					break;
912				case altKey:
913					altDown = false;
914					break;
915				case leftKey:
916					object.prev();
917					break;
918				case rightKey:
919					object.next();
920					break;
921				default:
922					break;
923			}
924			//log(event.keyCode);
925		}
926
927		ui.update = function (resize) {
928			log("ui update");
929			var target = object.target;
930
931			var pageNumber = validPage(target._activePage || object._activePage);
932			var pageCount = target.pageCount || object.pageCount;
933
934			var isRTL = target.direction == DFLIP.DIRECTION.RTL,
935				isStart = (pageNumber == 1 || pageNumber == 0),
936				isEnd = pageNumber == pageCount;
937
938			ui.next.show();
939			ui.prev.show();
940			ui.altNext.removeClass("disabled");
941			ui.altPrev.removeClass("disabled");
942
943			if ((isStart && !isRTL) || (isEnd && isRTL)) {
944				ui.prev.hide();
945				ui.altPrev.addClass("disabled");
946			}
947			if ((isEnd && !isRTL) || (isStart && isRTL)) {
948				ui.next.hide();
949				ui.altNext.addClass("disabled");
950			}
951
952			ui.pageInput.val(pageNumber);
953			ui.pageLabel.html((pageNumber) + "/" + pageCount);
954
955
956			if (container.find(".df-thumb-visible, .df-outline-visible").length > 0) {
957				container.addClass("df-sidemenu-open");
958			}
959			else {
960				container.removeClass("df-sidemenu-open");
961			}
962			if (resize == true)
963				object.resize();
964
965			if (target.contentProvider.zoomScale == target.contentProvider.maxZoom) {
966				ui.zoomIn.addClass("disabled");
967			}
968			else {
969				ui.zoomIn.removeClass("disabled");
970			}
971
972			if (target.contentProvider.zoomScale == 1) {
973				ui.zoomOut.addClass("disabled");
974			}
975			else {
976				ui.zoomOut.removeClass("disabled");
977			}
978
979		};
980
981		if (object.target !== void 0) {
982			object.target.ui = ui;
983		}
984
985		if (options.onCreateUI !== void 0)
986			options.onCreateUI();
987	};
988
989	var PreviewStage = void 0;
990	//later updated via RegisterMockupObjects in case 3d is requested
991
992	//Registers necessary mockup object when required
993	function RegisterMockupObjects() {
994
995		PreviewStage = (function (_super) {
996			__extends(PreviewStage, _super);
997			function PreviewStage(parameters) {
998				parameters = parameters || {};
999				var _this = this;
1000				_super.call(this, parameters);
1001				_this.options = parameters;
1002				_this.canvas = $(_this.renderer.domElement).addClass("df-3dcanvas");
1003				_this.container = parameters.container;
1004				_this.container.append(_this.canvas);
1005				//_this.container.height(parameters.height);
1006				_this.type = "PreviewStage";
1007				_this.mouse = new THREE.Vector2();
1008				_this.raycaster = new THREE.Raycaster();
1009
1010				_this.camera.position.set(0, 20, 600);
1011				_this.camera.lookAt(new THREE.Vector3(0, 0, 0));
1012
1013				_this.spotLight.position.set(-100, 200, 400);
1014
1015				_this.spotLight.castShadow = !isMobile;
1016				//_this.spotLight.shadowDarkness = 0.6;
1017				_this.spotLight.shadow.bias = -0.0008;
1018
1019				_this.spotLight.intensity = 0.2;
1020				_this.ambientLight.color = new THREE.Color("#888");
1021				_this.ambientLight.intensity = 1.45;
1022
1023				var material = new THREE.ShadowMaterial();
1024				material.opacity = 0.15;
1025
1026				_this.ground.material = material;
1027				_this.ground.position.z = -3;
1028
1029				_this.orbitControl.maxAzimuthAngle = 0.4;
1030				_this.orbitControl.minAzimuthAngle = -0.4;
1031				_this.orbitControl.minPolarAngle = 1.4;
1032				_this.orbitControl.maxPolarAngle = 2.2;
1033
1034				//_this.orbitControl.maxPolarAngle = 10;
1035				_this.orbitControl.mouseButtons.ORBIT = THREE.MOUSE.RIGHT;
1036				_this.orbitControl.mouseButtons.PAN = -1;
1037				_this.orbitControl.maxDistance = 5000;
1038				_this.orbitControl.minDistance = 50;
1039				_this.orbitControl.noZoom = true;
1040
1041				_this.selectiveRendering = true;
1042
1043				_this.orbitControl.zoomSpeed = 5;
1044
1045				_this.orbitControl.keyPanSpeed = 0;
1046				_this.orbitControl.center.set(0, 0, 0);
1047				_this.orbitControl.update();
1048
1049				_this.swipe_threshold = isMobile ? 15 : 20;
1050
1051				var cssRenderer = _this.cssRenderer = new THREE.CSS3DRenderer();
1052				$(cssRenderer.domElement).css({
1053					position: "absolute",
1054					top: 0,
1055					pointerEvents: "none"
1056				}).addClass("df-3dcanvas");
1057				_this.container[0].appendChild(cssRenderer.domElement);
1058
1059				var cssScene = _this.cssScene = new THREE.Scene();
1060
1061				var divLeftDOM = document.createElement("div");
1062				var divRightDOM = document.createElement("div");
1063				var divLeft = cssScene.divLeft = new THREE.CSS3DObject(divLeftDOM);
1064				var divRight = cssScene.divRight = new THREE.CSS3DObject(divRightDOM);
1065				cssScene.add(divLeft);
1066				cssScene.add(divRight);
1067
1068				_this.resizeCallback = function () {
1069					cssRenderer.setSize(_this.canvas.width(), _this.canvas.height());
1070				};
1071
1072				function requestRender() {
1073					_this.renderRequestPending = true;
1074				}
1075
1076				window.addEventListener(mouseEvents.move, requestRender, false);
1077
1078				window.addEventListener('keyup', requestRender, false);
1079
1080
1081				_this.dispose = function () {
1082
1083					_this.clearChild();
1084					_this.render();
1085
1086					window.removeEventListener(mouseEvents.move, requestRender, false);
1087
1088					if (_this.options.scrollWheel == true) {
1089						_this.renderer.domElement.removeEventListener('mousewheel', onMouseWheel, false);
1090						_this.renderer.domElement.removeEventListener('DOMMouseScroll', onMouseWheel, false); // firefox
1091					}
1092
1093					window.removeEventListener('keyup', requestRender, false);
1094
1095					_this.renderer.domElement.removeEventListener("mousemove", editor_mouseMove, false);
1096					_this.renderer.domElement.removeEventListener("touchmove", editor_mouseMove, false);
1097
1098					_this.renderer.domElement.removeEventListener("mousedown", editor_mouseDown, false);
1099					_this.renderer.domElement.removeEventListener("touchstart", editor_mouseDown, false);
1100					_this.renderer.domElement.removeEventListener("mouseup", editor_mouseUp, false);
1101					_this.renderer.domElement.removeEventListener("touchend", editor_mouseUp, false);
1102
1103
1104					_this.canvas.remove();
1105					cssRenderer.domElement.remove();
1106
1107					_this.renderCallback = null;
1108					_this.orbitControl.dispose();
1109
1110					_this.renderer.dispose();
1111
1112					_this.cancelRAF();
1113				};
1114
1115				_this.renderCallback = function () {
1116					if (TWEEN.getAll().length > 0)
1117						_this.renderRequestPending = true;
1118					TWEEN.update();
1119					cssRenderer.render(cssScene, _this.camera)
1120				};
1121
1122				var onMouseWheel = function (event) {
1123					var delta = 0;
1124
1125					if (event.wheelDelta !== void 0) { // WebKit / Opera / Explorer 9
1126
1127						delta = event.wheelDelta;
1128
1129					} else if (event.detail !== void 0) { // Firefox
1130
1131						delta = -event.detail;
1132
1133					}
1134					if (delta) {
1135						var currentZoom = _this.previewObject.contentProvider.zoomScale;
1136						if ((delta > 0 && currentZoom == 1)
1137							|| (delta < 0 && currentZoom > 1)) {
1138							event.preventDefault();
1139						}
1140						_this.previewObject.zoom(delta > 0);
1141					}
1142
1143					requestRender();
1144				};
1145
1146				var editor_mouseMove = function (event) {
1147
1148					_this.renderRequestPending = true;
1149					event = fixMouseEvent(event);
1150					if (_this.isMouseDown && event.movementX != 0 && event.movementY != 0) {
1151						_this.isMouseMoving = true;
1152					}
1153					if (_this.isMouseDown == true && _this.previewObject.contentProvider.zoomScale == 1) {
1154						//check if swipe has happened
1155
1156						var swipe_dist = event.pageX - _this.lastPos,
1157							swipe_time = performance.now() - _this.lastTime;
1158
1159						//$("body > p").html(swipe_dist);
1160
1161						if (Math.abs(swipe_dist) > _this.swipe_threshold) {
1162							//swipe has triggered
1163							//_this.dragPage.pendingPoint = point;
1164							if (swipe_dist < 0) {
1165								_this.target.next();
1166							}
1167							else {
1168								_this.target.prev();
1169							}
1170							event.preventDefault();
1171							_this.isMouseDown = false;
1172						}
1173						_this.lastPos = event.pageX;
1174						_this.lastTime = performance.now();
1175
1176					}
1177				};
1178
1179				var editor_mouseDown = function (event) {
1180					event = fixMouseEvent(event);
1181					document.activeElement.blur();
1182					_this.mouseValue = event.pageX + "," + event.pageY;
1183					_this.isMouseMoving = false;
1184					_this.isMouseDown = true;
1185					_this.lastPos = event.pageX;
1186					_this.lastTime = performance.now();
1187				};
1188
1189				var editor_click = function (event) {
1190					_this.isMouseDown = false;
1191					//bail out if it's not left click
1192					if (event.button !== 0) return this;
1193					var mouseValue = event.pageX + "," + event.pageY;
1194
1195					if (_this.isMouseMoving) {
1196
1197					}
1198					else if (mouseValue == _this.mouseValue) {
1199						event = event || window.event;
1200						event = $.event.fix(event);
1201
1202						var mouse = _this.mouse, raycaster = _this.raycaster;
1203						mouse.x = ( (event.offsetX) / _this.canvas.innerWidth() ) * 2 - 1;
1204						mouse.y = 1 - ( (event.offsetY ) / _this.canvas.innerHeight() ) * 2;
1205
1206						raycaster.setFromCamera(mouse, _this.camera);
1207
1208						var intersects = raycaster.intersectObjects(_this.target instanceof MOCKUP.Bundle
1209							? _this.target.children : [_this.target], true);
1210
1211						if (intersects.length > 0) {
1212
1213							var object, objectCount = 0;
1214							do {
1215								object = intersects[objectCount] !== void 0 ? intersects[objectCount].object : void 0;
1216								//bookStage.clickFace = intersects[objectCount].face;
1217								objectCount++;
1218							} while ((object instanceof THREE.BoxHelper || !(object instanceof MOCKUP.Paper) || object.isFlipping == true) && objectCount < intersects.length);
1219
1220							//if (object.parent instanceof  MOCKUP.Bundle) {
1221							//    object = object.parent;
1222							//}
1223
1224							if (object.userData.object !== void 0) {
1225
1226								// helper
1227
1228								//bookStage.selectObject(object.userData.object);
1229
1230							} else {
1231
1232								if (object.angles[1] > 90) {
1233									if (object.isEdge != true) _this.target.next();
1234								}
1235								else {
1236									if (object.isEdge != true) _this.target.prev();
1237								}
1238
1239							}
1240
1241						} else {
1242
1243							//bookStage.selectObject(null);
1244
1245						}
1246					}
1247					//bookStage.stage.render();
1248				};
1249
1250				var editor_mouseUp = function (event) {
1251					event = fixMouseEvent(event);
1252					editor_click(event);
1253				};
1254				//if (MOCKUP.mode !== MOCKUP.MODE.PLUGIN) {
1255
1256				//_this.renderer.domElement.addEventListener('click', editor_click, false);
1257				//bookStage.renderer.domElement.addEventListener('dblclick', editor_dblclick, false);
1258				_this.renderer.domElement.addEventListener("mousemove", editor_mouseMove, false);
1259				_this.renderer.domElement.addEventListener("touchmove", editor_mouseMove, false);
1260
1261				_this.renderer.domElement.addEventListener("mousedown", editor_mouseDown, false);
1262				_this.renderer.domElement.addEventListener("touchstart", editor_mouseDown, false);
1263				_this.renderer.domElement.addEventListener("mouseup", editor_mouseUp, false);
1264				_this.renderer.domElement.addEventListener("touchend", editor_mouseUp, false);
1265				if (_this.options.scrollWheel == true) {
1266					_this.renderer.domElement.addEventListener('mousewheel', onMouseWheel, false);
1267					_this.renderer.domElement.addEventListener('DOMMouseScroll', onMouseWheel, false); // firefox
1268				}
1269
1270				//}
1271
1272				$(_this.renderer.domElement).css({display: "block"});
1273
1274				$(window).trigger("resize");
1275
1276				return this;
1277			}
1278
1279			PreviewStage.prototype.width = function () {
1280				return this.container.width();
1281			};
1282
1283			PreviewStage.prototype.height = function () {
1284				return this.container.height();
1285			};
1286
1287			return PreviewStage;
1288
1289		})(MOCKUP.Stage);
1290		MOCKUP.PreviewStage = PreviewStage;
1291
1292		var BookPaper = (function (_super) {
1293			__extends(BookPaper, _super);
1294			function BookPaper(parameters, stage) {
1295				parameters = parameters || {};
1296				parameters.folds = 1;
1297				_super.call(this, parameters, stage);
1298				this.angle = 0;
1299				this.isFlipping = false;
1300				this.type = "BookPaper";
1301			}
1302
1303			BookPaper.prototype.tween = function (oldAngle, newAngle) {
1304				var page = this;
1305				var epsilon = 0.00001;
1306				page.originalStiff = page.stiffness;
1307				var oldTarget = page.newStiffness;
1308				//console.log(page.stiffness);
1309				var diff = newAngle - oldAngle;//170 -5 == 165 :  5-170 = -165
1310
1311
1312				page.init = {angle: oldAngle, angle2: (oldAngle < 90 ? 0 : 180), stiff: page.originalStiff};
1313				page.first = {angle: oldAngle + diff / 4, angle2: (oldAngle < 90 ? 90 : 90), stiff: page.originalStiff};
1314				page.mid = {
1315					angle: oldAngle + diff * 2 / 4,
1316					angle2: (oldAngle < 90 ? 135 : 45),
1317					stiff: page.newStiffness
1318				};
1319				page.mid2 = {
1320					angle: oldAngle + diff * 3 / 4,
1321					angle2: (oldAngle < 90 ? 180 : 0),
1322					stiff: page.newStiffness
1323				};
1324				page.end = {angle: newAngle, angle2: (oldAngle < 90 ? 180 : 0), stiff: page.newStiffness};
1325
1326				//console.log(page.init, page.first, page.mid, page.end);
1327				page.isFlipping = true;
1328
1329				var update = function (tween, event) {
1330
1331					page.angles[1] = tween.angle;
1332					page.angles[4] = tween.angle2;
1333					page.stiffness = tween.stiff / (oldTarget + epsilon) * (page.newStiffness + epsilon);
1334					page.stiffness = isNaN(page.stiffness) ? 0 : tween.stiff;
1335					//check if any sibling is flipping and their stiff is more that this
1336
1337					page.updateAngle(true);
1338
1339				};
1340
1341				new TWEEN.Tween(page.init)
1342					.to({
1343						angle: [page.first.angle, page.mid.angle, page.mid2.angle, page.end.angle],
1344						angle2: [page.first.angle2, page.mid.angle2, page.mid2.angle2, page.end.angle2],
1345						stiff: [page.first.stiff, page.mid.stiff, page.mid2.stiff, page.end.stiff]
1346					}, page.parent.duration)
1347					.onUpdate(function (event) {
1348						update(this, event);
1349					}).easing(TWEEN.Easing.Sinusoidal.Out)
1350					.onComplete(function (event) {
1351						page.stiffness = page.newStiffness;
1352						page.updateAngle();
1353						page.isFlipping = false;
1354						if (page.parent && page.parent.refresh)
1355							page.parent.refresh();
1356						//console.log(page.stiffness);
1357					}).start();
1358
1359			};
1360
1361			return BookPaper;
1362		})(MOCKUP.FlexBoxPaper);
1363		MOCKUP.BookPaper = BookPaper;
1364
1365		var Book = (function (_super) {
1366			__extends(Book, _super);
1367
1368			function Book(parameters, stage) {
1369
1370				parameters = parameters || {};
1371				parameters.segments = parameters.segments || 50;
1372				this.pageCount = parameters.pageCount;
1373
1374				this.height = parameters.height;
1375				this.width = parameters.width;
1376
1377				//correcting page count as multiple of 2
1378				//this.pageCount = Math.ceil(this.pageCount / 2) * 2;
1379				this.pageCount = (this.pageCount == 1 ? this.pageCount : Math.ceil(this.pageCount / 2) * 2);
1380
1381				this.direction = parameters.direction || DFLIP.DIRECTION.LTR;
1382
1383				this.startPage = 1;
1384				this.endPage = this.pageCount;
1385
1386				this.stackCount = parameters.stackCount || 6;// = 15;
1387				this.materials = [];
1388				//_super.call(this);
1389				_super.call(this, parameters, stage);
1390				this.angles = [0, 0, 0, 0, 0, 0];
1391				this.stiffness = parameters.stiffness || 1.5;
1392				this._activePage = parameters.openPage || this.startPage;
1393
1394				this.createStack(parameters);
1395				this.pageMode = parameters.pageMode || ((isMobile || this.pageCount <= 2) ? DFLIP.PAGE_MODE.SINGLE
1396					: DFLIP.PAGE_MODE.DOUBLE);
1397				//this.createCover(parameters);
1398				//this.updateAngle();
1399				//this.updatePage(this._activePage);
1400				this.type = "Book";
1401
1402			}
1403
1404			Book.prototype.getPageByNumber = function (pageNumber) {
1405				return this.getObjectByName(Math.floor((pageNumber - 1) / 2).toString());
1406			};
1407
1408			Book.prototype.activePage = function (pageNumber) {
1409				if (pageNumber == void 0) return this._activePage;
1410				this.gotoPage(pageNumber);
1411			};
1412
1413			Book.prototype.gotoPage = function (pageNumber) {
1414				pageNumber = parseInt(pageNumber, 10);
1415				this._activePage = pageNumber;
1416				this.updatePage(pageNumber);
1417			};
1418
1419
1420			Book.prototype.moveBy = function (step) {
1421				var nextPage = this._activePage + step;
1422
1423				nextPage = limitAt(nextPage, this.startPage, this.endPage);
1424
1425				this.gotoPage(nextPage);
1426			};
1427
1428			Book.prototype.next = function (step) {
1429				if (step == void 0)
1430					step =
1431						(this.direction == DFLIP.DIRECTION.RTL)
1432							? -this.pageMode : this.pageMode;
1433
1434				this.moveBy(step);
1435			};
1436
1437			Book.prototype.prev = function (step) {
1438				if (step == void 0)
1439					step =
1440						(this.direction == DFLIP.DIRECTION.RTL)
1441							? this.pageMode : -this.pageMode;
1442
1443				this.moveBy(step);
1444			};
1445
1446			Book.prototype.updateAngle = function () {
1447
1448				var startAngle = this.angles[1];
1449				var endAngle = this.angles[4];
1450
1451
1452				var spreadAngle = endAngle - startAngle;
1453				var stacks = this.stackCount;
1454
1455				for (var _stackCount = 0; _stackCount < stacks; _stackCount++) {
1456					var clone = this.children[_stackCount];
1457					//start from angle[1] and end at angles[4]
1458					clone.angles[1] = startAngle + _stackCount * spreadAngle / (stacks * 100);
1459					clone.stiffness = this.stiffness;//_stackCount/stacks;
1460					clone.updateAngle();
1461					//clone.position.z = 0;//-_stackCount/100;
1462				}
1463
1464				/*            var cover = this.cover;
1465				 cover.angles[1] = this.angles[1];
1466				 cover.angles[4] = this.angles[4];
1467				 cover.stiffness = this.stiffness;
1468				 cover.updateAngle();*/
1469
1470			};
1471
1472			Book.prototype.refresh = function () {
1473				this.updatePage(this._activePage);
1474				if (this.flipCallback !== void 0) this.flipCallback();
1475			};
1476
1477
1478			Book.prototype.updatePage = function (pageNumber) {
1479
1480				var isRTL = (this.direction == DFLIP.DIRECTION.RTL);
1481
1482				pageNumber = Math.floor((pageNumber / 2));
1483
1484				if (isRTL) pageNumber = Math.floor(this.pageCount / 2) - pageNumber;
1485
1486				var oldBaseNumber = this.oldBaseNumber || 0;
1487				var pageCount = this.pageCount / 2;
1488				var stackCount = this.stackCount;
1489				var angleShift = 0.02;
1490				var depth = 0.4;
1491				var stiffFactor = (0.5 - Math.abs(pageCount / 2 - pageNumber) / pageCount) / this.stiffness;
1492				var positionFactor = 1;//(stiffFactor +width);
1493				var centre = Math.floor(stackCount / 2);
1494				var midPoint = centre;//pageNumber < centre ? pageNumber //starting center pages
1495				// : ((pageCount - pageNumber > centre) ? centre //other pages
1496				//: (pageNumber + centre - pageCount)) ;//remainig center page
1497				//console.log(midPoint);
1498
1499				//var targetIndex = midPoint;
1500				//if(midPoint == centre) {
1501				/*This sitaution is good when there is icrement or decrement by 1*/
1502				var isLeft = false;
1503				if (oldBaseNumber > pageNumber) {
1504					isLeft = true;
1505					this.children[stackCount - 1].skipFlip = true;
1506					//this.children[midPoint].isFlipping = false;
1507					this.children.unshift(this.children.pop());
1508					//midPoint = centre;
1509					//this.children[midPoint].isFlipping = false;
1510				}
1511				else if (oldBaseNumber < pageNumber) {
1512					this.children[0].skipFlip = true;
1513					//this.children[midPoint-1].isFlipping = false;
1514					this.children.push(this.children.shift());
1515					//midPoint =centre -1;
1516					//this.children[midPoint].isFlipping = false;
1517				}
1518				else {
1519					//midPoint = centre;
1520				}
1521				if (Math.abs(oldBaseNumber - pageNumber) > 1) {
1522
1523				}
1524				//}
1525				var remainingPages = (pageCount - pageNumber);
1526				var stackDepth = (5) / pageCount;
1527				var leftDepth = stackDepth * pageNumber / 2;
1528				var rightDepth = stackDepth * remainingPages / 2;
1529				var maxDepth = (leftDepth < rightDepth ? rightDepth : leftDepth);
1530				//maxDepth = maxDepth > 5 ? 5: maxDepth;
1531				for (var _pageCount = 0; _pageCount < stackCount; _pageCount++) {
1532					var page = this.children[_pageCount];//this.getObjectByName("page"+_pageCount);//this.children[_pageCount];
1533
1534					var color = page.color;
1535					var oldAngle = page.angles[1];
1536					var newAngle;
1537					var relativePageNumber = pageNumber - midPoint + _pageCount;
1538
1539					var oldName = page.name;
1540
1541					page.visible = (relativePageNumber >= 0 && relativePageNumber < pageCount);
1542					if (this.requestPage !== void 0) {
1543
1544						if (isRTL) relativePageNumber = Math.floor(this.pageCount / 2) - relativePageNumber - 1;
1545
1546						page.name = relativePageNumber.toString();
1547						if (page.name != oldName && page.visible == true) {
1548							page.textureLoaded = false;
1549							page.backTextureLoaded = false;
1550							page.frontTextureLoaded = false;
1551							page.thumbLoaded = false;
1552							this.requestPage(relativePageNumber * 2 + 1);
1553							this.requestPage(relativePageNumber * 2 + 2);
1554						}
1555					}
1556					//Sizing
1557					page.isEdge = false; //true;
1558					if (_pageCount == 0) {
1559						page.depth = leftDepth < depth ? depth : leftDepth;
1560					}
1561					else if (_pageCount == stackCount - 1) {
1562						page.depth = rightDepth < depth ? depth : rightDepth;
1563					}
1564					else {
1565						page.depth = depth;
1566						page.isEdge = false;
1567					}
1568					if (page.isFlipping == true) {
1569						page.depth = depth;
1570					}
1571					page.position.x = 0;
1572
1573					var leftAngle = angleShift * _pageCount,
1574						rightAngle = 180 - angleShift * (_pageCount - midPoint) + angleShift * _pageCount;
1575
1576					if (_pageCount < midPoint) {
1577						page.newStiffness = stiffFactor / (pageNumber / pageCount) / 4;
1578						newAngle = leftAngle;
1579						page.position.z = maxDepth - ( -_pageCount + midPoint) * depth;//(pageNumber < pageCount / 2)
1580						if (isLeft == true) page.position.z -= depth;
1581
1582					}
1583					else {
1584						newAngle = rightAngle;
1585						page.newStiffness = stiffFactor / (Math.abs(pageCount - pageNumber) / pageCount) / 4;
1586						page.position.z = (maxDepth - (-stackCount + _pageCount + midPoint + 1) * depth) - page.depth;//(pageNumber < pageCount / 2)
1587
1588					}
1589
1590					if (page.isFlipping == false) {
1591
1592						if (Math.abs(oldAngle - newAngle) > 20 && page.skipFlip == false) {
1593							page.depth = depth;
1594							//we need predicted stiffness so that there is no overlap issues
1595							var predicted = page.stiffness;
1596
1597							if (oldAngle > newAngle) {//left
1598								predicted = stiffFactor / (Math.abs(pageCount - pageNumber) / pageCount) / 4;
1599							}
1600							else {//right
1601								predicted = stiffFactor / (pageNumber / pageCount) / 4;
1602							}
1603							page.position.z += depth;//((_pageCount < midPoint) ? 0 : depth) * 2;/// 2;
1604
1605							page.stiffness = isNaN(predicted) ? page.stiffness : predicted;
1606							page.updateAngle(true);
1607							page.targetStiffness = (_pageCount < pageNumber)
1608								? stiffFactor / (Math.abs(pageCount - pageNumber) / pageCount) / 4
1609								: stiffFactor / (pageNumber / pageCount) / 4;
1610
1611							page.targetStiffness = isNaN(page.targetStiffness) ? page.stiffness : page.targetStiffness;
1612
1613							page.isFlipping = true;
1614
1615							page.tween(oldAngle, newAngle);
1616
1617							if (this.preFlipCallback !== void 0)
1618								this.preFlipCallback();
1619						} else {
1620							page.skipFlip = false;
1621							page.newStiffness = isNaN(page.newStiffness) ? 0 : page.newStiffness;
1622							if (page.angles[1] != newAngle || page.stiffness != page.newStiffness || page.depth != page.oldDepth) {
1623								page.angles[1] = page.angles[4] = newAngle;
1624								page.stiffness = page.newStiffness;
1625								page.updateAngle(true);
1626							}
1627							else {
1628								//console.log("skipped");
1629							}
1630						}
1631					}
1632
1633					page.oldDepth = page.depth;
1634					var xPos = Math.abs(page.geometry.boundingBox.max.x) < Math.abs(page.geometry.boundingBox.min.x)
1635						? page.geometry.boundingBox.max.x : page.geometry.boundingBox.min.x;
1636					page.position.x = (page.isEdge == true && page.isFlipping == false ) ? ((_pageCount < midPoint)
1637						? xPos : -xPos) : 0;
1638				}
1639				//$(".quick-hint").html(pageNumber);
1640				//console.log("leftDepth:" + leftDepth, "rightDepth:" + rightDepth, "midPoint:" + midPoint, "oldBaseNumber:" + oldBaseNumber, "pageNumber:" + pageNumber);
1641				this.oldBaseNumber = pageNumber;
1642
1643				if (this.updatePageCallback !== void 0)
1644					this.updatePageCallback();
1645
1646			};
1647			//if (window.flipBook != void 0)flipBook.book.refresh();
1648			//book.activePage(book.activePage());
1649			Book.prototype.createCover = function (parameters) {
1650				parameters.width = parameters.width * 2;
1651				this.cover = new MOCKUP.BiFold(parameters);
1652				this.add(this.cover);
1653			};
1654
1655			Book.prototype.createStack = function (parameters) {
1656
1657				var colors = "red,green,blue,yellow,orange,black".split(",");
1658
1659				for (var _stackCount = 0; _stackCount < this.stackCount; _stackCount++) {
1660					parameters.angles = [, this.stackCount - _stackCount];//[1] = (this.stackCount - _stackCount);
1661					parameters.stiffness = (this.stackCount - _stackCount) / 100;
1662
1663					var clone = new MOCKUP.BookPaper(parameters);
1664					clone.angles[1] = 180;
1665					//clone.name = "page" + _stackCount;
1666					clone.index = _stackCount;
1667					clone.updateAngle();
1668					clone.textureReady = false;
1669					clone.textureRequested = false;
1670					this.add(clone);
1671					clone.color = colors[_stackCount];
1672					//for (var _count = 0; _count < 4; _count++) {
1673					//    clone.material.materials[_count].color = new THREE.Color(THREE.ColorKeywords[colors[_stackCount]]);
1674					//}
1675					clone.position.z = -1 * _stackCount;// * (this.mainObject.depth * 1.05);
1676				}
1677			};
1678
1679
1680			Book.prototype.shininess = function (shininess) {
1681				if (shininess == void 0) {
1682					return this.mainObject.shininess();
1683				}
1684				else {
1685					this.mainObject.shininess(shininess);
1686				}
1687			};
1688
1689			Book.prototype.bumpScale = function (bumpScale) {
1690				if (bumpScale == void 0) {
1691					return this.mainObject.bumpScale();
1692				}
1693				else {
1694					this.mainObject.bumpScale(bumpScale);
1695				}
1696			};
1697
1698
1699			Book.prototype.frontImage = function (frontImage) {
1700				if (frontImage == void 0) {
1701					return this.mainObject.frontImage();
1702				}
1703				else {
1704					this.mainObject.frontImage(frontImage);
1705				}
1706			};
1707
1708
1709			Book.prototype.backImage = function (backImage) {
1710				if (backImage == void 0) {
1711					return this.mainObject.backImage();
1712				}
1713				else {
1714					this.mainObject.backImage(backImage);
1715				}
1716			};
1717
1718			return Book;
1719		})(MOCKUP.Bundle);
1720		MOCKUP.Book = Book;
1721
1722	}
1723
1724	//base object of flipbook or other trifold objects
1725	var PreviewObject = (function (_super) {
1726
1727		function PreviewObject(parameters) {
1728			parameters = parameters || {};
1729			//_super.call(this, parameters);
1730			this.type = "PreviewObject";
1731			var _this = this;
1732
1733			function resizeDelay() {
1734				setTimeout(function () {
1735					_this.resize()
1736				}, 50);
1737			}
1738
1739			window.addEventListener("resize", resizeDelay, false);
1740
1741			this.sound = document.createElement("audio");
1742			this.sound.setAttribute("src", parameters.soundFile + "?ver=" + DFLIP.version);
1743			this.sound.setAttribute("type", "audio/mpeg");
1744
1745			//this.pageMode = DFLIP.PAGE_MODE.DOUBLE;
1746			this.dispose = function () {
1747
1748				if (this.container && this.container.info && this.container.info.remove)
1749					this.container.info.remove();
1750
1751				if (this.target && this.target.dispose)
1752					this.target.dispose();
1753				this.target = null;
1754
1755				if (this.stage && this.stage.dispose)
1756					this.stage.dispose();
1757				this.stage = null;
1758
1759				//if (this.target && this.target.outlineContainer) this.target.outlineContainer.remove();
1760				if (this.ui && this.ui.dispose)
1761					this.ui.dispose();
1762				this.ui = null;
1763
1764				if (this.contentProvider && this.contentProvider.dispose)
1765					this.contentProvider.dispose();
1766				this.contentProvider = null;
1767
1768				window.removeEventListener("resize", resizeDelay);
1769
1770			};
1771		}
1772
1773		PreviewObject.prototype = {
1774
1775			start: function () {
1776
1777				this.target.gotoPage(this.target.startPage);
1778
1779			},
1780
1781			end: function () {
1782				this.target.gotoPage(this.target.endPage);
1783			},
1784
1785			next: function () {
1786
1787			},
1788
1789			prev: function () {
1790
1791			},
1792
1793			zoom: function (delta) {
1794
1795				this.pendingZoom = true;
1796				this.zoomDelta = delta;
1797				/*
1798				 var contentProvider = this.contentProvider;
1799
1800				 contentProvider.zoomScale += delta;
1801
1802				 contentProvider.zoomScale = limitAt(contentProvider.zoomScale,1,contentProvider.maxZoom);//(delta == true) ? 2 : 1;
1803
1804				 //contentProvider.checkViewportSize();
1805				 //contentProvider.zoomScale = (zoom == true) ? contentProvider.normalViewport.height * contentProvider.viewport.scale / contentProvider.viewport.height : 1;
1806				 if (this.stage !== void 0) {
1807				 //this.stage.pendingZoom = true;//not used anymore
1808				 //this.stage.resize();
1809				 //var cameraZ =  this.stage.camera.position.z;
1810				 //this.stage.camera.position.set(0, 0, zoom == true ? 300 : 600);
1811
1812				 }
1813				 else {
1814
1815				 //this.target.wrapper.css({
1816				 //    transform: "scale(" + 1*/
1817				/*contentProvider.zoomScale*/
1818				/* + ")"
1819				 //});
1820				 this.target.left = 0;
1821				 this.target.top = 0;
1822				 }*/
1823				/*				if (contentProvider.zoomScale != 1) {
1824				 this.target.container.addClass("df-zoom-enabled");
1825				 }
1826				 else {
1827				 this.target.container.removeClass("df-zoom-enabled");
1828				 }*/
1829				this.resize();
1830				this.ui.update();
1831			},
1832
1833			resize: function () {
1834				var _this = this;
1835
1836				if (_this.target == void 0 ||
1837					_this.target.ui == void 0 ||
1838					_this.target.contentProvider == void 0 ||
1839					_this.target.contentProvider.viewport == void 0 ||
1840					_this.target.stage == void 0)
1841					return;
1842
1843				var isSingle = this.target.pageMode == DFLIP.PAGE_MODE.SINGLE,
1844					isFloating = _this.container.hasClass("df-floating");
1845				var target = _this.target,
1846					stage = target.stage,
1847					contentProvider = target.contentProvider,
1848					pageRatio = contentProvider.pageRatio,
1849					zoomViewport = contentProvider.zoomViewport,
1850					is3d = target.mode !== "css";
1851
1852				var parentWidth, parentHeight,
1853					windowHeight = $(window).height();
1854
1855				//checking if the container height is more than the window height
1856
1857				var containerHeight = target.ui.isFullscreen == true ? windowHeight : this.options.height;
1858
1859				_this.container.height(containerHeight);
1860
1861				if (Math.min(_this.container.height(), windowHeight) == windowHeight)
1862					containerHeight = windowHeight;
1863
1864				_this.container.height(containerHeight);
1865
1866				containerHeight = _this.container.height(); //fixing if the options are set on percentage
1867
1868				if (!is3d) {
1869					stage.css({
1870						top: 0,
1871						bottom: 0,
1872						right: 0,
1873						left: 0,
1874						transform: "translate3d(" + _this.target.left + "px," + _this.target.top + "px,0)"
1875					});
1876					target.stageHeight = stage.height();
1877				}
1878				parentWidth = stage.width();
1879				parentHeight = stage.height();
1880
1881				var availableWidth = parentWidth,
1882					availableHeight = Math.min(parentHeight, windowHeight),
1883					possibleWidth = Math.floor(isSingle ? availableWidth : availableWidth / 2);
1884
1885				var requiredHeight = Math.floor(possibleWidth / pageRatio);
1886				var height, width, cameraZ, fov, zoom;
1887
1888				height = Math.min(requiredHeight, availableHeight);
1889
1890				width = Math.floor(height * pageRatio);
1891
1892				contentProvider.maxZoom = contentProvider.zoomViewport.height / height;
1893
1894				if (_this.pendingZoom == true && _this.zoomDelta !== void 0) {
1895
1896					_this.pendingZoom = false;
1897					var delta = _this.zoomDelta, predictedIndex, currentMaxDimension = Math.max(height, width);
1898
1899					var improperZoom = contentProvider.zoomScale == 1;
1900
1901					var currentZoomScale = limitAt(improperZoom ? contentProvider.zoomScale
1902						: contentProvider.zoomScale + delta, 1, contentProvider.maxZoom);
1903
1904					if (delta > 0) {
1905						predictedIndex = nearestPowerOfTwo(currentMaxDimension * currentZoomScale);
1906					} else {
1907						predictedIndex = utils.lowerPowerOfTwo(currentMaxDimension * currentZoomScale);
1908					}
1909					//contentProvider.zoomScale += delta;
1910					//contentProvider.zoomScale = limitAt(predictedIndex / currentMaxDimension, 1, contentProvider.maxZoom);
1911					contentProvider.zoomScale = limitAt(delta > 0 ? _this.options.zoomRatio * contentProvider.zoomScale
1912						: contentProvider.zoomScale / _this.options.zoomRatio, 1, contentProvider.maxZoom);
1913
1914					_this.zoomDelta = void 0;
1915
1916				}
1917
1918				zoom = (contentProvider.zoomScale == 1 || contentProvider.zoomScale == void 0) ? 1
1919					: contentProvider.zoomScale;//zoomViewport.height / parentHeight,//target.contentProvider.zoomScale,
1920
1921				//findout which cacheIndex to use
1922				contentProvider.checkViewportSize(width * zoom, height * zoom);
1923
1924
1925				if (contentProvider.zoomScale != 1) {
1926					this.target.container.addClass("df-zoom-enabled");
1927				}
1928				else {
1929					this.target.container.removeClass("df-zoom-enabled");
1930				}
1931
1932				//if(contentProvider.zoomScale != 1)
1933				//zoom = contentProvider.cacheIndex / height;
1934
1935
1936//console.log(contentProvider.cacheIndex);
1937
1938				var maxZoom = contentProvider.maxZoom;
1939
1940				if (is3d) {
1941					//stage.resize();
1942					//_this.container.height(height);
1943
1944					height = containerHeight;
1945					var controlsHeight = _this.container.find(".df-ui-controls").height();
1946					if (controlsHeight == null || isFloating) controlsHeight = 0;
1947					stage.canvas.height(height - controlsHeight);
1948					if (_this.container.hasClass("df-sidemenu-open")) {
1949						parentWidth = parentWidth - 220;
1950					}
1951					stage.resizeCanvas(parentWidth, height - controlsHeight);
1952
1953					//if (target !== void 0)
1954					//    target.height = height;
1955
1956					//target.contentProvider.checkViewportSize();
1957
1958
1959					//height = 300;//flipBook.target.height;
1960					//var contentHeight = target.contentProvider.viewport.height * target.contentProvider.viewport.scale;
1961					//zoom = zoom ==1 ? zoom: zoom * zoom;
1962					//if (zoom == 1) {
1963					//    cameraZ = (height) * Math.tan(stage.camera.fov * 2 * Math.PI / 180);
1964					//}
1965					//else {
1966
1967					//var height = flipBook.options.height, visible = height ,zoom = (1600+ 1)/height
1968
1969					var refHeight = target.height,
1970						refWidth = parentWidth * refHeight / height,
1971						aspect = parentWidth / height;
1972
1973					var pageModeWidth = target.width * (isSingle ? 1 : 2);
1974
1975					var refLength = refWidth < pageModeWidth ? pageModeWidth / aspect : target.height;
1976
1977					var padding = _this.options.minTopOffset + (isFloating ? (60) : 30);
1978
1979					var adjustment = zoom == 1 ? height / (height - padding) : refHeight / refLength;
1980					/*
1981					 cameraZ = 1000,
1982					 fov = 2 * Math.atan((refLength) / (zoom / adjustment) / ( 2 * cameraZ )) * ( 180 / Math.PI );
1983
1984					 */
1985					//cameraZ = 1000,
1986					cameraZ = 1 / ( 2 * Math.tan(Math.PI * stage.camera.fov * 0.5 / 180) / ((refLength) / (zoom / adjustment)));
1987					//0.5* (zoom / adjustment) / (refLength) /  Math.tan((fov /2) * Math.PI /180) ;
1988
1989					//cameraZ = 1000/(zoom / adjustment);
1990					//stage.camera.fov = fov;
1991					stage.camera.updateProjectionMatrix();
1992
1993					//cameraZ = ((height + 60)*2 / zoom )* Math.tan(stage.camera.fov * Math.PI / 180);//(height /zoom) * Math.tan(stage.camera.fov * 2  * Math.PI / 180)/zoom;
1994					//}
1995
1996					stage.renderRequestPending = true;
1997					//if (stage.pendingZoom == true || zoom !== 1) {
1998					stage.camera.position.z = cameraZ;
1999
2000					//pixel value to stage position value
2001
2002					var shift = padding / 2 - _this.options.minTopOffset;
2003
2004					//put a check if the existing gap is enough
2005					_this.target.position.y = shift * refHeight / (_this.container.height() - padding);
2006					stage.cssScene.position.y = _this.target.position.y;
2007
2008					if (contentProvider.zoomScale == 1) {
2009						stage.camera.position.set(0, 0, cameraZ);
2010						stage.orbitControl.target = new THREE.Vector3(0, 0, 0);
2011						//stage.orbitControl.panUp(shift);
2012					}
2013					stage.orbitControl.update();
2014					stage.orbitControl.mouseButtons.ORBIT = zoom != 1 ? -1 : THREE.MOUSE.RIGHT;
2015					stage.orbitControl.mouseButtons.PAN = zoom != 1 ? THREE.MOUSE.LEFT : -1;
2016					//}
2017
2018					//if(isMobile) stage.orbitControl.mouseButtons.PAN = -1;
2019				}
2020				else {
2021					if (target !== void 0) {
2022
2023						//if (zoom > 1) {
2024						//	height = target.contentProvider.zoomViewport.height / zoom;//Math.min(requiredHeight, availableHeight);
2025						//	width = target.contentProvider.zoomViewport.width / zoom;
2026						//}
2027
2028						target.pageWidth = Math.floor(width);
2029						target.fullWidth = target.pageWidth * 2;
2030						target.height = height;
2031						//target.wrapper.width(target.fullWidth).height(height);
2032
2033
2034						var stagePaddingW = target.stage.innerWidth() - target.stage.width(),
2035							stagePaddingH = target.stage.innerHeight() - target.stage.height();
2036
2037						var shiftHeight = target.shiftHeight = limitAt((height * zoom - (containerHeight - stagePaddingH)) / 2, 0, target.height * zoom),
2038							shiftWidth = target.shiftWidth = limitAt(zoom == 1 ? 1 :
2039																	 (target.fullWidth * zoom - target.container.width() + stagePaddingW ) / 2, 0, target.fullWidth * zoom);
2040
2041						target.stage.css({
2042							top: -shiftHeight,
2043							bottom: -shiftHeight,
2044							right: -shiftWidth,
2045							left: -shiftWidth,
2046							transform: "translate3d(" + target.left + "px," + target.top + "px,0)"
2047						});
2048						//target.foldSense = this.pageWidth / 5;
2049
2050						var stageInnerHeight = target.stage.innerHeight();
2051						target.wrapper.css({
2052							width: target.fullWidth * zoom,
2053							height: height * zoom,
2054							marginTop: (containerHeight - height * zoom - stagePaddingH ) > 0
2055								? (containerHeight - stagePaddingH - height * zoom) / 2
2056								: 0
2057						});
2058
2059						var wrapperSize = Math.floor(distOrigin(width, height)) * zoom;
2060						target.stage.find(".df-page-wrapper").width(wrapperSize).height(wrapperSize);
2061
2062						target.stage.find(".df-book-page, .df-page-front , .df-page-back, .df-page-fold-inner-shadow").height(height * zoom).width(width * zoom);
2063						//target.contentProvider.checkViewportSize();
2064						//log("resized");
2065
2066						//target.resize();
2067					}
2068
2069				}
2070				this.checkCenter();
2071				if (target.thumblist) {
2072					target.thumblist.reset($(target.thumblist.container).height());
2073				}
2074
2075				/*				$(".quick-hint").html(JSON.stringify({
2076				 size: contentProvider.cacheIndex,
2077				 zoom: Math.round(contentProvider.zoomScale * 10) / 10,
2078				 height: height * zoom
2079				 }));*/
2080
2081				//rather than rsponsive lets use
2082				var containerWidth = _this.container.width();
2083				if (containerWidth < 400) {
2084					_this.container.addClass("df-xs");
2085				} else {
2086					_this.container.removeClass("df-xs");
2087				}
2088
2089			},
2090
2091			playSound: function () {
2092				try {
2093					if (this.options && this.options.soundEnable == true) {
2094						this.sound.currentTime = 0;
2095						this.sound.play();
2096					}
2097				} catch (error) {
2098
2099				}
2100			},
2101
2102			setPageMode: function (isSingle) {
2103				if (isSingle == true) {
2104					this.ui.pageMode.addClass(this.options.icons['doublepage']);
2105					this.ui.pageMode.html("<span>" + this.options.text.doublePageMode + "</span>");
2106					this.ui.pageMode.attr("title", this.options.text.doublePageMode);
2107					this.target.pageMode = DFLIP.PAGE_MODE.SINGLE;
2108				}
2109				else {
2110					this.ui.pageMode.removeClass(this.options.icons['doublepage']);
2111					this.ui.pageMode.html("<span>" + this.options.text.singlePageMode + "</span>");
2112					this.ui.pageMode.attr("title", this.options.text.singlePageMode);
2113					this.target.pageMode = DFLIP.PAGE_MODE.DOUBLE;
2114				}
2115				this.resize();
2116			},
2117			height: function (height) {
2118				if (height == void 0) {
2119					return this.container.height();
2120				} else {
2121					this.options.height = height;
2122					this.container.height(height);
2123					this.resize();
2124				}
2125			},
2126			/**
2127			 *checks whether the book is closed and needs to be centered
2128			 */
2129			checkCenter: function () {
2130				this.centerType = this.centerType || "start";
2131				var target = this.target;
2132				var singleShift = 0, left = 0, right = 0;
2133				var basePage = utils.getBasePage(target._activePage);
2134				var isEven = target._activePage % 2 == 0;
2135				var isRTL = target.direction == DFLIP.DIRECTION.RTL;
2136				var isSingle = target.pageMode == DFLIP.PAGE_MODE.SINGLE;
2137				var stageWidth = target.stage.width(),
2138					width;
2139
2140				if (target.mode == 'css') {
2141					width = target.wrapper.width();
2142					//calculate the excess shift required for corrction in case width is too small
2143					singleShift = Math.max((width - stageWidth) / 2, 0);
2144
2145					left = -width / 4,
2146						right = width / 4;
2147
2148					if (basePage == 0) {
2149						target.wrapper.css({
2150							left: isSingle
2151								? isRTL ? right - singleShift : left - singleShift
2152								: isRTL ? right : left
2153						});
2154						target.shadow.css({width: '50%', left: isRTL ? 0 : '50%', transitionDelay: ''});
2155					}
2156					else if (basePage == target.pageCount) {
2157						target.wrapper.css({
2158							left: isSingle
2159								? isRTL ? left - singleShift : right - singleShift
2160								: isRTL ? left : right
2161						});
2162						target.shadow.css({width: '50%', left: isRTL ? '50%' : 0, transitionDelay: ''});
2163					}
2164					else {
2165						target.wrapper.css({
2166							left: isSingle
2167								? isRTL
2168									  ? (isEven ? left - singleShift : right - singleShift )
2169									  : (isEven ? right - singleShift : left - singleShift )
2170								: 0
2171						});
2172						target.shadow.css({
2173							width: '100%',
2174							left: 0,
2175							transitionDelay: (parseInt(target.duration, 10) + 50) + 'ms'
2176						});
2177					}
2178
2179				}
2180				else if (target.stage !== void 0) {
2181					var init = target.position.x, end;
2182					singleShift = target.width / 4;
2183					width = target.width;
2184					left = -width / 2,
2185						right = width / 2;
2186
2187					if (basePage == 0) {
2188						end = isRTL ? right : left;
2189					}
2190					else if (basePage == target.pageCount) {
2191						end = isRTL ? left : right;
2192					}
2193					else {
2194						end = isSingle
2195							? isRTL
2196								  ? (isEven ? left : right )
2197								  : (isEven ? right : left )
2198							: 0;
2199					}
2200					//create a centertween
2201					if (end !== this.centerEnd) { //avoid recreating the tween if the target is same as before
2202						this.centerTween = new TWEEN.Tween({x: init}).delay(0)
2203							.to({x: end}, target.duration)
2204							.onUpdate(function () {
2205								target.position.x = this.x;
2206								target.stage.cssScene.position.x = this.x;
2207							}).easing(target.ease)
2208							.start();
2209						this.centerEnd = end;
2210
2211						//move the css too
2212						//this.target.flipCallback();
2213					}
2214				}
2215			},
2216
2217			width: function (width) {
2218				if (width == void 0) {
2219					return this.container.width();
2220				} else {
2221					this.options.width = width;
2222					this.container.width(width);
2223					this.resize();
2224				}
2225			}
2226
2227		};
2228
2229		return PreviewObject;
2230
2231	})({});
2232
2233	DFLIP.PreviewObject = PreviewObject;
2234
2235	//contentprovider that handles the source of book
2236	var ContentProvider = (function (_super) {
2237		__extends(ContentProvider, _super);
2238		var textureLoadTimeOut = void 0;
2239
2240		function ContentProvider(contentSource, callback, parameters, flipbook) {
2241
2242			parameters = parameters || {};
2243
2244			var _this = this;
2245
2246			_this.contentRawSource = contentSource || [defaults.textureLoadFallback];
2247			_this.contentSource = _this.contentRawSource;
2248			_this.contentSourceType = void 0;
2249			_this.minDimension = parameters.minTextureSize || 512;
2250			_this.maxDimension = parameters.maxTextureSize || 2048;
2251			_this.flipbook = flipbook;
2252			_this.waitPeriod = 50;
2253			_this.enableDebug = false;
2254			_this.zoomScale = 1;
2255			_this.maxZoom = 2;
2256			_this.options = parameters;
2257			_this.outline = parameters.outline;
2258			_this.links = parameters.links;
2259			_this.html = parameters.html;
2260			_this.isCrossOrigin = parameters.isCrossOrigin;
2261
2262			_this.normalViewport = {
2263				height: 297,
2264				width: 210,
2265				scale: 1
2266			};
2267			_this.viewport = {
2268				height: 297,
2269				width: 210,
2270				scale: 1
2271			};
2272			_this.zoomViewport = {
2273				height: 297,
2274				width: 210
2275			};
2276
2277			_this.thumbsize = 128;
2278			_this.cacheIndex = 512; //index of bigger dimension height or width
2279			_this.cache = [];
2280
2281			_this.pageRatio = parameters.pageRatio || _this.viewport.width / _this.viewport.height;
2282
2283			//texture load control so that it wont delay the transition
2284			_this.textureLoadTimeOut = void 0;
2285
2286			_this.type = "TextureLibrary";
2287
2288			if (Array === _this.contentSource.constructor || Array.isArray(_this.contentSource) || _this.contentSource instanceof Array) {
2289
2290				//case of images and html content
2291				_this.contentSourceType = SOURCE_TYPE.IMAGE;
2292				_this.pageCount = _this.contentSource.length;
2293
2294				//_this.setLoading(1, true);
2295
2296				// Make in memory copy of image to avoid css issues
2297				$("<img/>")
2298					.attr("src", _this.contentSource[0])
2299					.on('load', (function () {
2300						_this.viewport.height = this.height;
2301						_this.viewport.width = this.width;
2302
2303						_this.pageRatio = _this.viewport.width / _this.viewport.height;
2304
2305						_this.zoomViewport = {
2306							width: (_this.pageRatio > 1 ? 1 : _this.pageRatio) * _this.maxDimension,
2307							height: _this.maxDimension / (_this.pageRatio < 1 ? 1 : _this.pageRatio)
2308						};
2309
2310						_this.linkService = new PDFLinkService();
2311
2312						$(this).off();
2313
2314
2315						if (callback != void 0) callback(_this);
2316						//_this.setLoading(1);
2317
2318						//console.log(_this.zoomViewport);
2319						log(this.height + ":" + this.width);
2320						//pic_real_width = this.width;   // Note: $(this).width() will not
2321						//pic_real_height = this.height; // work for in memory images.
2322						//moved to set target function
2323						//_this.
2324						// ();
2325
2326
2327					}));
2328
2329			}
2330			else if (typeof _this.contentSource == 'string' || _this.contentSource instanceof String) { //case of link to pdf file
2331
2332				var processSource = function () {
2333					//configurePDFJS(PDFJS);
2334					PDFJS.workerSrc = defaults.pdfjsWorkerSrc;
2335
2336					_this.contentSourceType = SOURCE_TYPE.PDF;
2337					//PDFJS.disableWorker = true;
2338					PDFJS.disableAutoFetch = true;
2339					PDFJS.disableStream = true;
2340					PDFJS.externalLinkTarget = PDFJS.LinkTarget.BLANK;
2341
2342					var loading = PDFJS.getDocument(contentSource);
2343
2344					loading.then(function sourceLoaded(pdf) {
2345
2346							_this.pdfDocument = pdf;
2347							pdf.getPage(1).then(function (page) {
2348								_this.normalViewport = page.getViewport(1);
2349								_this.viewport = page.getViewport(1);
2350								_this.viewport.height = _this.viewport.height / 10;
2351								_this.viewport.width = _this.viewport.width / 10;
2352
2353								_this.pageRatio = _this.viewport.width / _this.viewport.height;
2354
2355								_this.zoomViewport = {
2356									width: (_this.pageRatio > 1 ? 1 : _this.pageRatio) * _this.maxDimension,
2357									height: _this.maxDimension / (_this.pageRatio < 1 ? 1 : _this.pageRatio)
2358								};
2359
2360								_this.refPage = page;
2361
2362								//console.log(_this.zoomViewport);
2363
2364								//check if intenal pages are of double sizes.
2365								if (pdf.numPages > 1) {
2366									pdf.getPage(2).then(function (page) {
2367										if (_this.options.pageSize == DFLIP.PAGE_SIZE.AUTO) {
2368											var _viewport = page.getViewport(1);
2369											if (_viewport.width > _this.normalViewport.width * 1.5) {
2370												_this.options.pageSize = DFLIP.PAGE_SIZE.DOUBLEINTERNAL;
2371												_this.pageCount = pdf.numPages * 2 - 2;
2372											}
2373											else {
2374												_this.options.pageSize = DFLIP.PAGE_SIZE.SINGLE;
2375											}
2376										}
2377										if (callback != void 0) callback(_this);
2378									});
2379								} else {
2380									if (callback != void 0) callback(_this);
2381								}
2382
2383							});
2384							_this.linkService = new PDFLinkService();
2385							_this.linkService.setDocument(pdf, null);
2386
2387							//moved to set target function
2388							//_this.initThumbs();
2389							_this.pageCount = pdf.numPages;
2390							_this.contentSource = pdf;
2391
2392						},
2393						function loadingError(error) {
2394
2395							var cors = "", tmp = document.createElement('a');
2396							tmp.href = _this.contentSource;
2397
2398							if (tmp.hostname !== window.location.hostname)
2399								cors = "CROSS ORIGIN!! ";
2400
2401							_this.updateInfo(cors + "Cannot access file!  " + _this.contentSource);
2402						});
2403
2404					loading.onProgress = function getDocumentProgress(progressData) {
2405						var percentage = 100 * progressData.loaded / progressData.total;
2406						if (isNaN(percentage)) {
2407							if (progressData && progressData.loaded) {
2408								_this.updateInfo("Loading PDF " + (Math.ceil(progressData.loaded / 10000) / 100).toString() + "MB ...");
2409							} else {
2410								_this.updateInfo("Loading PDF ...");
2411							}
2412						} else {
2413							_this.updateInfo("Loading PDF " + percentage.toString().split(".")[0] + "% ...");
2414						}
2415					};
2416				};
2417				var checkCORS = function () {
2418
2419					defaults.pdfjsWorkerSrc += "?ver=" + DFLIP.version;
2420
2421					_this.updateInfo("Loading PDF Worker ...");
2422					var tmp = document.createElement('a');
2423					tmp.href = defaults.pdfjsWorkerSrc;
2424
2425					if (tmp.hostname !== window.location.hostname) {
2426						_this.updateInfo("Loading PDF Worker CORS ...");
2427						$.ajax({
2428							url: defaults.pdfjsWorkerSrc,
2429							cache: true,
2430							success: function (data) {
2431								defaults.pdfjsWorkerSrc = DFLIP.createObjectURL(data, "text/javascript");
2432								processSource();
2433							}
2434						});
2435					}
2436					else {
2437						processSource();
2438					}
2439				};
2440				if (window.PDFJS == void 0) {
2441					_this.updateInfo("Loading PDF Service ...");
2442					//getScript(defaults.pdfjsCompatibilitySrc + "?ver=" + DFLIP.version, function () {
2443
2444						getScript(defaults.pdfjsSrc + "?ver=" + DFLIP.version, function () {
2445
2446							if (typeof define === 'function' && define.amd) {
2447								_this.updateInfo("Loading PDF Service (require) ...");
2448								require(['pdfjs-dist/build/pdf'], function (pdf) {
2449									checkCORS();
2450								});
2451							} else {
2452								checkCORS();
2453							}
2454						}, function () {
2455							_this.updateInfo("Unable to load PDF service..");
2456						});
2457					//});
2458				}
2459				else {
2460
2461					processSource();
2462				}
2463
2464			}
2465			else {
2466				console.error("Unknown source type. Please check documentation for help");
2467			}
2468
2469			this.dispose = function () {
2470				if (this.targetObject) {
2471					if (this.targetObject.dispose) this.targetObject.dispose();
2472					this.targetObject.processPage = null;
2473					this.targetObject.requestPage = null;
2474				}
2475				if (this.pdfDocument && this.pdfDocument.destroy) this.pdfDocument.destroy();
2476				if (this.linkService && this.linkService.dispose)  this.linkService.dispose();
2477				if (this.outlineViewer && this.outlineViewer.dispose) this.outlineViewer.dispose();
2478				if (this.thumblist && this.thumblist.dispose) this.thumblist.dispose();
2479
2480				this.targetObject = null;
2481				this.pdfDocument = null;
2482				this.linkService = null;
2483				this.outlineViewer = null;
2484				this.thumblist = null;
2485			};
2486			return this;
2487		}
2488
2489		ContentProvider.prototype.updateInfo = function (info) {
2490			if (this.flipbook && this.flipbook.updateInfo) {
2491				this.flipbook.updateInfo(info);
2492			}
2493		}
2494
2495		ContentProvider.prototype.initThumbs = function () {
2496
2497			var _this = this;
2498			if (_this.cache[_this.thumbsize] == void 0) _this.cache[_this.thumbsize] = [];
2499			var thumbLoadTimeOut;
2500			var review = function () {
2501				clearTimeout(thumbLoadTimeOut);
2502				thumbLoadTimeOut = setTimeout(function () {
2503
2504					thumbLoadTimeOut = setTimeout(reviewThumbs, _this.waitPeriod / 2);
2505
2506				}, _this.waitPeriod);
2507			};
2508
2509			var reviewThumbs = function () {
2510				var requestCount = 0;
2511				if (Date.now() - _this.thumblist.lastScrolled < 100) {
2512					requestCount = 1;
2513				} else {
2514					_this.targetObject.container.find(".df-thumb-container .df-vrow").each(function () {
2515						var thumb = $(this);
2516						if (!thumb.hasClass("df-thumb-loaded")) {
2517							requestCount++;
2518							var id = $(this).attr("id").replace("df-thumb", "");
2519							_this.getPage(id, review, true);
2520							thumb.addClass("df-thumb-loaded");
2521							return false;
2522						}
2523					});
2524					if (requestCount == 0) {
2525						clearTimeout(thumbLoadTimeOut);
2526					}
2527				}
2528
2529				if (requestCount > 0) {
2530					review();
2531				}
2532			};
2533
2534			_this.thumblist = _this.targetObject.thumblist = new ThumbList({
2535				//w: 128 * _this.viewport.width/_this.viewport.height,
2536				h: 500,
2537				addFn: function (row) {
2538
2539				},
2540				scrollFn: review,
2541				itemHeight: 128,
2542				totalRows: _this.pageCount,
2543				generatorFn: function (row) {
2544					var el = document.createElement("div");
2545					var pageNumber = row + 1;
2546					el.id = "df-thumb" + pageNumber;
2547					var elText = document.createElement("div");
2548					elText.innerHTML = pageNumber;
2549					el.appendChild(elText);
2550					//el.style.position = "absolute";
2551					//el.callback = function_this.getPage(pageNumber,void 0,true);
2552					return el;
2553				}
2554			});
2555
2556			_this.thumblist.lastScrolled = Date.now();
2557			review();
2558
2559			//_this.thumblist.container.classList.add('thumb-container');
2560			_this.targetObject.thumbContainer = $(_this.thumblist.container).addClass("df-thumb-container df-thumb-visible");
2561			_this.targetObject.container.append(_this.targetObject.thumbContainer);
2562
2563			_this.thumblist.reset($(_this.thumblist.container).height());
2564			_this.targetObject.container.on('click', '.df-thumb-container .df-vrow', function (e) {
2565				e.stopPropagation();
2566				var id = $(this).attr("id").replace("df-thumb", "");
2567				_this.targetObject.gotoPage(parseInt(id, 10));
2568			});
2569		};
2570
2571		ContentProvider.prototype.initOutline = function () {
2572			var _this = this;
2573			var outlineContainer = $('<div>').addClass("df-outline-container");
2574			_this.targetObject.container.append(outlineContainer);
2575			_this.targetObject.outlineContainer = outlineContainer;
2576
2577			_this.outlineViewer = new BookMarkViewer({
2578				container: outlineContainer[0],
2579				linkService: _this.linkService,
2580				outlineItemClass: "df-outline-item",
2581				outlineToggleClass: "df-outline-toggle",
2582				outlineToggleHiddenClass: "df-outlines-hidden"
2583			});
2584
2585			function processOutline(outline) {
2586
2587				if (_this.options.overwritePDFOutline == true) {
2588					outline = [];
2589				}
2590				outline = outline || [];
2591
2592				if (_this.outline) {
2593					for (var count = 0; count < _this.outline.length; count++) {
2594						_this.outline[count].custom = true;
2595						if (outline) outline.push(_this.outline[count]);
2596					}
2597					/*                    _this.outline.forEach(function(v) {
2598					 //v.custom = true;
2599					 this.push(v);
2600					 }, this);
2601					 outline.push(_this.outline)*/
2602				}
2603
2604				_this.outlineViewer.render({outline: outline});
2605			}
2606
2607			if (_this.pdfDocument) {
2608				_this.pdfDocument.getOutline().then(function (outline) {
2609					processOutline(outline);
2610				});
2611			}
2612			else {
2613				processOutline([]);
2614			}
2615
2616			if (_this.options.autoEnableOutline == true) {
2617				_this.targetObject.ui.outline.trigger("click");
2618			}
2619
2620		};
2621
2622		ContentProvider.prototype.checkViewportSize = function (width, height) {
2623			var _this = this;
2624			var target = _this.targetObject;
2625
2626			var oldCacheSize = _this.cacheIndex;
2627
2628			/*            var height = target.mode == "css"
2629			 ? (target.container.height() - (target.stage.innerWidth() - target.stage.width()) )
2630			 : target.stage.height();
2631
2632			 var width = height * _this.normalViewport.width / _this.normalViewport.height;*/
2633
2634			//var zoom = _this.zoomScale != 1;
2635
2636			if (_this.contentSourceType == SOURCE_TYPE.PDF) {
2637
2638				_this.viewport = (target.mode == "css")
2639					? _this.refPage.getViewport(height / _this.normalViewport.height)
2640					: _this.refPage.getViewport(300 / _this.normalViewport.height);
2641
2642				/*                _this.viewport.height = height;
2643				 _this.viewport.width = width;*/
2644
2645				_this.cacheIndex = nearestPowerOfTwo(Math.max(width, height));// * _this.zoomScale;//nearestPowerOfTwo(Math.max(_this.viewport.width,_this.viewport.height));
2646
2647				_this.cacheIndex = limitAt(_this.cacheIndex, _this.minDimension, _this.maxDimension);
2648
2649				_this.cacheScale = _this.cacheIndex / Math.max(_this.normalViewport.width, _this.normalViewport.height);
2650
2651				if (_this.cache[_this.cacheIndex] == void 0) _this.cache[_this.cacheIndex] = [];
2652
2653				if (oldCacheSize !== _this.cacheIndex) {
2654					for (var pageCount = 0; pageCount < target.children.length; pageCount++) {
2655						var page = target.children[pageCount];
2656						page.name = "-1";
2657					}
2658					target.refresh();
2659				}
2660
2661				var div = target.container.find(".linkAnnotation");
2662				div.css({
2663					transform: 'matrix(' + _this.viewport.clone({dontFlip: true}).transform.join(',') + ')'
2664				});
2665				//_this.zoomScale = (zoom == true) ? _this.normalViewport.height * _this.viewport.scale / _this.viewport.height : 1;
2666
2667			}
2668			else {
2669				if (_this.cache[_this.cacheIndex] == void 0) _this.cache[_this.cacheIndex] = [];
2670				/*                _this.cacheIndex = _this.zoomScale == 1 ? limitAt(_this.cacheIndex, _this.minDimension, _this.maxDimension) : _this.maxDimension;*/
2671
2672				//_this.zoomScale = (zoom == true) ? _this.zoomViewport.height / height : 1;
2673			}
2674
2675			//_this.zoomScale = (zoom == true) ? _this.zoomViewport.height / height : 1;
2676		};
2677
2678		ContentProvider.prototype.getCache = function (index, isThumb) {
2679			return (isThumb == true)
2680				? this.cache[this.thumbsize] == void 0 ? void 0 : this.cache[this.thumbsize][index]
2681				: this.cache[this.cacheIndex] == void 0 ? void 0 : this.cache[this.cacheIndex][index];
2682		};
2683
2684		ContentProvider.prototype.setCache = function (index, src, isThumb, cacheIndexSize) {
2685			if (isThumb == true) {
2686				if (this.cache[this.thumbsize] != void 0) this.cache[this.thumbsize][index] = src;
2687			}
2688			else {
2689				var cacheIndex = cacheIndexSize == void 0 ? this.cacheIndex : cacheIndexSize;
2690				if (this.cache[cacheIndex] != void 0)
2691					this.cache[cacheIndex][index] = src;
2692			}
2693
2694		};
2695
2696		ContentProvider.prototype.setTarget = function (targetObject) {
2697			var _this = this;
2698			if (targetObject == void 0) {
2699				return this.targetObject;
2700			}
2701			else {
2702				this.targetObject = targetObject;
2703				targetObject.contentProvider = this;
2704
2705				targetObject.container.removeClass("df-loading df-init");
2706
2707				//_this.initThumbs();
2708
2709				if (_this.linkService !== void 0) {
2710					_this.linkService.setViewer(targetObject);
2711
2712					_this.initOutline();
2713				}
2714
2715				targetObject.processPage = function (pageNumber, callback) {
2716					if (pageNumber > 0 && pageNumber <= _this.pageCount) {
2717						//log("Loading page :" + pageNumber);
2718						_this.getPage(pageNumber, callback);
2719					}
2720					else {
2721						_this.setPage(pageNumber, defaults.textureLoadFallback, callback);
2722						//log("Invalid PageNumber :" + pageNumber);
2723					}
2724				};
2725
2726				targetObject.requestPage = function (pageNumber) {
2727
2728					_this.setPage(pageNumber, defaults.textureLoadFallback);
2729					_this.review("Request");
2730				};
2731
2732				if (targetObject.resize !== void 0)
2733					targetObject.resize();
2734
2735			}
2736		};
2737
2738		ContentProvider.prototype.review = function (message) {
2739			var _this = this;
2740			message = message || "timer review";
2741			clearTimeout(textureLoadTimeOut);
2742			textureLoadTimeOut = setTimeout(function () {
2743
2744				textureLoadTimeOut = setTimeout(_this.reviewPages, _this.waitPeriod / 2, _this, message);
2745
2746			}, _this.waitPeriod);
2747		};
2748
2749		ContentProvider.prototype.reviewPages = function (_this, message) {
2750			_this = _this || this;
2751			var target = _this.targetObject;
2752
2753			if (target == void 0) return;
2754
2755			if (message !== void 0) log(message);
2756			var requiresRevisit = false;
2757			var pageCount, page;
2758
2759			for (pageCount = 0; pageCount < _this.targetObject.children.length; pageCount++) {
2760				page = target.children[pageCount];
2761				if (page.isFlipping == true) { //requires revisit
2762					requiresRevisit = true;
2763					break;
2764				}
2765			}
2766			if (requiresRevisit == false) {
2767
2768				var pageLength = target.children.length;
2769				var midPoint = pageLength / 2;
2770
2771				var basePage = getBasePage(target._activePage);
2772
2773
2774				if (_this.zoomScale > 1) {
2775					pageLength = 1;
2776				}
2777
2778				for (pageCount = 0; pageCount < pageLength; pageCount++) {
2779
2780					var dividend = Math.floor(pageCount / 2);
2781					var diff = pageCount % 2 == 0
2782						? -dividend * 2
2783						: (dividend == 0 ? 1 : dividend) * 2;
2784
2785					var frontPageNumber = basePage + diff,
2786						backPageNumber = basePage + diff + 1;
2787
2788					var page1 = target.getPageByNumber(frontPageNumber);
2789					var page2 = target.getPageByNumber(backPageNumber);
2790
2791					var requestCount = 0;
2792					if (page1 !== void 0 && page1.frontTextureLoaded != true) {
2793						target.processPage(frontPageNumber, function () {
2794							_this.review("Batch Call");
2795						});
2796						page1.frontTextureLoaded = true;
2797						requestCount++;
2798					}
2799					if (page2 !== void 0 && page2.backTextureLoaded != true) {
2800						target.processPage(backPageNumber, function () {
2801							_this.review("Batch Call");
2802						});
2803						page2.backTextureLoaded = true;
2804						requestCount++;
2805					}
2806
2807					//diff is 0 only at the open pages
2808					if (diff == 0 && _this.annotedPage !== basePage && target.mode !== "css") {
2809						_this.getAnnotations(frontPageNumber);
2810						_this.getAnnotations(backPageNumber);
2811						_this.annotedPage = basePage;
2812					}
2813
2814					if (requestCount > 0) {
2815						break;
2816					}
2817				}
2818				if (requestCount == 0)
2819					_this.setLoading(basePage), _this.setLoading(basePage + 1);
2820			}
2821			else {
2822				_this.review("Revisit request");
2823				if (_this.annotedPage !== void 0 && target.mode !== "css") {
2824					var baseActive = getBasePage(target._activePage);
2825					$(target.getContentLayer(baseActive)).html("");
2826					$(target.getContentLayer(baseActive + 1)).html("");
2827					_this.annotedPage = void 0;
2828				}
2829			}
2830
2831		};
2832
2833		ContentProvider.prototype.getPage = function (pageNumber, callbackFunction, isThumb) {
2834			var _this = this;
2835
2836			pageNumber = parseInt(pageNumber, 10);
2837			var source = _this.contentSource;
2838			if (pageNumber <= 0 && pageNumber >= _this.pageCount) {
2839				_this.setPage(pageNumber, defaults.textureLoadFallback, callbackFunction, isThumb);
2840			}
2841			else {
2842				if (_this.contentSourceType == SOURCE_TYPE.PDF) {
2843					if (_this.getCache(pageNumber, isThumb) !== void 0) {
2844						_this.setPage(pageNumber, _this.getCache(pageNumber, isThumb), callbackFunction, isThumb);
2845						log("Page " + pageNumber + " loaded from cache");
2846					}
2847					else {
2848						if (isThumb !== true)_this.setLoading(pageNumber, true);
2849						var _pageNumber = pageNumber;
2850						if (_this.options.pageSize == DFLIP.PAGE_SIZE.DOUBLEINTERNAL && pageNumber > 2) {
2851							_pageNumber = Math.ceil((pageNumber - 1) / 2) + 1;
2852						}
2853						source.getPage(_pageNumber, isThumb).then(function (page) {
2854							renderPage(page, pageNumber, callbackFunction, isThumb);
2855						});
2856					}
2857				}
2858				else if (_this.contentSourceType == SOURCE_TYPE.IMAGE || _this.contentSourceType == SOURCE_TYPE.HTML) {
2859					if (_this.getCache(pageNumber, isThumb) !== void 0) {
2860						_this.setPage(pageNumber, _this.getCache(pageNumber, isThumb), callbackFunction, isThumb);
2861						log("Page " + pageNumber + " loaded from cache");
2862					}
2863					else {
2864						if (isThumb !== true)_this.setLoading(pageNumber, true);
2865
2866						loadImage(source[pageNumber - 1], function (src) {
2867
2868							_this.setCache(pageNumber, src, isThumb, _this.cacheIndex);
2869							_this.setPage(pageNumber, src, callbackFunction, isThumb);
2870
2871							if (callbackFunction != void 0) callbackFunction();
2872
2873						}, _this.isCrossOrigin);
2874
2875					}
2876
2877					//_this.setPage(pageNumber, source[pageNumber - 1], callbackFunction, isThumb);
2878				}
2879			}
2880
2881			function loadImage(src, callback, isCrossOrigin) {
2882
2883				var img = new Image;
2884
2885				img.crossOrigin = "Anonymous";
2886
2887				img.onload = function () {
2888
2889					if (isCrossOrigin == true) {
2890						var canvas = document.createElement("canvas"),
2891							ctx = canvas.getContext("2d");
2892						canvas.width = img.width;
2893						canvas.height = img.height;
2894						ctx.drawImage(img, 0, 0);
2895						//localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
2896
2897						if (defaults.canvasToBlob == true) {
2898							canvas.toBlob(function (blob) {
2899								var src = DFLIP.createObjectURL(blob, "image/jpeg");
2900
2901								if (callback != void 0) callback(src);
2902
2903							}, "image/jpeg", 0.85)
2904
2905
2906						}
2907						else {
2908							if (callback != void 0) callback(canvas);
2909						}
2910					}
2911					else {
2912						if (callback != void 0) callback(src);
2913					}
2914					//$(this).off();
2915					img.onload = null;
2916					img = null;
2917
2918				}
2919
2920				img.src = src;
2921
2922				// make sure the load event fires for cached images too
2923				if (img.complete || img.complete === undefined) {
2924					img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
2925					img.src = src;
2926				}
2927
2928			}
2929
2930			function renderPage(page, pageNumber, callbackFunction, isThumb) {
2931
2932				log("rendering" + pageNumber);
2933
2934				/*                var heightScale = _this.pageRatio < 1
2935				 ? _this.cacheScale
2936				 : _this.cacheScale / _this.pageRatio;*/
2937
2938				var scale = _this.cacheScale;//heightScale /_this.normalViewport.height;
2939
2940				var viewport;
2941				var canvas = document.createElement('canvas');
2942				var start = performance.now();
2943
2944				var requestedCacheSize = _this.cacheIndex;
2945
2946				var context = canvas.getContext('2d');
2947
2948				if (isThumb == true) {
2949					scale = _this.thumbsize / _this.normalViewport.height;
2950				}
2951
2952				canvas.height = _this.normalViewport.height * scale;
2953				canvas.width = _this.normalViewport.width * scale;
2954
2955				viewport = page.getViewport(scale);
2956				if (_this.options.pageSize == DFLIP.PAGE_SIZE.DOUBLEINTERNAL && pageNumber > 2 && pageNumber % 2 == 1) {
2957					//viewport = new PDFJS.PageViewport(viewport.viewBox.slice(), viewport.scale, viewport.rotation,
2958					//	canvas.width, 0);
2959					viewport.transform[4] = -canvas.width;
2960				}
2961				var renderContext = {
2962					canvasContext: context,
2963					viewport: viewport
2964				};
2965
2966				page.cleanupAfterRender = true;
2967				var pageRendering = page.render(renderContext);
2968
2969				pageRendering.promise.then(
2970					function () {
2971
2972						log(performance.now() - start);
2973						start = performance.now();
2974						if (isThumb == true || (_this.options.canvasToBlob == true && _this.webgl !== true)) {
2975							canvas.toBlob(function (blob) {
2976								var src = DFLIP.createObjectURL(blob, "image/jpeg");
2977								log(performance.now() - start);
2978								_this.setCache(pageNumber, src, isThumb, requestedCacheSize);
2979								_this.setPage(pageNumber, src, callbackFunction, isThumb);
2980
2981								//canvas.width = canvas.height = 1;
2982								//context.clearRect( 0, 0, canvas.width, canvas.height );
2983
2984								//page.cleanup();
2985							}, "image/jpeg", 0.85)
2986						}
2987						else {
2988							_this.setPage(pageNumber, canvas, callbackFunction, isThumb);
2989						}
2990						renderContext = null;
2991					});
2992
2993			}
2994
2995		};
2996
2997		ContentProvider.prototype.getTargetPage = function (pageNumber) {
2998
2999		};
3000
3001		ContentProvider.prototype.setLoading = function (pageNumber, show) {
3002			if (this.targetObject !== void 0) {
3003				if (this.webgl == true) {
3004					var container = this.targetObject.container;
3005					if (show == true) container.addClass("df-loading");
3006					else container.removeClass("df-loading");
3007				} else {
3008					var contentLayer = $(this.targetObject.getContentLayer(pageNumber));
3009					if (contentLayer !== void 0) {
3010						if (show == true) contentLayer.addClass("df-page-loading");
3011						else contentLayer.removeClass("df-page-loading");
3012					}
3013				}
3014			}
3015		};
3016
3017		ContentProvider.prototype.getAnnotations = function (pageNumber) {
3018			var _this = this;
3019			var target = _this.targetObject;
3020
3021			pageNumber = parseInt(pageNumber, 10);
3022			var source = _this.contentSource;
3023			var contentLayer = $(target.getContentLayer(pageNumber));
3024			contentLayer.empty();
3025			if (pageNumber > 0 && pageNumber <= _this.pageCount) {
3026
3027
3028				if (_this.contentSourceType == SOURCE_TYPE.PDF) {
3029					var basePage = getBasePage(pageNumber);
3030
3031					var _pageNumber = pageNumber;
3032					if (_this.options.pageSize == DFLIP.PAGE_SIZE.DOUBLEINTERNAL && pageNumber > 2) {
3033						_pageNumber = Math.ceil((pageNumber - 1) / 2) + 1;
3034					}
3035
3036					source.getPage(_pageNumber).then(function (page) {
3037
3038						if (contentLayer !== void 0 && contentLayer.length > 0) {
3039							_this.setupAnnotations(page, _this.viewport, contentLayer, pageNumber);
3040
3041							/*                            //it's just resizing nothing to do with annotation fetch
3042							 if (target.mode != "css") {
3043
3044							 var page3d = target.getPageByNumber(pageNumber);
3045							 if (page3d !== void 0) {
3046							 var isLeft = (pageNumber % 2 == 0);
3047							 var width = Math.abs(page3d.geometry.boundingBox.max.x - page3d.geometry.boundingBox.min.x);
3048							 var height = Math.abs(page3d.geometry.boundingBox.max.z - page3d.geometry.boundingBox.min.z);
3049
3050							 var div3d = isLeft ? target.parent.cssScene.divLeft : target.parent.cssScene.divRight;
3051							 if (div3d !== void 0) {
3052							 div3d.rotation.y = (isLeft ? -1 : 1 ) * Math.atan2(height, width) * 0.9;
3053							 div3d.position.z = height * 0.8;
3054							 div3d.position.x = (isLeft ? 1 : -1 ) * height / 2.5;
3055							 $(div3d.element).css({
3056							 width: width,
3057							 left: isLeft ? -width / 2 : width / 2
3058							 });
3059
3060							 }
3061							 }
3062							 }*/
3063						}
3064					});
3065				}
3066
3067				//render any custom liks available for page.
3068
3069				if (_this.links !== void 0 && _this.links[pageNumber] !== void 0) {
3070					var pageLinks = _this.links[pageNumber];
3071					for (var index = 0; index < pageLinks.length; index++) {
3072						var pageLink = pageLinks[index];
3073
3074						var link = document.createElement('a');
3075						link.setAttribute("dest", pageLink.dest);
3076						link.className = "customLinkAnnotation";
3077						link.href = "#" + pageLink.dest;
3078						link.onclick = function () {
3079							var dest = this.getAttribute("dest");
3080							if (dest) {
3081								_this.linkService.customNavigateTo(dest);
3082							}
3083							return false;
3084						};
3085						link.style.left = pageLink.x + "%";
3086						link.style.top = pageLink.y + "%";
3087
3088						link.style.width = pageLink.w + "%";
3089						link.style.height = pageLink.h + "%";
3090						contentLayer[0].appendChild(link);
3091					}
3092				}
3093
3094				//render any html available for page.
3095
3096				if (_this.html !== void 0 && _this.html[pageNumber] !== void 0) {
3097					var pageHTML = _this.html[pageNumber];
3098					contentLayer.append($("<div class='customHTMLAnnotation'>").html(pageHTML));
3099				}
3100			}
3101		};
3102
3103		ContentProvider.prototype.setPage = function (pageNumber, textureSrc, callbackFunction, isThumb) {
3104			var _this = this;
3105			var target = _this.targetObject;
3106			if (isThumb == true) {
3107				var page = _this.targetObject.container.find("#df-thumb" + pageNumber);
3108				//log("setting:" + pageNumber + " " + bgImage(textureSrc));
3109				page.css({
3110					backgroundImage: bgImage(textureSrc)
3111				});
3112			}
3113			else {
3114
3115				if (textureSrc == defaults.textureLoadFallback) {
3116					log("Fallback on " + pageNumber);
3117				}
3118				else {
3119					if (target.mode == "css")
3120						_this.getAnnotations(pageNumber);
3121				}
3122
3123				var bookPage = target.getPageByNumber(pageNumber);
3124				if (bookPage !== void 0) {
3125					if (
3126						pageNumber % 2 != 0 && target.direction == DFLIP.DIRECTION.LTR ||
3127						pageNumber % 2 != 1 && target.direction == DFLIP.DIRECTION.RTL
3128					) {
3129						log(pageNumber + "rendered to back of " + bookPage.color);
3130						bookPage.backImage(textureSrc, function () {
3131							_this.setLoading(pageNumber);
3132							if (callbackFunction != void 0) callbackFunction();
3133						});
3134					}
3135					else {
3136						log(pageNumber + "rendered to front of " + bookPage.color);
3137						bookPage.frontImage(textureSrc, function () {
3138							_this.setLoading(pageNumber);
3139							if (callbackFunction != void 0) callbackFunction();
3140						});
3141					}
3142				}
3143				else {
3144					log("Invalid set request on Page " + pageNumber);
3145				}
3146			}
3147		};
3148
3149		ContentProvider.prototype.setupAnnotations = function (page, viewport, pageDiv, pageNumber) {
3150			if (pageDiv == void 0 || $(pageDiv).length == 0) return;
3151			var _this = this;
3152			return page.getAnnotations().then(function (annotationsData) {
3153				viewport = viewport.clone({
3154					dontFlip: true
3155				});
3156
3157				if (_this.options.pageSize == DFLIP.PAGE_SIZE.DOUBLEINTERNAL && pageNumber > 2 && pageNumber % 2 == 1) {
3158					//viewport.transform[4]= -viewport.scale * page.view[2]/2;
3159
3160				}
3161				else if (pageNumber == 1) {
3162
3163				}
3164				if (pageDiv == void 0) {
3165					return;
3166				}
3167				pageDiv = $(pageDiv);
3168				if (pageDiv.find(".annotationDiv").length == 0) {
3169					pageDiv.append($("<div class='annotationDiv'>"));
3170				}
3171				var div = pageDiv.find(".annotationDiv");
3172				div.empty();
3173				if (_this.options.pageSize == DFLIP.PAGE_SIZE.DOUBLEINTERNAL && pageNumber > 2 && pageNumber % 2 == 1) {
3174					//viewport.transform[4]= -viewport.scale * page.view[2]/2;
3175					div.css({left: '-100%'});
3176				}
3177				else if (pageNumber == 1) {
3178					div.css({left: ''});
3179				}
3180				/*                div.css({
3181				 transform:'matrix(' + _this.viewport.transform.join(',') + ')'
3182				 });*/
3183
3184				PDFJS.AnnotationLayer.render({
3185					annotations: annotationsData,
3186					div: div[0],
3187					page: page,
3188					viewport: viewport,
3189					linkService: _this.linkService
3190				});
3191
3192				div.find(" > section").addClass("someclass");
3193				/*				page.getTextContent().then(function(textContent){
3194				 console.log( textContent );
3195				 var textLayer = new DFLIP.TextLayerBuilder({
3196				 textLayerDiv :div[0],
3197				 pageIndex : void 0,
3198				 viewport : viewport.clone({
3199				 dontFlip: false
3200				 })
3201				 });
3202
3203				 textLayer.setTextContent(textContent);
3204				 textLayer.render();
3205				 });*/
3206
3207			});
3208
3209		};
3210
3211		return ContentProvider;
3212	})({});
3213
3214	var PageCSS = (function () {
3215		function PageCSS(parameters) {
3216			this.angles = parameters.angles || [0, 0, 0, 0, 0, 0];
3217			this.stiffness = parameters.angles || 0.1;
3218			this.segments = parameters.segments || 1;
3219			this.initDOM();
3220		}
3221
3222		function createInternals(pageSide) {
3223			var contentLayer = pageSide.contentLayer = $(html.div, {
3224				class: "df-page-content"
3225			});
3226			pageSide.append(contentLayer);
3227		}
3228
3229		PageCSS.prototype = {
3230			initDOM: function () {
3231				var element = this.element = $(html.div, {
3232					class: "df-book-page"
3233				});
3234				var wrapper = this.wrapper = $(html.div, {
3235					class: "df-page-wrapper"
3236				});
3237				var front = this.front = $(html.div, {
3238					class: "df-page-front"
3239				});
3240				var back = this.back = $(html.div, {
3241					class: "df-page-back"
3242				});
3243				var foldInnerShadow = this.foldInnerShadow = $(html.div, {
3244					class: "df-page-fold-inner-shadow"
3245				});
3246				var foldOuterShadow = this.foldOuterShadow = $(html.div, {
3247					class: "df-page-fold-outer-shadow"
3248				});
3249				createInternals(front, this.segments, true);
3250				createInternals(back, this.segments, false);
3251				element.append(wrapper).append(foldOuterShadow);
3252				wrapper.append(front).append(back).append(foldInnerShadow);
3253
3254			},
3255
3256			updatePoint: function (point) {
3257
3258				if (point == void 0) return;
3259
3260				//detect the current page
3261				var page = this.parent.dragPage != void 0 ? this.parent.dragPage
3262					: point.page != void 0 ? point.page : this;
3263
3264				//get the pageWidth and pageHeight
3265				var pageWidth = page.element.width(),
3266					pageHeight = page.element.height();
3267
3268				//the corner where the drag started
3269				var corner = this.parent.corner !== void 0 ? this.parent.corner : point.corner,
3270					corners = DFLIP.CORNERS;
3271
3272				var
3273					isRight = page.side == drag.right,
3274					isBottom = (corner == corners.BL) || (corner == corners.BR);
3275
3276				point.rx = (isRight == true)
3277					? pageWidth * 2 - point.x
3278					: point.x;
3279
3280				point.ry = (isBottom == true)
3281					? pageHeight - point.y
3282					: point.y;
3283
3284				var radAngle = Math.atan2(point.ry, point.rx);
3285
3286				radAngle = Math.PI / 2 - limitAt(radAngle, 0, toRad(90));
3287
3288				var correctionX = isRight
3289						? point.x / 2
3290						: pageWidth - point.x / 2,
3291
3292					correctionY = point.ry / 2,
3293
3294					refLength = Math.max(0,
3295						Math.sin(radAngle - Math.atan2(correctionY, correctionX)) * distOrigin(correctionX,
3296							correctionY)),
3297
3298					foldLength = 0.5 * distOrigin(point.rx, point.ry);
3299
3300				var x = Math.round(pageWidth - refLength * Math.sin(radAngle)),
3301					y = Math.round(refLength * Math.cos(radAngle)),
3302
3303					angle = toDeg(radAngle);
3304
3305				var angle1 = isBottom
3306					? isRight ? 180 + ( 90 - angle) : 180 + angle
3307					: isRight ? angle : 90 - angle;
3308
3309				var angle2 = isBottom
3310						? isRight ? 180 + ( 90 - angle) : angle
3311						: isRight ? angle + 180 : angle1,
3312					angleS = isBottom
3313						? isRight ? 90 - angle : angle + 90
3314						: isRight ? angle1 - 90 : angle1 + 180,
3315					x1 = isRight ? pageWidth - x : x,
3316					y1 = isBottom ? pageHeight + y : -y,
3317					x2 = isRight ? -x : x - pageWidth,
3318					y2 = isBottom ? -pageHeight - y : y;
3319
3320				var opacity = limitAt(point.distance * 0.5 / pageWidth, 0, 0.5);
3321				var foldOpacity = limitAt((pageWidth * 2 - point.rx) * 0.5 / pageWidth, 0.05, 0.3);
3322
3323				page.element.addClass("df-folding");
3324
3325				var front = isRight ? page.back : page.front;
3326				var back = isRight ? page.front : page.back;
3327				var outerShadow = page.foldOuterShadow;
3328				var innerShadow = page.foldInnerShadow;
3329				page.wrapper.css({
3330					transform: translateStr(x1, y1) + rotateStr(angle1)
3331				});
3332
3333				front.css({
3334					transform: rotateStr(-angle1) + translateStr(-x1, -y1)
3335				});
3336
3337				back.css({
3338					transform: rotateStr(angle2) + translateStr(x2, y2),
3339					boxShadow: "rgba(0, 0, 0, " + opacity + ") 0px 0px 20px"
3340				});
3341
3342				innerShadow.css({
3343					transform: rotateStr(angle2) + translateStr(x2, y2),
3344					opacity: foldOpacity / 2,
3345					backgroundImage: prefix.css + "linear-gradient( " + angleS + "deg, rgba(0, 0, 0, 0.25) , rgb(0, 0, 0) " + foldLength * 0.7 + "px, rgb(255, 255, 255) " + foldLength + "px)"
3346				});
3347
3348				outerShadow.css({
3349					//transform: rotateStr(angle - (isRight ? -180 : 0)) + translateStr(isRight ? -x : x - pageWidth, y),
3350					opacity: foldOpacity / 2,
3351					left: isRight ? "auto" : 0,
3352					right: isRight ? 0 : "auto",
3353					backgroundImage: prefix.css + "linear-gradient( " + (-angleS + 180) + "deg, rgba(0, 0, 0,0) " + foldLength / 3 + "px, rgb(0, 0, 0) " + foldLength + "px)"
3354				});
3355
3356				//$("body > p").html(JSON.stringify({
3357				//	x: Math.round(point.rx),
3358				//	y: Math.round(point.ry),
3359				//	a: Math.round(angle),
3360				//	a1: Math.round(angle1),
3361				//	cx: Math.round(correctionX),
3362				//	cy: Math.round(correctionY),
3363				//	dx: Math.round(x),
3364				//	dy: Math.round(y),
3365				//	ref: Math.round(refLength),
3366				//	dis: Math.round(distOrigin(point.x, point.y))
3367				//}));
3368			},
3369
3370			updateAngle: function (angle, isRight) {
3371
3372				var width = this.element.width() * 5;
3373
3374				//if(prefix.dom!=='MS') {
3375				this.wrapper.css({
3376					perspective: width,
3377					perspectiveOrigin: isRight == true ? "0% 50%" : "100% 50%"
3378				});
3379				//}
3380
3381				this.front.css({
3382					display: (isRight == true ? (angle <= -90 ? 'block' : 'none') : (angle < 90 ? 'block' : 'none')),
3383					transform: (prefix.dom !== 'MfS' ? "" : "perspective(" + width + "px) ")
3384					+ (isRight == true ? "translateX(-100%) " : "" )
3385					+ "rotateY(" + ((isRight == true ? 180 : 0 ) + angle) + "deg)"
3386				});
3387				this.back.css({
3388					display: (isRight == true ? (angle > -90 ? 'block' : 'none') : (angle >= 90 ? 'block' : 'none')),
3389					transform: (prefix.dom !== 'MSd' ? "" : "perspective(" + width + "px) ")
3390					+ (isRight == false ? "translateX(100%) " : "" )
3391					+ "rotateY(" + ((isRight == false ? -180 : 0 ) + angle) + "deg)"
3392				});
3393				//$("body > p").html(JSON.stringify({
3394				//	a: Math.round(angle)
3395				//}));
3396				return;
3397				/*if(this.angles[1] != void 0) {
3398				 var segsb = this.back.segments;
3399				 var segsf = this.front.segments;
3400				 var width = this.element.width();
3401				 var angle1 = this.angles[1];
3402				 var angle2 = this.angles[4]/segsb.length;
3403				 var step = Math.floor(width/segsb.length);
3404
3405				 for (var count = 0; count < segsb.length; count++) {
3406				 var segb = segsb[count];
3407				 var segf = segsf[count];
3408				 segb.css({
3409				 transform: "rotate3d(0,1,0," + (count == 0 ? angle1 : angle2) + "deg)",
3410				 //backgroundPositionX: -step * count,
3411				 //backgroundSize: width + "px 100%"
3412				 });
3413
3414				 segf.css({
3415				 transform: "rotate3d(0,1,0," + (count == 0 ? 180 + angle1 : angle2) + "deg)",
3416				 //backgroundPositionX: step * (count + 1),
3417				 //backgroundSize: width + "px 100%"
3418				 });
3419				 }
3420				 }
3421				 else{
3422				 this.element.find(".bg-segment").css({
3423				 transform: "translate3d(0px,0,0) rotate3d(0,1,0,0deg)"
3424				 });
3425				 }*/
3426
3427			},
3428
3429			tween: function (point) {
3430				var page = this;
3431				if (page == void 0 || page.parent == void 0) return;
3432
3433				var isRight = page.side == drag.right;
3434				var isBottom = page.parent.corner == DFLIP.CORNERS.BL || page.parent.corner == DFLIP.CORNERS.BR;
3435
3436				var travelY = isBottom ? page.parent.height : 0;
3437
3438				var init, first, mid, angle = 0;
3439
3440				var end = page.end = (page && page.animateToReset == true)
3441					? {x: isRight ? page.parent.fullWidth : 0, y: travelY}
3442					: {x: isRight ? 0 : page.parent.fullWidth, y: travelY};
3443
3444				page.ease = page.isHard ? TWEEN.Easing.Quadratic.InOut : TWEEN.Easing.Linear.None;
3445
3446				var tempDuration = page.parent.duration;
3447
3448				if (page.isHard == true) {
3449
3450					if (point != void 0) {
3451						angle = angleByDistance(point.distance, point.fullWidth);
3452					}
3453
3454					init = page.init = {angle: angle * (isRight ? -1 : 1)};
3455					end = page.end = (page && page.animateToReset == true)
3456						? {angle: isRight ? 0 : -0}
3457						: {angle: isRight ? -180 : 180};
3458
3459				} else {
3460
3461					if (point == void 0) {
3462
3463						init = page.init = (page && page.animateToReset == true)
3464							? {x: isRight ? 0 : page.parent.fullWidth, y: 0}
3465							: {x: isRight ? page.parent.fullWidth : 0, y: 0};
3466
3467						first = page.first = {
3468							x: (isRight ? 3 : 1 ) * page.parent.fullWidth / 4,
3469							y: 0
3470						};
3471
3472						mid = page.mid = {x: (isRight ? 1 : 3 ) * page.parent.fullWidth / 4, y: 0};
3473
3474					}
3475					else {
3476
3477						init = page.init = {x: point.x, y: point.y};
3478						first = page.first = {x: point.x * 3 / 4, y: point.y * 3 / 4};
3479						mid = page.mid = {x: point.x / 4, y: point.y / 4};
3480
3481						tempDuration = page.parent.duration * distPoints(init.x, init.y, end.x, end.y) / page.parent.fullWidth;
3482
3483						tempDuration = limitAt(tempDuration, page.parent.duration / 3, page.parent.duration);
3484
3485					}
3486				}
3487				page.isFlipping = true;
3488
3489				var update = function (tween) {
3490
3491					if (page.isHard == true) {
3492						page.updateAngle(tween.angle, isRight);
3493					} else {
3494						page.updatePoint({
3495							x: tween.x,
3496							y: tween.y
3497						});
3498					}
3499
3500				};
3501
3502				var completeTween = page.completeTween = page.completeTween || function (skipRefresh) {
3503					page.isFlipping = false;
3504
3505					if (page.isHard == true) {
3506
3507						page.updateAngle(page.end.angle);
3508						page.back.css({display: "block"});
3509						page.front.css({display: "block"});
3510
3511					}
3512					else {
3513
3514						page.updatePoint({
3515							x: page.end.x,
3516							y: page.end.y
3517						});
3518
3519					}
3520
3521					if (page.animateToReset !== true) {
3522						page.side = page.side == drag.right ? drag.left : drag.right;
3523					}
3524					else
3525						page.animateToReset = void 0;
3526
3527					page.currentTween = void 0;
3528					page.pendingPoint = void 0;
3529					page.magnetic = false;
3530					page.parent.dragPage = void 0;
3531					page.parent.corner = DFLIP.CORNERS.NONE;
3532
3533					if (skipRefresh != true)
3534						page.parent.refresh();
3535
3536
3537					//log("Tween Completed");
3538				};
3539				if (page.isHard == true) {
3540					page.currentTween = new TWEEN.Tween(init).delay(0)
3541						.to(end, page.parent.duration)
3542						.onUpdate(function () {
3543							update(this);
3544						}).easing(page.ease)
3545						.onComplete(page.completeTween)
3546						.start();
3547				} else {
3548					if (point == void 0) {
3549						page.currentTween = new TWEEN.Tween(init).delay(0)
3550							.to(end, page.parent.duration)
3551							.onUpdate(function () {
3552								update(this);
3553							}).easing(TWEEN.Easing.Sinusoidal.Out)
3554							.onComplete(page.completeTween)
3555							.start();
3556					}
3557					else {
3558						page.currentTween = new TWEEN.Tween(init).delay(0)
3559							.to(end, tempDuration)
3560							.onUpdate(function () {
3561								update(this);
3562							}).easing(TWEEN.Easing.Sinusoidal.Out)
3563							.onComplete(page.completeTween);
3564						page.currentTween.start();
3565					}
3566				}
3567				//page.currentTween.parent= page;
3568
3569			},
3570			frontImage: function (texture, callback) {
3571				if (texture.nodeName == "CANVAS") {
3572					this.front.find(">canvas").remove();
3573					this.front.append($(texture));
3574				}
3575				else {
3576					this.front.css({
3577						backgroundImage: bgImage(texture)
3578					});
3579				}
3580				if (callback !== void 0) callback();
3581			},
3582			backImage: function (texture, callback) {
3583
3584				if (texture.nodeName == "CANVAS") {
3585					this.back.find(">canvas").remove();
3586					this.back.append($(texture));
3587				}
3588				else {
3589					this.back.css({
3590						backgroundImage: bgImage(texture)
3591					});
3592				}
3593				if (callback !== void 0) callback();
3594			},
3595			updateCSS: function (css) {
3596				this.element.css(css);
3597			},
3598			resetCSS: function () {
3599				this.wrapper.css({
3600					transform: ''
3601				});
3602
3603				this.front.css({
3604					transform: '',
3605					boxShadow: ''
3606				});
3607
3608				this.back.css({
3609					transform: '',
3610					boxShadow: ''
3611				});
3612			},
3613			clearTween: function (skipRefresh) {
3614				this.currentTween.stop();
3615				this.completeTween(skipRefresh == true);
3616				this.resetCSS();
3617			}
3618
3619		};
3620
3621		return PageCSS;
3622	})();
3623
3624	var BookCSS = (function (_super) {
3625		__extends(BookCSS, _super);
3626
3627		function updateFolding(dragPage) {
3628			dragPage.parent.container.find(".df-folding").removeClass("df-folding");
3629			dragPage.element.addClass("df-folding");
3630		}
3631
3632		function hasFlipping(book) {
3633			var hasFlipping = false;
3634			for (var pageCount = 0; pageCount < book.pages.length; pageCount++) {
3635				var page = book.pages[pageCount];
3636				if (page.isFlipping == true) {
3637					hasFlipping = true;
3638					break;
3639				}
3640			}
3641			return hasFlipping;
3642		}
3643
3644		function BookCSS(parameters, container) {
3645			//parameters = extendOptions(parameters);
3646
3647			//_super.call(this, parameters, stage);
3648			var _this = this;
3649			_this.type = "BookCSS";
3650			_this.images = parameters.images || [];
3651			_this.pageCount = parameters.pageCount || 2;
3652			//_this.segments = parameters.segments = 5;
3653
3654			_this.foldSense = 50;
3655
3656			_this.stackCount = 4;
3657			_this.mode = "css";
3658			_this.pages = [];
3659			_this.duration = parameters.duration;
3660
3661			_this.container = $(container);
3662			_this.options = parameters;
3663			_this.drag = drag.none;
3664			_this.pageCount = (_this.pageCount == 1 ? _this.pageCount : Math.ceil(_this.pageCount / 2) * 2);
3665			_this.pageMode = parameters.pageMode || ((isMobile || _this.pageCount <= 2) ? DFLIP.PAGE_MODE.SINGLE
3666				: DFLIP.PAGE_MODE.DOUBLE);
3667
3668			_this.swipe_threshold = isMobile ? 15 : 50;
3669
3670			_this.direction = parameters.direction || DFLIP.DIRECTION.LTR;
3671
3672			_this.startPage = 1;
3673			_this.endPage = _this.pageCount;
3674
3675			_this._activePage = parameters.openPage || _this.startPage;
3676
3677			_this.hardConfig = parameters.hard;
3678			//var foldTime = void 0;
3679			has3d = 'WebKitCSSMatrix' in window || (document.body && 'MozPerspective' in document.body.style);
3680
3681			_this.animateF = function () {
3682				if (TWEEN.getAll().length > 0)
3683					TWEEN.update();
3684				else
3685					clearInterval(_this.animate);
3686			};
3687
3688			_this.init(parameters);
3689
3690			_this.skipDrag = false;
3691
3692			function checkPage(point) {
3693				if (_this.dragPage != point.page && point.page.visible == true) {
3694					_this.dragPage.clearTween(true);
3695					_this.dragPage = point.page;
3696					_this.corner = point.corner;
3697					_this.dragPage.pendingPoint = point;
3698				}
3699			}
3700
3701			var mouseMove = function (event) {
3702					//event.preventDefault();
3703					var point = _this.eventToPoint(event);
3704					if (event.touches !== void 0 && event.touches.length > 1) return;
3705
3706					var targetPage = _this.dragPage || point.page;
3707
3708					if (_this.contentProvider.zoomScale !== 1) {
3709						if ((event.touches !== void 0 || _this.isPanning == true)) {
3710							_this.pan(point);
3711							event.preventDefault();
3712						}
3713					}
3714					else {
3715						if (_this.skipDrag !== true) {
3716							//if (_this.cancelMouse != true) {
3717
3718							var distance = point.distance;//_this.getDistance(event);//point.x < _this.pageWidth ? point.x : _this.fullWidth - point.x;
3719
3720							if (!hasFlipping(_this)) {
3721
3722
3723								if ((_this.dragPage !== void 0 ) || (point.isInside == true)) {
3724									//$(".quick-hint").html(distance);
3725									if (_this.dragPage !== void 0) {
3726										log("set mouse down move");
3727									}
3728									else {
3729										point.y = limitAt(point.y, 1, _this.height - 1);
3730										point.x = limitAt(point.x, 1, point.fullWidth - 1);
3731									}
3732
3733									var corner = _this.corner || point.corner;
3734									if (targetPage.isHard) {
3735										var isRight = corner == DFLIP.CORNERS.BR || corner == DFLIP.CORNERS.TR;
3736
3737										var angle = angleByDistance(point.distance, point.fullWidth);
3738
3739										targetPage.updateAngle(angle * (isRight ? -1 : 1), isRight);
3740
3741									}
3742									else {
3743										targetPage.updatePoint(point, _this);
3744									}
3745
3746									targetPage.magnetic = true;
3747									targetPage.magneticCorner = point.corner;
3748									event.preventDefault();
3749									//point.page.updatePoint(point);
3750								}
3751
3752								if (_this.dragPage == void 0 && targetPage !== void 0 && point.isInside == false && targetPage.magnetic == true) {
3753									targetPage.pendingPoint = point;
3754									targetPage.animateToReset = true;
3755									_this.corner = targetPage.magneticCorner;
3756									_this.animatePage(targetPage);
3757									targetPage.pendingPoint = void 0;
3758									targetPage.magnetic = false;
3759									targetPage.magneticCorner = void 0;
3760								}
3761
3762								if (_this.isPanning == true && _this.dragPage == void 0 && _this.contentProvider.zoomScale == 1) {
3763									//check if swipe has happened
3764									//console.log(_this.lastPos - point.x,performance.now()-_this.lastTime);
3765									var swipe_dist = point.x - _this.lastPos,
3766										swipe_time = performance.now() - _this.lastTime;
3767									if (Math.abs(swipe_dist) > _this.swipe_threshold) {
3768										//swipe has triggered
3769										//_this.dragPage.pendingPoint = point;
3770										if (swipe_dist < 0) {
3771											_this.next();
3772										}
3773										else {
3774											_this.prev();
3775										}
3776										_this.drag = drag.none;
3777										_this.isPanning = false;
3778										event.preventDefault();
3779									}
3780									_this.lastPos = point.x;
3781									_this.lastTime = performance.now();
3782
3783								}
3784							}
3785						}
3786					}
3787
3788				},
3789				mouseUp = function (event) {
3790
3791					_this.isPanning = false;
3792					if (event.touches !== void 0 && event.touches.length > 1) return;
3793					if (_this.skipDrag !== true) {
3794						//completeFold();
3795
3796						if (_this.dragPage) {
3797							event.preventDefault();
3798
3799							/*							if (_this.animate !== void 0) {
3800							 clearInterval(_this.animate);
3801							 }
3802
3803							 _this.animate = setInterval(_this.animateF, 30);
3804
3805							 _this.dragPage.tween(point);*/
3806
3807							//use something like pending point
3808							// detect the next page anbd call the updatepage
3809							//will be better
3810							var point = _this.eventToPoint(event);
3811							_this.dragPage.pendingPoint = point;
3812							if (point.x == _this.startPoint.x && point.y == _this.startPoint.y && point.isInside == true) {
3813
3814								if (_this.corner == DFLIP.CORNERS.BR || _this.corner == DFLIP.CORNERS.TR) {
3815									checkPage(point);
3816									if (_this.dragPage.isFlipping !== true)
3817										_this.next();
3818								}
3819								else if (_this.corner == DFLIP.CORNERS.BL || _this.corner == DFLIP.CORNERS.TL) {
3820									checkPage(point);
3821									if (_this.dragPage.isFlipping !== true)
3822										_this.prev();
3823								}
3824							}
3825							else if (_this.dragPage.isFlipping !== true) {
3826								if (point.distance > point.fullWidth / 2) {
3827									if (point.x > point.fullWidth / 2)
3828										_this.prev();
3829									else
3830										_this.next();
3831								}
3832								else {
3833									_this.dragPage.animateToReset = true;
3834									_this.animatePage(_this.dragPage);
3835								}
3836							}
3837							//_this.dragPage.animateToReset = true;
3838							if (_this.dragPage) {
3839								_this.dragPage.pendingPoint = void 0;
3840								_this.dragPage.magnetic = false;
3841							}
3842						}
3843
3844						_this.drag = drag.none;
3845
3846						//_this.dragPage = void 0;
3847						//_this.corner = DFLIP.CORNERS.NONE;
3848						//log("set mouse up");
3849					}
3850
3851				},
3852				mouseDown = function (event) {
3853					if (event.touches !== void 0 && event.touches.length > 1) return;
3854					var point = _this.eventToPoint(event);
3855					_this.startPoint = point;
3856					_this.left = _this.left || 0;
3857					_this.top = _this.top || 0;
3858					_this.isPanning = true;
3859					_this.lastPos = point.x;
3860					_this.lastTime = performance.now();
3861
3862					if (_this.skipDrag !== true) {
3863
3864						if (point.isInside == true && !hasFlipping(_this)) {
3865							_this.startPoint = point;
3866							_this.drag = point.drag;
3867							_this.dragPage = point.page;
3868
3869							_this.corner = point.corner;
3870
3871							log(_this.corner);
3872
3873							updateFolding(_this.dragPage);
3874							//log("set mouse down");
3875							if (point.page.isHard) {
3876
3877							}
3878							else {
3879								point.page.updatePoint(point, _this);
3880							}
3881							if (point.page.name == "0") {
3882								_this.shadow.css({
3883									width: '50%',
3884									left: _this.direction == DFLIP.DIRECTION.RTL ? 0 : '50%',
3885									transitionDelay: ''
3886								});
3887							} else if (point.page.name == Math.ceil(_this.pageCount / 2) - 1) {
3888								_this.shadow.css({
3889									width: '50%',
3890									left: _this.direction == DFLIP.DIRECTION.RTL ? '50%' : 0,
3891									transitionDelay: ''
3892								});
3893							}
3894						}
3895					}
3896				},
3897				onMouseWheel = function (event) {
3898					var delta = 0;
3899
3900					//var zoom = _this.contentProvider.zoomScale > 1;
3901					if (event.wheelDelta != void 0) { // WebKit / Opera / Explorer 9
3902
3903						delta = event.wheelDelta / 120;
3904
3905					} else if (event.detail !== void 0) { // Firefox
3906
3907						delta = -event.detail / 3;
3908
3909					}
3910
3911					var zoom1 = _this.contentProvider.zoomScale,
3912						maxZoom = _this.contentProvider.maxZoom;
3913
3914					if (delta) {
3915
3916						if ((delta > 0 && zoom1 < maxZoom) || (delta < 0 && zoom1 > 1)) {
3917
3918							event.stopPropagation();
3919							event.preventDefault();
3920
3921							var pointOld = _this.eventToPoint(event);
3922							var pointNew = _this.eventToPoint(event);
3923
3924							var origin = {x: _this.container.width() / 2, y: -23 + _this.container.height() / 2};
3925
3926							_this.previewObject.zoom(delta);
3927
3928							var zoom2 = _this.contentProvider.zoomScale;
3929							if (zoom1 !== zoom2) {
3930								var dz = (zoom2 / zoom1);
3931
3932								//fix zoom to previous center
3933								if (zoom2 == 1) {
3934									_this.left = 0;
3935									_this.top = 0;
3936								} else {
3937									_this.left *= dz;
3938									_this.top *= dz;
3939								}
3940
3941								//fix zoom to previous pointer
3942								var dx = (pointOld.raw.x - origin.x ) * dz,
3943									dy = (pointOld.raw.y - origin.y ) * dz;
3944
3945								pointNew.raw.x = origin.x + dx;// origin.x + dz * (point.x-origin.x);
3946								pointNew.raw.y = origin.y + dy;// origin.y + dz * (point.y-origin.y);
3947
3948								_this.startPoint = pointNew;
3949								//console.log(pointOld.raw.x - origin.x,dx,pointOld.raw.y - origin.y,dy,pointNew.raw,_this.startPoint.raw);
3950								_this.pan(pointOld);
3951
3952								var targetPage = _this.dragPage || pointOld.page;
3953								if (_this.dragPage == void 0 && targetPage !== void 0 && pointOld.isInside == true && targetPage.magnetic == true) {
3954									targetPage.pendingPoint = pointOld;
3955									targetPage.animateToReset = true;
3956									_this.corner = targetPage.magneticCorner;
3957									_this.animatePage(targetPage);
3958									targetPage.pendingPoint = void 0;
3959									targetPage.magnetic = false;
3960									targetPage.magneticCorner = void 0;
3961								}
3962							}
3963
3964						}
3965					}
3966
3967				};
3968
3969			var containerDom = _this.container[0];
3970			var stageDom = _this.stage[0];
3971			if (containerDom) {
3972				containerDom.addEventListener("mousemove", mouseMove, false);
3973				containerDom.addEventListener("touchmove", mouseMove, false);
3974
3975				containerDom.addEventListener("mousedown", mouseDown, false);
3976				containerDom.addEventListener("mouseup", mouseUp, false);
3977				containerDom.addEventListener("touchend", mouseUp, false);
3978				containerDom.addEventListener("touchstart", mouseDown, false);
3979
3980				if (_this.options.scrollWheel == true) {
3981					//lets not trigger scroll when in outline or another
3982					stageDom.addEventListener('mousewheel', onMouseWheel, false);
3983					stageDom.addEventListener('DOMMouseScroll', onMouseWheel, false); // firefox
3984				}
3985			}
3986
3987			this.dispose = function () {
3988				containerDom.removeEventListener("mousemove", mouseMove, false);
3989				containerDom.removeEventListener("touchmove", mouseMove, false);
3990
3991				containerDom.removeEventListener("mousedown", mouseDown, false);
3992				containerDom.removeEventListener("mouseup", mouseUp, false);
3993				containerDom.removeEventListener("touchend", mouseUp, false);
3994				containerDom.removeEventListener("touchstart", mouseDown, false);
3995
3996				if (_this.options.scrollWheel == true) {
3997					stageDom.removeEventListener('mousewheel', onMouseWheel, false);
3998					stageDom.removeEventListener('DOMMouseScroll', onMouseWheel, false); // firefox
3999				}
4000				_this.flipCallback = null;
4001				_this.animateF = null;
4002				_this.stage.remove();
4003
4004			};
4005
4006			/*            _this.container.on("mousemove", function (event) {
4007
4008			 }).on(mouseEvents.start, function (event) {
4009
4010			 }).on(mouseEvents.end, function () {
4011
4012			 });*/
4013		}
4014
4015		function isPageHard(setting, pageNumber) {
4016			return true;
4017		}
4018
4019		BookCSS.prototype = {
4020			add: function (object) {
4021				if (object instanceof PageCSS)
4022					this.container.append($(object.element));
4023				else
4024					this.container.append($(object));
4025			},
4026			pan: function (point) {
4027				var origin = this.startPoint;
4028				var scale = this.contentProvider.zoomScale;
4029
4030				var left = (this.left + (point.raw.x - origin.raw.x)),
4031					top = (this.top + (point.raw.y - origin.raw.y));
4032
4033				this.left = limitAt(left, -this.shiftWidth, this.shiftWidth);
4034				this.top = limitAt(top, -this.shiftHeight, this.shiftHeight);
4035
4036				this.startPoint = point;
4037
4038				//console.log(point, origin);
4039				this.stage.css({
4040					transform: "translate3d(" + this.left + "px," + this.top + "px,0)"
4041				});
4042
4043				//var a = book.wrapper.height();
4044			},
4045			getPageByNumber: function (pageNumber) {
4046				var relativePageNumber = Math.floor((pageNumber - 1) / 2);
4047				var page;
4048				for (var count = 0; count < this.pages.length; count++) {
4049					if (relativePageNumber == parseInt(this.pages[count].name, 10))
4050						page = this.pages[count];
4051				}
4052				return page;
4053			},
4054			getPageSide: function (pageNumber) {
4055
4056				var isRTL = this.direction == DFLIP.DIRECTION.RTL;
4057
4058				var page = this.getPageByNumber(pageNumber);
4059				if (page == void 0) return;
4060				if (pageNumber % 2 == 0)
4061					return isRTL ? page.back : page.front;
4062				else
4063					return isRTL ? page.front : page.back;
4064			},
4065			getContentLayer: function (pageNumber) {
4066				var pageSide = this.getPageSide(pageNumber);
4067				return pageSide == void 0 ? void 0 : pageSide.contentLayer;
4068			}
4069		};
4070
4071		BookCSS.prototype.init = function (parameters) {
4072			var _this = this;
4073			_this.stage = $(html.div, {
4074				class: "df-book-stage"
4075			});
4076			_this.wrapper = $(html.div, {
4077				class: "df-book-wrapper"
4078			});
4079			_this.shadow = $(html.div, {
4080				class: "df-book-shadow"
4081			});
4082			//_this.resize();
4083			_this.container.append(_this.stage);
4084			_this.stage.append(_this.wrapper);
4085			_this.wrapper.append(_this.shadow);
4086			/*			_this.nextButton = $(html.div, {
4087			 class: "df-book-next-button df-book-side-buttons " + parameters.icons['altnext']
4088			 }).appendTo(_this.wrapper).on("click", function () {
4089			 _this.next();
4090			 });
4091			 _this.prevButton = $(html.div, {
4092			 class: "df-book-prev-button df-book-side-buttons " + parameters.icons['altprev']
4093			 }).appendTo(_this.wrapper).on("click", function () {
4094			 _this.prev();
4095			 });*/
4096
4097
4098			//_this.container.height(parameters.height);
4099
4100			_this.createStack(parameters);
4101		};
4102
4103		BookCSS.prototype.createStack = function (parameters) {
4104
4105			var colors = "red,green,blue,yellow,orange,black".split(",");
4106
4107			for (var _stackCount = 0; _stackCount < this.stackCount; _stackCount++) {
4108				parameters.angles = [, this.stackCount - _stackCount];//[1] = (this.stackCount - _stackCount);
4109				parameters.stiffness = (this.stackCount - _stackCount) / 100;
4110
4111				var clone = new PageCSS(parameters);
4112				clone.angles[1] = 180;
4113				clone.index = _stackCount;
4114				clone.parent = this;
4115				clone.textureReady = false;
4116				clone.textureRequested = false;
4117				this.wrapper.append(clone.element);
4118				clone.isFlipping = false;
4119				this.pages.push(clone);
4120				clone.color = colors[_stackCount];
4121				//for (var _count = 0; _count < 4; _count++) {
4122				//    clone.element.css({
4123				//        backgroundColor : colors[_stackCount]
4124				//    });
4125				//}
4126			}
4127
4128			this.children = this.pages;
4129		};
4130
4131		BookCSS.prototype.isPageHard = function (pageNumber) {
4132
4133			if (this.hardConfig !== void 0) {
4134
4135				var config = this.hardConfig;
4136
4137				if (config == "cover") {
4138					return pageNumber == 0  //front cover is 0
4139					|| pageNumber == (Math.floor(this.pageCount / 2) - 1); //start with 0 so 1 minus
4140				}
4141				else if (config == "all") {
4142					return true;
4143				}
4144				else {
4145					var baseTest = ("," + config + ",").indexOf("," + (pageNumber * 2 + 1) + ",") > -1;
4146					var nextTest = ("," + config + ",").indexOf("," + (pageNumber * 2 + 2) + ",") > -1;
4147					return baseTest || nextTest;
4148
4149				}
4150			}
4151			return false;
4152		};
4153
4154		BookCSS.prototype.setDuration = function (_duration) {
4155			this.duration = _duration;
4156		};
4157
4158		/*		BookCSS.prototype.next = function (step) {
4159		 if(step ==void 0) step = this.pageMode;
4160		 var nextPage = this._activePage + step;
4161		 if (nextPage > this.pageCount) {
4162		 nextPage = this.pageCount;
4163		 }
4164		 if (this._activePage != nextPage)
4165		 this.gotoPage(nextPage);
4166		 };
4167
4168		 BookCSS.prototype.prev = function (step) {
4169		 if(step ==void 0) step =this.pageMode;
4170		 var prevPage = this._activePage - step;
4171		 if (prevPage < 1) {
4172		 prevPage = 1;
4173		 }
4174		 if (this._activePage != prevPage)
4175		 this.gotoPage(prevPage);
4176		 };*/
4177		BookCSS.prototype.moveBy = function (step) {
4178			var nextPage = this._activePage + step;
4179
4180			nextPage = limitAt(nextPage, this.startPage, this.endPage);
4181
4182			this.gotoPage(nextPage);
4183		};
4184
4185		BookCSS.prototype.next = function (step) {
4186			if (step == void 0)
4187				step =
4188					(this.direction == DFLIP.DIRECTION.RTL)
4189						? -this.pageMode : this.pageMode;
4190
4191			this.moveBy(step);
4192		};
4193
4194		BookCSS.prototype.prev = function (step) {
4195			if (step == void 0)
4196				step =
4197					(this.direction == DFLIP.DIRECTION.RTL)
4198						? this.pageMode : -this.pageMode;
4199
4200			this.moveBy(step);
4201		};
4202		BookCSS.prototype.eventToPoint = function (event) {
4203
4204			event = fixMouseEvent(event);
4205
4206			var wrapper = this.wrapper,
4207				pages = this.pages,
4208				pageWidth = this.pageWidth,
4209				fullWidth = this.fullWidth,
4210				height = this.height,
4211				win = $(window),
4212				point = {x: event.clientX, y: event.clientY};
4213
4214			var left = point.x - wrapper[0].getBoundingClientRect().left;// + win['scrollLeft']();
4215
4216			var top = point.y - wrapper[0].getBoundingClientRect().top;// + win['scrollTop']();
4217
4218			point.x = point.x - this.container[0].getBoundingClientRect().left;
4219			point.y = point.y - this.container[0].getBoundingClientRect().top;
4220
4221			var distance = (this.drag == drag.none)
4222				? left < pageWidth ? left : fullWidth - left
4223				: this.drag == drag.left ? left : fullWidth - left;
4224
4225			var page = //((left >= 0 && left <= fullWidth)?
4226				(left < pageWidth ? pages[this.stackCount / 2 - 1] : pages[this.stackCount / 2]);
4227
4228			var pageDrag = left < this.foldSense ? drag.left
4229				: (left > fullWidth - this.foldSense) ? drag.right : drag.none;
4230
4231			//determine the corner
4232			var x = left,
4233				y = top,
4234				h = height,
4235				w = fullWidth,
4236				delta = this.foldSense,
4237				corners = DFLIP.CORNERS,
4238				corner;
4239
4240			if (x >= 0 && x < delta) {
4241				if (y >= 0 && y <= delta)
4242					corner = corners.TL;
4243				else if (y >= h - delta && y <= h)
4244					corner = corners.BL;
4245				else if (y > delta && y < h - delta)
4246					corner = corners.L;
4247				else
4248					corner = corners.NONE;
4249			}
4250			else if (x >= w - delta && x <= w) {
4251				if (y >= 0 && y <= delta)
4252					corner = corners.TR;
4253				else if (y >= h - delta && y <= h)
4254					corner = corners.BR;
4255				else if (y > delta && y < h - delta)
4256					corner = corners.R;
4257				else
4258					corner = corners.NONE;
4259			}
4260			else
4261				corner = corners.NONE;
4262
4263			return {
4264				isInside: corner !== corners.NONE && corner !== corners.L && corner !== corners.R,
4265				x: left,
4266				y: top,
4267				fullWidth: fullWidth,
4268				rawDistance: fullWidth - left,
4269				distance: distance,
4270				page: page,
4271				drag: pageDrag,
4272				foldSense: this.foldSense,
4273				event: event,
4274				raw: point,
4275				corner: corner
4276			};
4277		};
4278
4279		BookCSS.prototype.gotoPage = function (pageNumber) {
4280			pageNumber = parseInt(pageNumber, 10);
4281			this._activePage = pageNumber;
4282			this.updatePage(pageNumber);
4283		};
4284
4285		BookCSS.prototype.refresh = function () {
4286			this.updatePage(this._activePage);
4287			if (this.flipCallback !== void 0) this.flipCallback();
4288		};
4289
4290		BookCSS.prototype.updatePage = function (pageNumber) {
4291
4292			var isRTL = (this.direction == DFLIP.DIRECTION.RTL);
4293
4294			pageNumber = Math.floor((pageNumber / 2));
4295
4296			if (isRTL) pageNumber = Math.floor(this.pageCount / 2) - pageNumber;
4297
4298			var oldBaseNumber = this.oldBaseNumber || 0;
4299			var pageCount = this.pageCount / 2;
4300			var stackCount = this.stackCount;
4301
4302			var midPoint = Math.floor(stackCount / 2);
4303
4304			if (oldBaseNumber > pageNumber) {
4305				this.children[stackCount - 1].skipFlip = true;
4306				this.children.unshift(this.children.pop());
4307			}
4308			else if (oldBaseNumber < pageNumber) {
4309				this.children[0].skipFlip = true;
4310				this.children.push(this.children.shift());
4311			}
4312
4313			/*            if(oldBaseNumber !==pageNumber){
4314			 var tweens = TWEEN.getAll();
4315			 for(var count = 0; count< tweens.length ;
4315 count++){
4316			 var tween = tweens[0];
4317			 if(tween.parent!==void 0){
4318			 tween.stop();
4319			 }
4320			 }
4321			 }*/
4322
4323			for (var _pageCount = 0; _pageCount < stackCount; _pageCount++) {
4324				var page = this.children[_pageCount];
4325
4326				if (oldBaseNumber !== pageNumber) {
4327					if (page.currentTween !== void 0) {
4328						page.clearTween(true);
4329						//page.currentTween.stop();
4330						//page.completeTween(true);
4331						//page.resetCSS();
4332						//page.currentTween = null;
4333					}
4334				}
4335				var oldSide = page.side;
4336				var newSide;
4337				var relativePageNumber = pageNumber - midPoint + _pageCount;
4338				var oldName = page.name;
4339
4340				page.isHard = this.isPageHard(relativePageNumber);
4341				if (page.isHard) {
4342					page.element.addClass("df-hard-page");
4343				} else {
4344					page.element.removeClass("df-hard-page");
4345					page.front.css({display: "block"});
4346					page.back.css({display: "block"});
4347				}
4348				var oldPageNumber = $(page.element).attr("pageNumber");
4349				if (oldPageNumber != relativePageNumber) {
4350					page.front.contentLayer.empty();
4351					page.back.contentLayer.empty();
4352				}
4353				$(page.element).attr("pageNumber", relativePageNumber);
4354				page.visible = (relativePageNumber >= 0 && relativePageNumber < pageCount);
4355
4356				if (this.requestPage !== void 0 && page.visible == true) {
4357					if (isRTL) relativePageNumber = Math.floor(this.pageCount / 2) - relativePageNumber - 1;
4358					page.name = relativePageNumber.toString();
4359					if (page.name != oldName) {
4360
4361						page.backTextureLoaded = false;
4362						page.frontTextureLoaded = false;
4363						page.thumbLoaded = false;
4364						this.requestPage(relativePageNumber * 2 + 1);
4365						this.requestPage(relativePageNumber * 2 + 2);
4366
4367					}
4368				}
4369
4370				//Sizing
4371				page.isEdge = false; //true;
4372				if (_pageCount == 0) {
4373
4374				}
4375				else if (_pageCount == stackCount - 1) {
4376
4377				}
4378				else {
4379
4380					page.isEdge = false;
4381				}
4382
4383
4384				if (_pageCount < midPoint) {
4385					newSide = drag.left;
4386				}
4387				else {
4388					newSide = drag.right;
4389				}
4390
4391
4392				if (page.isFlipping == false) {
4393
4394					if (newSide !== oldSide && page.skipFlip == false) {
4395
4396						this.animatePage(page);
4397
4398						if (this.preFlipCallback !== void 0)
4399							this.preFlipCallback();
4400
4401					} else {
4402						page.skipFlip = false;
4403						page.element.removeClass("df-flipping df-quick-turn df-folding df-left-side df-right-side");
4404						page.element.addClass((_pageCount < midPoint) ? "df-left-side" : "df-right-side");
4405						page.side = newSide;
4406					}
4407				}
4408				page.oldDepth = page.depth;
4409				page.updateCSS({
4410					display: page.visible == true ? "block" : "none",
4411					zIndex: 6 + (_pageCount < midPoint ? (_pageCount - midPoint) : (midPoint - _pageCount)),
4412					transform: ''
4413				});
4414
4415				if (page.pendingPoint == void 0) {
4416					page.resetCSS();
4417				}
4418			}
4419
4420			if (TWEEN.getAll().length == 0) {
4421				clearInterval(this.animate);
4422			}
4423			$(".quick-hint").html(pageNumber);
4424
4425			this.oldBaseNumber = pageNumber;
4426
4427			if (this.updatePageCallback !== void 0)
4428				this.updatePageCallback();
4429
4430		};
4431
4432		BookCSS.prototype.animatePage = function (page) {
4433			page.element.addClass("df-flipping");
4434			page.isFlipping = true;
4435
4436			if (this.animate !== void 0) {
4437				clearInterval(this.animate);
4438			}
4439
4440			this.animate = setInterval(this.animateF, 30);
4441
4442			page.tween(page.pendingPoint);
4443		};
4444
4445		return BookCSS;
4446	})({});
4447
4448	var FlipBook = (function (_super) {
4449
4450		__extends(FlipBook, _super);
4451
4452		function FlipBook(container, source, parameters) {
4453			_super.call(this, parameters);
4454			var _this = this;
4455
4456			_this.type = "FlipBook";
4457			_this.container = container;
4458			_this.options = parameters;
4459			_this.options.source = source;
4460			_this.contentSource = source;
4461
4462			if (parameters.height !== void 0 && parameters.height.toString().indexOf('%') < 0) {
4463				_this.container.height(Math.min(parameters.height, $(window).height()));
4464			} else {
4465				_this.container.height(parameters.height);
4466			}
4467
4468			if (!_this.options.isLightBox && _this.container.attr("id") !== void 0) {
4469				_this.options.id = _this.container.attr("id");
4470			}
4471
4472			if (_this.options.parsed !== true && _this.options.links != void 0) {
4473				DFLIP.parseLinks(_this.options.links);
4474			}
4475			var webgl = _this.webgl = parameters.webgl == true && hasWebgl == true;
4476
4477			container.addClass("df-container df-loading df-init df-floating");
4478
4479			if (_this.options.transparent == true) {
4480				container.addClass("df-transparent");
4481			}
4482			_this.container.info = $(html.div, {
4483				class: "loading-info"
4484			}).appendTo(_this.container).html("Loading...");
4485
4486			if (navigator.userAgent.indexOf('MSIE') !== -1
4487				|| navigator.appVersion.indexOf('Trident/') > 0) {
4488				_this.options.webgl = false; //IE 11
4489			}
4490
4491			if (!!navigator.userAgent.match(/msie\s[5-9]/i)) {
4492				_this.container.info.html("Your browser (Internet Explorer) is out of date to run DFlip Flipbook Plugin. <br><a href='http://browsehappy.com/'>Upgrade to a new one</a>").addClass("df-old-browser");
4493				container.removeClass("df-loading");
4494				return _this;
4495			}
4496
4497			_this.container.css({
4498				position: "relative",
4499				overflow: "hidden",
4500				backgroundColor: parameters.backgroundColor,
4501				backgroundImage: "url('" + parameters.backgroundImage + "')"
4502			});
4503
4504			_this.init(webgl, source);
4505
4506			if (_this.options.onCreate !== void 0)
4507				_this.options.onCreate();
4508
4509			return _this;
4510
4511		}
4512
4513		FlipBook.prototype.init = function (webgl) {
4514			var _this = this;
4515			var book = _this.target;
4516
4517			var options = _this.options;
4518
4519			if (webgl == true) {
4520
4521				var updateMockupJs = function (callback) {
4522
4523					var process3d = function () {
4524						MOCKUP.defaults.anisotropy = 0;
4525						MOCKUP.defaults.groundTexture = "blank";
4526						THREE.skipPowerOfTwo = true;
4527
4528						RegisterMockupObjects();
4529
4530						if (callback !== void 0) callback();
4531					};
4532
4533					if (window.MOCKUP == void 0) {
4534						_this.updateInfo("Loading WEBGL 3D ...");
4535						getScript(defaults.threejsSrc + "?ver=" + DFLIP.version, function () {
4536							_this.updateInfo("Loading 3D Pages ...");
4537							getScript(defaults.mockupjsSrc + "?ver=" + DFLIP.version, function () {
4538								process3d();
4539							});
4540						});
4541					}
4542					else {
4543						process3d();
4544					}
4545				};
4546
4547				updateMockupJs(function () {
4548
4549					//Todo: ability to use anisotropy
4550
4551					_this.container.css({
4552						minHeight: 300,
4553						minWidth: 300
4554					});
4555
4556					_this.stage = new PreviewStage(extendOptions(_this.options, {container: _this.container}));
4557					_this.stage.previewObject = _this;
4558
4559					_this.contentProvider = new ContentProvider(_this.contentSource, function (contentProvider) {
4560						var options = {
4561							pageCount: contentProvider.pageCount,//Math.ceil(contentProvider.pageCount / 2) * 2,
4562							stackCount: 6,
4563							segments: 20,
4564							width: 300 * contentProvider.pageRatio,
4565							height: 300
4566						};
4567
4568						_this.checkOpenPage();
4569						_this.target = book = _this.stage.target = new MOCKUP.Book(extendOptions(_this.options, options), _this.stage);
4570
4571						createUI(_this.container, _this);
4572
4573						//bookStage.setTarget(_this.target);
4574						book.ui = _this.ui;
4575						book.container = _this.container;
4576						contentProvider.webgl = webgl;
4577						contentProvider.setTarget(_this.target);
4578
4579						book.getContentLayer = function (pageNumber) {
4580
4581							var isRTL = book.direction == DFLIP.DIRECTION.RTL,
4582								left = _this.stage.cssScene.divLeft.element,
4583								right = _this.stage.cssScene.divRight.element;
4584
4585							var baseActive = getBasePage(book._activePage);
4586
4587							//if(isRTL){
4588							//	if(pageNumber == 0 || pageNumber == 1) return right;
4589							//	if(pageNumber == book.pageCount) return left;
4590							//}
4591
4592							if (pageNumber % 2 == 0)
4593								return isRTL ? right : left;
4594							else
4595								return isRTL ? left : right;
4596							//else
4597							//	return void 0;
4598						};
4599						book.stage = _this.stage;
4600
4601						book.flipCallback = function () {
4602							_this.contentProvider.review("flipCallback");
4603
4604							var baseActive = getBasePage(book._activePage);
4605
4606							var width, height;
4607							var pageLeft = book.getPageByNumber(baseActive),
4608								pageRight = book.getPageByNumber(baseActive + 1);
4609							//if (page3d !== void 0) {
4610							//    var isLeft = (pageNumber % 2 == 0);
4611							var divLeft = book.parent.cssScene.divLeft,
4612								divRight = book.parent.cssScene.divRight;
4613
4614							var isSingle = book.pageMode == DFLIP.PAGE_MODE.SINGLE;
4615							var isRTL = book.direction == DFLIP.DIRECTION.RTL;
4616
4617							if (pageLeft !== void 0 && divLeft !== void 0) {
4618								width = Math.abs(pageLeft.geometry.boundingBox.max.x - pageLeft.geometry.boundingBox.min.x);
4619								height = Math.abs(pageLeft.geometry.boundingBox.max.z - pageLeft.geometry.boundingBox.min.z);
4620
4621								divLeft.rotation.y = -Math.atan2(height, width) * 0.9;
4622								divLeft.position.z = height * 0.8;
4623								divLeft.position.x = height / 2.5;
4624								$(divLeft.element).css({
4625									width: width,
4626									left: -width / 2//baseActive == 0 && isRTL == true? width
4627									//: baseActive == book.pageCount && isRTL == true ? 0 : -width / 2
4628								});
4629
4630							}
4631
4632							if (pageRight !== void 0 && divRight !== void 0) {
4633								width = Math.abs(pageRight.geometry.boundingBox.max.x - pageRight.geometry.boundingBox.min.x);
4634								height = Math.abs(pageRight.geometry.boundingBox.max.z - pageRight.geometry.boundingBox.min.z);
4635
4636								divRight.rotation.y = Math.atan2(height, width) * 0.9;
4637								divRight.position.z = height * 0.8;
4638								divRight.position.x = -height / 2.5;
4639								$(divRight.element).css({
4640									width: width,
4641									left: width / 2// == 0 && isRTL == true ? 0
4642									//: baseActive == book.pageCount && isRTL == true ? -width : width / 2
4643								});
4644
4645							}
4646
4647							if (_this.options.onFlip !== void 0)
4648								_this.options.onFlip();
4649						};
4650
4651						book.resize = function () {
4652							_this.resize();
4653						}();
4654
4655						book.updatePageCallback = function () {
4656							_this.ui.update();
4657							_this.checkCenter();
4658							_this.stage.renderRequestPending = true;
4659						};
4660
4661						var divLeft = $(_this.stage.cssScene.divLeft.element);
4662						var divRight = $(_this.stage.cssScene.divRight.element);
4663
4664						book.preFlipCallback = function () {
4665							divLeft.empty();
4666							divRight.empty();
4667							if (_this.options.beforeFlip !== void 0)
4668								_this.options.beforeFlip();
4669
4670							_this.playSound();
4671						};
4672
4673						$(window).trigger("resize");
4674
4675						divLeft.css({
4676							width: 300 * contentProvider.pageRatio,
4677							height: 300,
4678							left: -300 * contentProvider.pageRatio / 2
4679						});
4680
4681						divRight.css({
4682							width: 300 * contentProvider.pageRatio,
4683							height: 300,
4684							left: 300 * contentProvider.pageRatio / 2
4685						});
4686
4687						book.ease = TWEEN.Easing.Cubic.InOut;
4688						//book.ease = TWEEN.Easing.Quadratic.InOut;
4689						book.contentProvider = contentProvider;
4690						book.duration = _this.options.duration;
4691						book.gotoPage(book._activePage);
4692						book.flipCallback();
4693
4694						if (_this.options.onReady !== void 0)
4695							_this.options.onReady();
4696
4697					}, options, _this);
4698				});
4699			}
4700			else {
4701
4702				_this.contentProvider = new ContentProvider(_this.contentSource, function (contentProvider) {
4703					var options = {
4704						pageCount: contentProvider.pageCount//Math.ceil(contentProvider.pageCount / 2) * 2
4705					};
4706
4707					_this.checkOpenPage();
4708					_this.target = book = new BookCSS(extendOptions(_this.options, options), _this.container);
4709					_this.target.previewObject = _this;
4710
4711					createUI(_this.container, _this);
4712					contentProvider.webgl = webgl;
4713					contentProvider.setTarget(_this.target);
4714					contentProvider.waitPeriod = 2;
4715					book.ease = TWEEN.Easing.Quadratic.InOut;
4716					book.duration = _this.options.duration;
4717
4718					/*					_this.ui.prev.hide();
4719					 _this.ui.next.hide();
4720
4721					 _this.ui.prev = book.prevButton;
4722					 _this.ui.next = book.nextButton;*/
4723
4724					book.container = _this.container;
4725					book.updatePageCallback = function () {
4726						_this.ui.update();
4727						_this.checkCenter();
4728					};
4729
4730					book.gotoPage(book._activePage);
4731
4732					book.resize = function () {
4733						_this.resize();
4734					}();
4735
4736					$(window).trigger("resize");
4737
4738					book.flipCallback = function () {
4739						_this.contentProvider.review("flipCallback");
4740
4741						if (_this.options.onFlip !== void 0)
4742							_this.options.onFlip();
4743
4744					};
4745
4746					book.preFlipCallback = function () {
4747						if (_this.options.beforeFlip !== void 0)
4748							_this.options.beforeFlip();
4749
4750						_this.playSound();
4751					};
4752
4753					if (_this.options.onReady !== void 0)
4754						_this.options.onReady();
4755
4756				}, options, _this);
4757
4758			}
4759
4760		};
4761
4762		FlipBook.prototype.getURLHash = function () {
4763			if (this.options.id != void 0) {
4764				var hash = "dflip-" + this.options.id + "/";
4765				if (this.target != void 0 && this.target._activePage != void 0) {
4766					hash += this.target._activePage + "/";
4767				}
4768				window.location.hash = hash;
4769			}
4770			return window.location.href;
4771		};
4772
4773		FlipBook.prototype.checkOpenPage = function () {
4774			//options value is overridden by attribute
4775			if (this.options.id != void 0) {
4776				var book = $("#" + this.options.id);
4777				if (book.length > 0 && book.data("page") !== void 0) {
4778					var pageNumber = parseInt(book.data("page"), 10);
4779					if (!isNaN(pageNumber))
4780						this.options.openPage = pageNumber;
4781				}
4782			}
4783		};
4784
4785		FlipBook.prototype.end = function () {
4786
4787			this.target.gotoPage(this.target.endPage);
4788
4789		};
4790
4791		FlipBook.prototype.gotoPage = function (pageNumber) {
4792
4793			this.target.gotoPage(pageNumber);
4794			if (this.ui !== void 0)this.ui.update();
4795
4796		};
4797
4798		FlipBook.prototype.prev = function () {
4799
4800			this.target.prev();
4801
4802		};
4803
4804		FlipBook.prototype.next = function () {
4805
4806			this.target.next();
4807
4808		};
4809
4810		FlipBook.prototype.updateInfo = function (info) {
4811			if (this.container && this.container.info && this.container.info.html)
4812				this.container.info.html(info);
4813		}
4814		return FlipBook;
4815
4816	})(PreviewObject);
4817
4818	$.fn.extend({
4819
4820		shelf: function () {
4821
4822		},
4823		flipBook: function (source, options) {
4824			return new FlipBook($(this), source, extendDFlipOptions(options));
4825		}
4826	});
4827
4828})(DFLIP, jQuery);
4829
4830
4831//Polyfills
4832
4833/**
4834 * Blob.js Polyfill
4835 * A Blob implementation.
4836 * 2014-07-24
4837 *
4838 * By Eli Grey, http://eligrey.com
4839 * By Devin Samarin, https://github.com/dsamarin
4840 * License: X11/MIT
4841 */
4842(function (view) {
4843	"use strict";
4844
4845	view.URL = view.URL || view.webkitURL;
4846
4847	if (view.Blob && view.URL) {
4848		try {
4849			new Blob;
4850			return;
4851		} catch (e) {
4852		}
4853	}
4854
4855	// Internally we use a BlobBuilder implementation to base Blob off of
4856	// in order to support older browsers that only have BlobBuilder
4857	var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function (view) {
4858			var
4859				get_class = function (object) {
4860					return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
4861				}, FakeBlobBuilder = function BlobBuilder() {
4862					this.data = [];
4863				}, FakeBlob = function Blob(data, type, encoding) {
4864					this.data = data;
4865					this.size = data.length;
4866					this.type = type;
4867					this.encoding = encoding;
4868				}, FBB_proto = FakeBlobBuilder.prototype, FB_proto = FakeBlob.prototype, FileReaderSync = view.FileReaderSync, FileException = function (type) {
4869					this.code = this[this.name = type];
4870				}, file_ex_codes = (
4871				"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
4872				+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
4873				).split(" "), file_ex_code = file_ex_codes.length, real_URL = view.URL || view.webkitURL || view, real_create_object_URL = real_URL.createObjectURL, real_revoke_object_URL = real_URL.revokeObjectURL, URL = real_URL, btoa = view.btoa, atob = view.atob, ArrayBuffer = view.ArrayBuffer, Uint8Array = view.Uint8Array, origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
4874				;
4875			FakeBlob.fake = FB_proto.fake = true;
4876			while (file_ex_code--) {
4877				FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
4878			}
4879			// Polyfill URL
4880			if (!real_URL.createObjectURL) {
4881				URL = view.URL = function (uri) {
4882					var
4883						uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a"), uri_origin
4884						;
4885					uri_info.href = uri;
4886					if (!("origin" in uri_info)) {
4887						if (uri_info.protocol.toLowerCase() === "data:") {
4888							uri_info.origin = null;
4889						} else {
4890							uri_origin = uri.match(origin);
4891							uri_info.origin = uri_origin && uri_origin[1];
4892						}
4893					}
4894					return uri_info;
4895				};
4896			}
4897			URL.createObjectURL = function (blob) {
4898				var
4899					type = blob.type, data_URI_header
4900					;
4901				if (type === null) {
4902					type = "application/octet-stream";
4903				}
4904				if (blob instanceof FakeBlob) {
4905					data_URI_header = "data:" + type;
4906					if (blob.encoding === "base64") {
4907						return data_URI_header + ";base64," + blob.data;
4908					} else if (blob.encoding === "URI") {
4909						return data_URI_header + "," + decodeURIComponent(blob.data);
4910					}
4911					if (btoa) {
4912						return data_URI_header + ";base64," + btoa(blob.data);
4913					} else {
4914						return data_URI_header + "," + encodeURIComponent(blob.data);
4915					}
4916				} else if (real_create_object_URL) {
4917					return real_create_object_URL.call(real_URL, blob);
4918				}
4919			};
4920			URL.revokeObjectURL = function (object_URL) {
4921				if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
4922					real_revoke_object_URL.call(real_URL, object_URL);
4923				}
4924			};
4925			FBB_proto.append = function (data/*, endings*/) {
4926				var bb = this.data;
4927				// decode data to a binary string
4928				if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
4929					var
4930						str = "", buf = new Uint8Array(data), i = 0, buf_len = buf.length
4931						;
4932					for (; i < buf_len; i++) {
4933						str += String.fromCharCode(buf[i]);
4934					}
4935					bb.push(str);
4936				} else if (get_class(data) === "Blob" || get_class(data) === "File") {
4937					if (FileReaderSync) {
4938						var fr = new FileReaderSync;
4939						bb.push(fr.readAsBinaryString(data));
4940					} else {
4941						// async FileReader won't work as BlobBuilder is sync
4942						throw new FileException("NOT_READABLE_ERR");
4943					}
4944				} else if (data instanceof FakeBlob) {
4945					if (data.encoding === "base64" && atob) {
4946						bb.push(atob(data.data));
4947					} else if (data.encoding === "URI") {
4948						bb.push(decodeURIComponent(data.data));
4949					} else if (data.encoding === "raw") {
4950						bb.push(data.data);
4951					}
4952				} else {
4953					if (typeof data !== "string") {
4954						data += ""; // convert unsupported types to strings
4955					}
4956					// decode UTF-16 to binary string
4957					bb.push(unescape(encodeURIComponent(data)));
4958				}
4959			};
4960			FBB_proto.getBlob = function (type) {
4961				if (!arguments.length) {
4962					type = null;
4963				}
4964				return new FakeBlob(this.data.join(""), type, "raw");
4965			};
4966			FBB_proto.toString = function () {
4967				return "[object BlobBuilder]";
4968			};
4969			FB_proto.slice = function (start, end, type) {
4970				var args = arguments.length;
4971				if (args < 3) {
4972					type = null;
4973				}
4974				return new FakeBlob(
4975					this.data.slice(start, args > 1 ? end : this.data.length), type, this.encoding
4976				);
4977			};
4978			FB_proto.toString = function () {
4979				return "[object Blob]";
4980			};
4981			FB_proto.close = function () {
4982				this.size = 0;
4983				delete this.data;
4984			};
4985			return FakeBlobBuilder;
4986		}(view));
4987
4988	view.Blob = function (blobParts, options) {
4989		var type = options ? (options.type || "") : "";
4990		var builder = new BlobBuilder();
4991		if (blobParts) {
4992			for (var i = 0, len = blobParts.length; i < len; i++) {
4993				if (Uint8Array && blobParts[i] instanceof Uint8Array) {
4994					builder.append(blobParts[i].buffer);
4995				}
4996				else {
4997					builder.append(blobParts[i]);
4998				}
4999			}
5000		}
5001		var blob = builder.getBlob(type);
5002		if (!blob.slice && blob.webkitSlice) {
5003			blob.slice = blob.webkitSlice;
5004		}
5005		return blob;
5006	};
5007
5008	var getPrototypeOf = Object.getPrototypeOf || function (object) {
5009			return object.__proto__;
5010		};
5011	view.Blob.prototype = getPrototypeOf(new view.Blob());
5012}(window));
5013
5014/**
5015 * canvas-toBlob.js Polyfill
5016 * A canvas.toBlob() implementation.
5017 * 2013-12-27
5018 *
5019 * By Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
5020 * License: X11/MIT
5021 *   See https://github.com/eligrey/canvas-toBlob.js/blob/master/LICENSE.md
5022 */
5023(function (view) {
5024	"use strict";
5025	var
5026		Uint8Array = view.Uint8Array, HTMLCanvasElement = view.HTMLCanvasElement, canvas_proto = HTMLCanvasElement && HTMLCanvasElement.prototype, is_base64_regex = /\s*;\s*base64\s*(?:;|$)/i, to_data_url = "toDataURL", base64_ranks, decode_base64 = function (base64) {
5027			var
5028				len = base64.length, buffer = new Uint8Array(len / 4 * 3 | 0), i = 0, outptr = 0, last = [0, 0], state = 0, save = 0, rank, code;
5029			while (len--) {
5030				code = base64.charCodeAt(i++);
5031				rank = base64_ranks[code - 43];
5032				if (rank !== 255 && rank !== void 0) {
5033					last[1] = last[0];
5034					last[0] = code;
5035					save = (save << 6) | rank;
5036					state++;
5037					if (state === 4) {
5038						buffer[outptr++] = save >>> 16;
5039						if (last[1] !== 61 /* padding character */) {
5040							buffer[outptr++] = save >>> 8;
5041						}
5042						if (last[0] !== 61 /* padding character */) {
5043							buffer[outptr++] = save;
5044						}
5045						state = 0;
5046					}
5047				}
5048			}
5049			// 2/3 chance there's going to be some null bytes at the end, but that
5050			// doesn't really matter with most image formats.
5051			// If it somehow matters for you, truncate the buffer up outptr.
5052			return buffer;
5053		}
5054		;
5055	if (Uint8Array) {
5056		base64_ranks = new Uint8Array([
5057			62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
5058		]);
5059	}
5060	if (HTMLCanvasElement && !canvas_proto.toBlob) {
5061		canvas_proto.toBlob = function (callback, type /*, ...args*/) {
5062			if (!type) {
5063				type = "image/png";
5064			}
5065			if (this.mozGetAsFile) {
5066				callback(this.mozGetAsFile("canvas", type));
5067				return;
5068			}
5069			if (this.msToBlob && /^\s*image\/png\s*(?:$|;)/i.test(type)) {
5070				callback(this.msToBlob());
5071				return;
5072			}
5073
5074			var
5075				args = Array.prototype.slice.call(arguments, 1),
5076				dataURI = this[to_data_url].apply(this, args),
5077				header_end = dataURI.indexOf(","),
5078				data = dataURI.substring(header_end + 1),
5079				is_base64 = is_base64_regex.test(dataURI.substring(0, header_end)),
5080				blob
5081				;
5082			if (Blob.fake) {
5083				// no reason to decode a data: URI that's just going to become a data URI again
5084				blob = new Blob;
5085				if (is_base64) {
5086					blob.encoding = "base64";
5087				} else {
5088					blob.encoding = "URI";
5089				}
5090				blob.data = data;
5091				blob.size = data.length;
5092			} else if (Uint8Array) {
5093				if (is_base64) {
5094					blob = new Blob([decode_base64(data)], {type: type});
5095				} else {
5096					blob = new Blob([decodeURIComponent(data)], {type: type});
5097				}
5098			}
5099			callback(blob);
5100		};
5101
5102		if (canvas_proto.toDataURLHD) {
5103			canvas_proto.toBlobHD = function () {
5104				to_data_url = "toDataURLHD";
5105				var blob = this.toBlob();
5106				to_data_url = "toDataURL";
5107				return blob;
5108			}
5109		} else {
5110			canvas_proto.toBlobHD = canvas_proto.toBlob;
5111		}
5112	}
5113}(window));
5114
5115/**
5116 * performance.now polyfill
5117 **/
5118(function PerformanceNowPolyfill() {
5119
5120	if ('performance' in window === false) {
5121		window.performance = {};
5122	}
5123
5124	// IE 8
5125	Date.now = (Date.now || function () {
5126		return new Date().getTime();
5127	});
5128
5129	if ('now' in window.performance === false) {
5130		var offset = window.performance.timing && window.performance.timing.navigationStart
5131			? window.performance.timing.navigationStart
5132			: Date.now();
5133
5134		window.performance.now = function () {
5135			return Date.now() - offset;
5136		};
5137	}
5138
5139})();
5140
5141/**
5142 * Tween.js - Licensed under the MIT license
5143 * https://github.com/tweenjs/tween.js
5144 */
5145(function TweenJs() {
5146	var TWEEN = TWEEN || (function () {
5147
5148			var _tweens = [];
5149
5150			return {
5151
5152				getAll: function () {
5153
5154					return _tweens;
5155
5156				},
5157
5158				removeAll: function () {
5159
5160					_tweens = [];
5161
5162				},
5163
5164				add: function (tween) {
5165
5166					_tweens.push(tween);
5167
5168				},
5169
5170				remove: function (tween) {
5171
5172					var i = _tweens.indexOf(tween);
5173
5174					if (i !== -1) {
5175						_tweens.splice(i, 1);
5176					}
5177
5178				},
5179
5180				update: function (time) {
5181
5182					if (_tweens.length === 0) {
5183						return false;
5184					}
5185
5186					var i = 0;
5187
5188					time = time !== void 0 ? time : window.performance.now();
5189
5190					while (i < _tweens.length) {
5191
5192						if (_tweens[i].update(time)) {
5193							i++;
5194						} else {
5195							_tweens.splice(i, 1);
5196						}
5197
5198					}
5199
5200					return true;
5201
5202				}
5203			};
5204
5205		})();
5206
5207	TWEEN.Tween = function (object) {
5208
5209		var _object = object;
5210		var _valuesStart = {};
5211		var _valuesEnd = {};
5212		var _valuesStartRepeat = {};
5213		var _duration = 1000;
5214		var _repeat = 0;
5215		var _yoyo = false;
5216		var _isPlaying = false;
5217		var _reversed = false;
5218		var _delayTime = 0;
5219		var _startTime = null;
5220		var _easingFunction = TWEEN.Easing.Linear.None;
5221		var _interpolationFunction = TWEEN.Interpolation.Linear;
5222		var _chainedTweens = [];
5223		var _onStartCallback = null;
5224		var _onStartCallbackFired = false;
5225		var _onUpdateCallback = null;
5226		var _onCompleteCallback = null;
5227		var _onStopCallback = null;
5228
5229		// Set all starting values present on the target object
5230		for (var field in object) {
5231			_valuesStart[field] = parseFloat(object[field], 10);
5232		}
5233
5234		this.to = function (properties, duration) {
5235
5236			if (duration !== void 0) {
5237				_duration = duration;
5238			}
5239
5240			_valuesEnd = properties;
5241
5242			return this;
5243
5244		};
5245
5246		this.start = function (time) {
5247
5248			TWEEN.add(this);
5249
5250			_isPlaying = true;
5251
5252			_onStartCallbackFired = false;
5253
5254			_startTime = time !== void 0 ? time : window.performance.now();
5255			_startTime += _delayTime;
5256
5257			for (var property in _valuesEnd) {
5258
5259				// Check if an Array was provided as property value
5260				if (_valuesEnd[property] instanceof Array) {
5261
5262					if (_valuesEnd[property].length === 0) {
5263						continue;
5264					}
5265
5266					// Create a local copy of the Array with the start value at the front
5267					_valuesEnd[property] = [_object[property]].concat(_valuesEnd[property]);
5268
5269				}
5270
5271				// If `to()` specifies a property that doesn't exist in the source object,
5272				// we should not set that property in the object
5273				if (_valuesStart[property] === void 0) {
5274					continue;
5275				}
5276
5277				_valuesStart[property] = _object[property];
5278
5279				if ((_valuesStart[property] instanceof Array) === false) {
5280					_valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings
5281				}
5282
5283				_valuesStartRepeat[property] = _valuesStart[property] || 0;
5284
5285			}
5286
5287			return this;
5288
5289		};
5290
5291		this.stop = function () {
5292
5293			if (!_isPlaying) {
5294				return this;
5295			}
5296
5297			TWEEN.remove(this);
5298			_isPlaying = false;
5299
5300			if (_onStopCallback !== null) {
5301				_onStopCallback.call(_object);
5302			}
5303
5304			this.stopChainedTweens();
5305			return this;
5306
5307		};
5308
5309		this.stopChainedTweens = function () {
5310
5311			for (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {
5312				_chainedTweens[i].stop();
5313			}
5314
5315		};
5316
5317		this.complete = function () {
5318			if (!_isPlaying) {
5319				return this;
5320			}
5321
5322			TWEEN.remove(this);
5323			_isPlaying = false;
5324
5325			if (_onCompleteCallback !== null) {
5326				_onCompleteCallback.call(_object);
5327			}
5328
5329			this.completeChainedTweens();
5330			return this;
5331		};
5332
5333		this.completeChainedTweens = function () {
5334
5335			for (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {
5336				_chainedTweens[i].complete();
5337			}
5338
5339		};
5340
5341		this.delay = function (amount) {
5342
5343			_delayTime = amount;
5344			return this;
5345
5346		};
5347
5348		this.repeat = function (times) {
5349
5350			_repeat = times;
5351			return this;
5352
5353		};
5354
5355		this.yoyo = function (yoyo) {
5356
5357			_yoyo = yoyo;
5358			return this;
5359
5360		};
5361
5362
5363		this.easing = function (easing) {
5364
5365			_easingFunction = easing == void 0 ? _easingFunction : easing;
5366			return this;
5367
5368		};
5369
5370		this.interpolation = function (interpolation) {
5371
5372			_interpolationFunction = interpolation;
5373			return this;
5374
5375		};
5376
5377		this.chain = function () {
5378
5379			_chainedTweens = arguments;
5380			return this;
5381
5382		};
5383
5384		this.onStart = function (callback) {
5385
5386			_onStartCallback = callback;
5387			return this;
5388
5389		};
5390
5391		this.onUpdate = function (callback) {
5392
5393			_onUpdateCallback = callback;
5394			return this;
5395
5396		};
5397
5398		this.onComplete = function (callback) {
5399
5400			_onCompleteCallback = callback;
5401			return this;
5402
5403		};
5404
5405		this.onStop = function (callback) {
5406
5407			_onStopCallback = callback;
5408			return this;
5409
5410		};
5411
5412		this.update = function (time) {
5413
5414			var property;
5415			var elapsed;
5416			var value;
5417
5418			if (time < _startTime) {
5419				return true;
5420			}
5421
5422			if (_onStartCallbackFired === false) {
5423
5424				if (_onStartCallback !== null) {
5425					_onStartCallback.call(_object);
5426				}
5427
5428				_onStartCallbackFired = true;
5429
5430			}
5431
5432			elapsed = (time - _startTime) / _duration;
5433			elapsed = elapsed > 1 ? 1 : elapsed;
5434
5435			value = _easingFunction(elapsed);
5436
5437			for (property in _valuesEnd) {
5438
5439				// Don't update properties that do not exist in the source object
5440				if (_valuesStart[property] === void 0) {
5441					continue;
5442				}
5443
5444				var start = _valuesStart[property] || 0;
5445				var end = _valuesEnd[property];
5446
5447				if (end instanceof Array) {
5448
5449					_object[property] = _interpolationFunction(end, value);
5450
5451				} else {
5452
5453					// Parses relative end values with start as base (e.g.: +10, -3)
5454					if (typeof (end) === 'string') {
5455
5456						if (end.startsWith('+') || end.startsWith('-')) {
5457							end = start + parseFloat(end, 10);
5458						} else {
5459							end = parseFloat(end, 10);
5460						}
5461					}
5462
5463					// Protect against non numeric properties.
5464					if (typeof (end) === 'number') {
5465						_object[property] = start + (end - start) * value;
5466					}
5467
5468				}
5469
5470			}
5471
5472			if (_onUpdateCallback !== null) {
5473				_onUpdateCallback.call(_object, value);
5474			}
5475
5476			if (elapsed === 1) {
5477
5478				if (_repeat > 0) {
5479
5480					if (isFinite(_repeat)) {
5481						_repeat--;
5482					}
5483
5484					// Reassign starting values, restart by making startTime = now
5485					for (property in _valuesStartRepeat) {
5486
5487						if (typeof (_valuesEnd[property]) === 'string') {
5488							_valuesStartRepeat[property] = _valuesStartRepeat[property] + parseFloat(_valuesEnd[property], 10);
5489						}
5490
5491						if (_yoyo) {
5492							var tmp = _valuesStartRepeat[property];
5493
5494							_valuesStartRepeat[property] = _valuesEnd[property];
5495							_valuesEnd[property] = tmp;
5496						}
5497
5498						_valuesStart[property] = _valuesStartRepeat[property];
5499
5500					}
5501
5502					if (_yoyo) {
5503						_reversed = !_reversed;
5504					}
5505
5506					_startTime = time + _delayTime;
5507
5508					return true;
5509
5510				} else {
5511
5512					if (_onCompleteCallback !== null) {
5513						_onCompleteCallback.call(_object);
5514					}
5515
5516					for (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {
5517						// Make the chained tweens start exactly at the time they should,
5518						// even if the `update()` method was called way past the duration of the tween
5519						_chainedTweens[i].start(_startTime + _duration);
5520					}
5521
5522					return false;
5523
5524				}
5525
5526			}
5527
5528			return true;
5529
5530		};
5531
5532	};
5533
5534	TWEEN.Easing = {
5535
5536		Linear: {
5537
5538			None: function (k) {
5539
5540				return k;
5541
5542			}
5543
5544		},
5545
5546		Quadratic: {
5547
5548			In: function (k) {
5549
5550				return k * k;
5551
5552			},
5553
5554			Out: function (k) {
5555
5556				return k * (2 - k);
5557
5558			},
5559
5560			InOut: function (k) {
5561
5562				if ((k *= 2) < 1) {
5563					return 0.5 * k * k;
5564				}
5565
5566				return -0.5 * (--k * (k - 2) - 1);
5567
5568			}
5569
5570		},
5571		Quartic: {
5572
5573			In: function (k) {
5574
5575				return k * k * k * k;
5576
5577			},
5578
5579			Out: function (k) {
5580
5581				return 1 - (--k * k * k * k);
5582
5583			},
5584
5585			InOut: function (k) {
5586
5587				if ((k *= 2) < 1) {
5588					return 0.5 * k * k * k * k;
5589				}
5590
5591				return -0.5 * ((k -= 2) * k * k * k - 2);
5592
5593			}
5594
5595		},
5596		Sinusoidal: {
5597
5598			In: function (k) {
5599
5600				return 1 - Math.cos(k * Math.PI / 2);
5601
5602			},
5603
5604			Out: function (k) {
5605
5606				return Math.sin(k * Math.PI / 2);
5607
5608			},
5609
5610			InOut: function (k) {
5611
5612				return 0.5 * (1 - Math.cos(Math.PI * k));
5613
5614			}
5615
5616		},
5617		Cubic: {
5618
5619			In: function (k) {
5620
5621				return k * k * k;
5622
5623			},
5624
5625			Out: function (k) {
5626
5627				return --k * k * k + 1;
5628
5629			},
5630
5631			InOut: function (k) {
5632
5633				if ((k *= 2) < 1) {
5634					return 0.5 * k * k * k;
5635				}
5636
5637				return 0.5 * ((k -= 2) * k * k + 2);
5638
5639			}
5640
5641		}
5642
5643	};
5644
5645	TWEEN.Interpolation = {
5646
5647		Linear: function (v, k) {
5648
5649			var m = v.length - 1;
5650			var f = m * k;
5651			var i = Math.floor(f);
5652			var fn = TWEEN.Interpolation.Utils.Linear;
5653
5654			if (k < 0) {
5655				return fn(v[0], v[1], f);
5656			}
5657
5658			if (k > 1) {
5659				return fn(v[m], v[m - 1], m - f);
5660			}
5661
5662			return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);
5663
5664		},
5665
5666		Bezier: function (v, k) {
5667
5668			var b = 0;
5669			var n = v.length - 1;
5670			var pw = Math.pow;
5671			var bn = TWEEN.Interpolation.Utils.Bernstein;
5672
5673			for (var i = 0; i <= n; i++) {
5674				b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);
5675			}
5676
5677			return b;
5678
5679		},
5680
5681		Utils: {
5682
5683			Linear: function (p0, p1, t) {
5684
5685				return (p1 - p0) * t + p0;
5686
5687			},
5688
5689			Bernstein: function (n, i) {
5690
5691				var fc = TWEEN.Interpolation.Utils.Factorial;
5692
5693				return fc(n) / fc(i) / fc(n - i);
5694
5695			},
5696
5697			Factorial: (function () {
5698
5699				var a = [1];
5700
5701				return function (n) {
5702
5703					var s = 1;
5704
5705					if (a[n]) {
5706						return a[n];
5707					}
5708
5709					for (var i = n; i > 1; i--) {
5710						s *= i;
5711					}
5712
5713					a[n] = s;
5714					return s;
5715
5716				};
5717
5718			})(),
5719
5720			CatmullRom: function (p0, p1, p2, p3, t) {
5721
5722				var v0 = (p2 - p0) * 0.5;
5723				var v1 = (p3 - p1) * 0.5;
5724				var t2 = t * t;
5725				var t3 = t * t2;
5726
5727				return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
5728
5729			}
5730
5731		}
5732	};
5733
5734	window.TWEEN = TWEEN;
5735})();
5736
5737DFLIP.createBlob = function createBlob(data, contentType) {
5738	if (typeof Blob !== 'undefined') {
5739		return new Blob([data], {type: contentType});
5740	}
5741	// Blob builder is deprecated in FF14 and removed in FF18.
5742	var bb = new MozBlobBuilder();
5743	bb.append(data);
5744	return bb.getBlob(contentType);
5745};
5746
5747DFLIP.createObjectURL = (function createObjectURLClosure() {
5748	// Blob/createObjectURL is not available, falling back to data schema.
5749	var digits =
5750		'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
5751
5752	return function createObjectURL(data, contentType) {
5753		if (typeof URL !== 'undefined' && URL.createObjectURL) {
5754			var blob = DFLIP.createBlob(data, contentType);
5755			return URL.createObjectURL(blob);
5756		}
5757
5758		var buffer = 'data:' + contentType + ';base64,';
5759		for (var i = 0, ii = data.length; i < ii; i += 3) {
5760			var b1 = data[i] & 0xFF;
5761			var b2 = data[i + 1] & 0xFF;
5762			var b3 = data[i + 2] & 0xFF;
5763			var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
5764			var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
5765			var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
5766			buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
5767		}
5768		return buffer;
5769	};
5770})();
5771
5772var ThumbList = (function ThumbListClosure() {
5773	function ThumbList(config) {
5774		var width = (config && config.w + 'px') || '100%';
5775		var height = (config && config.h + 'px') || '100%';
5776		var itemHeight = this.itemHeight = config.itemHeight;
5777
5778		this.items = config.items;
5779		this.generatorFn = config.generatorFn;
5780		this.totalRows = config.totalRows || (config.items && config.items.length);
5781
5782		this.addFn = config.addFn;
5783		this.scrollFn = config.scrollFn;
5784
5785		var scroller = ThumbList.createScroller(itemHeight * this.totalRows);
5786		this.container = ThumbList.createContainer(width, height);
5787		this.container.appendChild(scroller);
5788
5789		this.screenItemsLen = Math.ceil(config.h / itemHeight);
5790		this.offsetItems = this.screenItemsLen;
5791		// Cache 4 times the number of items that fit in the container viewport
5792		this.cachedItemsLen = this.screenItemsLen + this.offsetItems * 2;
5793		this._renderChunk(this.container, 0);
5794
5795		var self = this;
5796		self.lastRepaintY = 0;
5797		var maxBuffer = this.screenItemsLen * itemHeight;
5798		var lastScrolled = 0;
5799
5800		var requestInterval;
5801
5802		function onScroll(e) {
5803			var scrollTop = e.target.scrollTop; // Triggers reflow
5804			if (!self.lastRepaintY || Math.abs(scrollTop - self.lastRepaintY) >= (self.offsetItems * self.itemHeight)) {
5805				var first = parseInt(scrollTop / itemHeight, 10) - self.offsetItems;
5806				self._renderChunk(self.container, first < 0 ? 0 : first);
5807				self.lastRepaintY = scrollTop;
5808			}
5809
5810			self.lastScrolled = lastScrolled = Date.now();
5811
5812			if (self.scrollFn !== void 0) {
5813				self.scrollFn();
5814			}
5815
5816			e.preventDefault && e.preventDefault();
5817		}
5818
5819		self.dispose = function () {
5820			if (self.container) {
5821				if (self.container.parentNode) {
5822					self.container.parentNode.removeChild(self.container);
5823				}
5824			}
5825
5826			self.container.removeEventListener('scroll', onScroll);
5827		};
5828
5829		self.container.addEventListener('scroll', onScroll);
5830	}
5831
5832	ThumbList.prototype.reset = function (height) {
5833
5834		//container.find(".df-vrow").remove();
5835		this.screenItemsLen = Math.ceil(height / this.itemHeight);
5836		this.cachedItemsLen = this.screenItemsLen + this.offsetItems * 2;
5837		var first = parseInt(this.lastRepaintY / this.itemHeight, 10) - this.offsetItems;
5838		//this.lastRepaintY = 0;
5839		this.needReset = true;
5840		this._renderChunk(this.container, Math.max(first, 0));
5841	};
5842
5843	ThumbList.prototype.createRow = function (i) {
5844		var item;
5845		if (this.generatorFn) {
5846			item = this.generatorFn(i);
5847			item.classList.add('df-vrow');
5848			item.style.position = 'absolute';
5849			item.style.top = (i * this.itemHeight) + 'px';
5850			item.setAttribute("index", i);
5851		}
5852		return item;
5853	};
5854
5855	/**
5856	 * Renders a particular, consecutive chunk of the total rows in the list. To
5857	 * keep acceleration while scrolling, we mark the nodes that are candidate for
5858	 * deletion instead of deleting them right away, which would suddenly stop the
5859	 * acceleration. We delete them once scrolling has finished.
5860	 *
5861	 * @param {Node} node Parent node where we want to append the children chunk.
5862	 * @param {Number} from Starting position, i.e. first children index.
5863	 * @return {void}
5864	 */
5865	ThumbList.prototype._renderChunk = function (node, from) {
5866		var isEmpty = this.range == void 0;
5867		this.range = this.range || {min: 0, max: this.cachedItemsLen};
5868		var range = this.range;
5869
5870		var min = range.min, max = range.max;
5871
5872		var isAdd = isEmpty ? true : from >= min;
5873
5874		if (!isEmpty && from == min && this.needReset == false) return;
5875
5876		var countVar;
5877
5878		var start = isEmpty ? min :
5879					isAdd ? max : from;// - this.cachedItemsLen/3;
5880
5881		start = start > this.totalRows ? this.totalRows
5882			: start < 0 ? 0 : start;
5883
5884		var end = from + this.cachedItemsLen;//this.cachedItemsLen/3);
5885
5886		end = end > this.totalRows ? this.totalRows : end;
5887
5888		for (countVar = start; countVar < end; countVar++) {
5889			if (isAdd)
5890				node.appendChild(this.createRow(countVar));
5891			else
5892				node.insertBefore(this.createRow(countVar), node.childNodes[1 + countVar - start]);
5893			if (this.addFn !== void 0) {
5894				this.addFn(countVar);
5895			}
5896		}
5897		var difference = Math.abs(from - min);
5898		this.needReset = false;
5899		if (!isEmpty && node.childNodes.length > (this.cachedItemsLen + 1)) {
5900			// Hide and mark obsolete nodes for deletion.
5901			var delStart = isAdd ? 1 : 1 + this.cachedItemsLen,
5902				delEnd = delStart + (end - start);
5903
5904			for (var j = delEnd; j > delStart; j--) {
5905				if (node.childNodes[delStart])
5906					this.container.removeChild(node.childNodes[delStart]);
5907			}
5908		}
5909		this.range.min = from;
5910		this.range.max = end;
5911	};
5912
5913	ThumbList.createContainer = function (w, h) {
5914		var c = document.createElement('div');
5915		c.style.width = w;
5916		c.style.height = h;
5917		c.style.overflow = 'auto';
5918		c.style.position = 'relative';
5919		c.style.padding = 0;
5920		//c.style.border = '1px solid black';
5921		return c;
5922	};
5923
5924	ThumbList.createScroller = function (h) {
5925		var scroller = document.createElement('div');
5926		scroller.style.opacity = 0;
5927		scroller.style.position = 'absolute';
5928		scroller.style.top = 0;
5929		scroller.style.left = 0;
5930		scroller.style.width = '1px';
5931		scroller.style.height = h + 'px';
5932		return scroller;
5933	};
5934	return ThumbList;
5935})();
5936
5937
5938/**
5939 * @typedef {Object} BookMarkViewerOptions
5940 * @property {HTMLDivElement} container - The viewer element.
5941 * @property {IPDFLinkService} linkService - The navigation/linking service.
5942 */
5943
5944/**
5945 * @typedef {Object} BookMarkViewerRenderParameters
5946 * @property {Array|null} outline - An array of outline objects.
5947 */
5948
5949/**
5950 * @class
5951 */
5952var BookMarkViewer = (function BookMarkViewerClosure() {
5953	/**
5954	 * @constructs BookMarkViewer
5955	 * @param {BookMarkViewerOptions} options
5956	 */
5957	function BookMarkViewer(options) {
5958		this.outline = null;
5959		this.lastToggleIsShow = true;
5960		this.container = options.container;
5961		this.linkService = options.linkService;
5962		this.outlineItemClass = options.outlineItemClass || "outlineItem";
5963		this.outlineToggleClass = options.outlineToggleClass || "outlineItemToggler";
5964		this.outlineToggleHiddenClass = options.outlineToggleHiddenClass || "outlineItemsHidden";
5965	}
5966
5967	BookMarkViewer.prototype = {
5968
5969		dispose: function () {
5970			if (this.container) {
5971				if (this.container.parentNode) {
5972					this.container.parentNode.removeChild(this.container);
5973				}
5974			}
5975			this.linkService = null;
5976
5977		},
5978		reset: function BookMarkViewer_reset() {
5979			this.outline = null;
5980			this.lastToggleIsShow = true;
5981
5982			var container = this.container;
5983			while (container.firstChild) {
5984				container.removeChild(container.firstChild);
5985			}
5986		},
5987
5988		/**
5989		 * @private
5990		 */
5991		_dispatchEvent: function BookMarkViewer_dispatchEvent(outlineCount) {
5992			var event = document.createEvent('CustomEvent');
5993			event.initCustomEvent('outlineloaded', true, true, {
5994				outlineCount: outlineCount
5995			});
5996			this.container.dispatchEvent(event);
5997		},
5998
5999		/**
6000		 * @private
6001		 */
6002		_bindLink: function BookMarkViewer_bindLink(element, item) {
6003			var linkService = this.linkService;
6004			if (item.custom == true) {
6005				element.href = linkService.getCustomDestinationHash(item.dest);
6006				element.onclick = function goToDestination(e) {
6007					linkService.customNavigateTo(item.dest);
6008					return false;
6009				};
6010			}
6011			else {
6012				if (item.url) {
6013					PDFJS.addLinkAttributes(element, {url: item.url});
6014					return;
6015				}
6016
6017				element.href = linkService.getDestinationHash(item.dest);
6018				element.onclick = function goToDestination(e) {
6019					linkService.navigateTo(item.dest);
6020					return false;
6021				};
6022			}
6023		},
6024
6025		/**
6026		 * Prepend a button before an outline item which allows the user to toggle
6027		 * the visibility of all outline items at that level.
6028		 *
6029		 * @private
6030		 */
6031		_addToggleButton: function BookMarkViewer_addToggleButton(div) {
6032			var toggler = document.createElement('div');
6033			toggler.className = this.outlineToggleClass + " " + this.outlineToggleHiddenClass;
6034			toggler.onclick = function (event) {
6035				event.stopPropagation();
6036				toggler.classList.toggle(this.outlineToggleHiddenClass);
6037
6038				if (event.shiftKey) {
6039					var shouldShowAll = !toggler.classList.contains(this.outlineToggleHiddenClass);
6040					this._toggleOutlineItem(div, shouldShowAll);
6041				}
6042			}.bind(this);
6043			div.insertBefore(toggler, div.firstChild);
6044		},
6045
6046		/**
6047		 * Toggle the visibility of the subtree of an outline item.
6048		 *
6049		 * @param {Element} root - the root of the outline (sub)tree.
6050		 * @param {boolean} show - whether to show the outline (sub)tree. If false,
6051		 *   the outline subtree rooted at |root| will be collapsed.
6052		 *
6053		 * @private
6054		 */
6055		_toggleOutlineItem: function BookMarkViewer_toggleOutlineItem(root, show) {
6056			this.lastToggleIsShow = show;
6057			var togglers = root.querySelectorAll('.' + this.outlineToggleClass);
6058			for (var i = 0, ii = togglers.length; i < ii; ++i) {
6059				togglers[i].classList[show ? 'remove' : 'add'](this.outlineToggleHiddenClass);
6060			}
6061		},
6062
6063		/**
6064		 * Collapse or expand all subtrees of the outline.
6065		 */
6066		toggleOutlineTree: function BookMarkViewer_toggleOutlineTree() {
6067			if (!this.outline) {
6068				return;
6069			}
6070			this._toggleOutlineItem(this.container, !this.lastToggleIsShow);
6071		},
6072
6073		/**
6074		 * @param {BookMarkViewerRenderParameters} params
6075		 */
6076		render: function BookMarkViewer_render(params) {
6077			var outline = (params && params.outline) || null;
6078			var outlineCount = 0;
6079
6080			if (this.outline) {
6081				this.reset();
6082			}
6083			this.outline = outline;
6084
6085			if (!outline) {
6086				//this._dispatchEvent(outlineCount);
6087				return;
6088			}
6089
6090			var fragment = document.createDocumentFragment();
6091			var queue = [{parent: fragment, items: this.outline}];
6092			var hasAnyNesting = false;
6093			while (queue.length > 0) {
6094				var levelData = queue.shift();
6095				var isCustom = levelData.custom;
6096				for (var i = 0, len = levelData.items.length; i < len; i++) {
6097					var item = levelData.items[i];
6098
6099					var div = document.createElement('div');
6100					div.className = this.outlineItemClass;
6101
6102					var element = document.createElement('a');
6103					if (item.custom == void 0 && isCustom !== void 0)
6104						item.custom = isCustom;
6105
6106					this._bindLink(element, item);
6107					//element.
6108					element.textContent = item.title.replace(/\x00/g, '');
6109					//PDFJS.removeNullCharacters(item.title) || "Untitled Bookmark";
6110
6111					div.appendChild(element);
6112
6113					if (item.items && item.items.length > 0) {
6114						hasAnyNesting = true;
6115						this._addToggleButton(div);
6116
6117						var itemsDiv = document.createElement('div');
6118						itemsDiv.className = this.outlineItemClass + "s";
6119						div.appendChild(itemsDiv);
6120						queue.push({parent: itemsDiv, custom: item.custom, items: item.items});
6121					}
6122
6123					levelData.parent.appendChild(div);
6124					outlineCount++;
6125				}
6126			}
6127			if (hasAnyNesting) {
6128				if (this.container.classList != void 0) {
6129					this.container.classList.add(this.outlineItemClass + "s");
6130				}
6131				else if (this.container.className != void 0) {
6132					this.container.className += " picWindow";
6133				}
6134			}
6135
6136			this.container.appendChild(fragment);
6137
6138			this._dispatchEvent(outlineCount);
6139		}
6140
6141	};
6142
6143	return BookMarkViewer;
6144})();
6145//PDFJS.PDFOutlineViewer = PDFOutlineViewer;
6146
6147var DFLightBox = (function DFLightBoxClosure($) {
6148	/**
6149	 * @constructs DFLightBox
6150	 * @param closeCallback callBack function required to dispose object properly when lighbox is closed
6151	 */
6152	function DFLightBox(closeCallback) {
6153
6154		this.duration = 300;
6155
6156		//cache this
6157		var _this = this;
6158		//lightbox wrapper div
6159		_this.lightboxWrapper = $("<div>").addClass("df-lightbox-wrapper");
6160
6161		//lightbox container
6162		_this.container = $("<div>").addClass("df-container").appendTo(_this.lightboxWrapper);
6163		//lightbox controls
6164		_this.controls = $("<div>").addClass("df-lightbox-controls").appendTo(_this.lightboxWrapper);
6165
6166		//lightbox close button
6167		_this.closeButton = $("<div>").addClass("df-lightbox-close df-ui-btn ti-close")
6168			.on("click", function () {
6169				_this.close(closeCallback);
6170			})
6171			.appendTo(_this.controls);
6172
6173		_this.lightboxWrapper.append(_this.container);
6174
6175		return _this;
6176	}
6177
6178	DFLightBox.prototype.show = function (callback) {
6179
6180		if (this.lightboxWrapper.parent().length == 0)
6181			$("body").append(this.lightboxWrapper);
6182
6183		this.lightboxWrapper.fadeIn(this.duration, callback);
6184
6185		return this;
6186	};
6187
6188	DFLightBox.prototype.close = function (callback) {
6189
6190		this.lightboxWrapper.fadeOut(this.duration, callback);
6191
6192		return this;
6193	};
6194
6195	return DFLightBox;
6196})(jQuery);
6197
6198DFLIP.Share = (function ShareClosure($) {
6199
6200	function Share(container, options) {
6201		var _this = this;
6202		var htmlDiv = '<div>';
6203		var shareButtonClass = "df-share-button";
6204		var windowParameters = "width=500,height=400";
6205		_this.isOpen = false;
6206		_this.shareUrl = "";
6207		_this.wrapper = $('<div class="df-share-wrapper" style="display: none;">')
6208			.on("click", function (e) {
6209				_this.close();
6210			});
6211		_this.box = $('<div class="df-share-box">')
6212			.on("click", function (e) {
6213				e.preventDefault();
6214				e.stopPropagation();
6215			}).appendTo(_this.wrapper).html('<span class="df-share-title">'+options.text.share+'</span>');
6216		_this.urlInput = $('<textarea class="df-share-url">').on("click", function () {
6217			$(this).select();
6218		});
6219
6220		_this.facebook = $(htmlDiv, {
6221			class: shareButtonClass + " df-share-facebook " + options.icons['facebook']
6222		}).on("click", function (e) {
6223			window.open('https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(_this.shareUrl), "Sharer", windowParameters);
6224		});
6225		_this.google = $(htmlDiv, {
6226			class: shareButtonClass + " df-share-google " + options.icons['google']
6227		}).on("click", function (e) {
6228			window.open('https://plus.google.com/share?url=' + encodeURIComponent(_this.shareUrl), "Sharer", windowParameters);
6229		});
6230		_this.twitter = $(htmlDiv, {
6231			class: shareButtonClass + " df-share-twitter " + options.icons['twitter']
6232		}).on("click", function (e) {
6233			window.open('http://twitter.com/share?url=' + encodeURIComponent(_this.shareUrl), "Sharer", windowParameters);
6234		});
6235		/*_this.mail = $(htmlDiv, {
6236		 class:shareButtonClass + " df-share-mail " + options.icons['mail']
6237		 }).on("click", function (e) {
6238		 window.open('http://www.facebook.com/sharer.php?u=' + encodeURIComponent(_this.shareUrl) , "Sharer",windowParameters);
6239		 });*/
6240
6241		_this.box.append(_this.urlInput).append(_this.facebook).append(_this.twitter);
6242		$(container).append(_this.wrapper);
6243
6244	}
6245
6246	Share.prototype.show = function () {
6247		this.wrapper.fadeIn(300);
6248		this.urlInput.val(this.shareUrl);
6249		this.urlInput.trigger("click");
6250		this.isOpen = true;
6251	}
6252
6253	Share.prototype.dispose = function () {
6254		var _this = this;
6255		_this.box.off();
6256		_this.google.off();
6257		_this.twitter.off();
6258		_this.facebook.off();
6259		//_this.mail.off();
6260		_this.urlInput.off();
6261		_this.wrapper.off().remove();
6262	}
6263
6264	Share.prototype.close = function () {
6265		this.wrapper.fadeOut(300);
6266		this.isOpen = false;
6267	}
6268
6269	Share.prototype.update = function (url) {
6270		this.shareUrl = url;
6271	}
6272
6273	return Share;
6274})(jQuery);
6275
6276/**
6277 * Performs navigation functions inside PDF, such as opening specified page,
6278 * or destination.
6279 * @class
6280 * @implements {IPDFLinkService}
6281 */
6282var PDFLinkService = (function () {
6283	/**
6284	 * @constructs PDFLinkService
6285	 */
6286	function PDFLinkService() {
6287		this.baseUrl = null;
6288		this.pdfDocument = null;
6289		this.pdfViewer = null;
6290		this.pdfHistory = null;
6291
6292		this._pagesRefCache = null;
6293	}
6294
6295	PDFLinkService.prototype = {
6296		dispose: function () {
6297			this.baseUrl = null;
6298			this.pdfDocument = null;
6299			this.pdfViewer = null;
6300			this.pdfHistory = null;
6301
6302			this._pagesRefCache = null;
6303		},
6304		setDocument: function PDFLinkService_setDocument(pdfDocument, baseUrl) {
6305			this.baseUrl = baseUrl;
6306			this.pdfDocument = pdfDocument;
6307			this._pagesRefCache = Object.create(null);
6308		},
6309
6310		setViewer: function PDFLinkService_setViewer(pdfViewer) {
6311			this.pdfViewer = pdfViewer;
6312		},
6313
6314		setHistory: function PDFLinkService_setHistory(pdfHistory) {
6315			this.pdfHistory = pdfHistory;
6316		},
6317
6318		/**
6319		 * @returns {number}
6320		 */
6321		get pagesCount() {
6322			return this.pdfDocument.numPages;
6323		},
6324
6325		/**
6326		 * @returns {number}
6327		 */
6328		get page() {
6329			return this.pdfViewer.currentPageNumber;
6330		},
6331
6332		/**
6333		 * @param {number} value
6334		 */
6335		set page(value) {
6336			this.pdfViewer.currentPageNumber = value;
6337		},
6338
6339		/**
6340		 * @param dest - The PDF destination object.
6341		 */
6342		navigateTo: function PDFLinkService_navigateTo(dest) {
6343			var destString = '';
6344			var self = this;
6345
6346			var goToDestination = function (destRef) {
6347				// dest array looks like that: <page-ref> </XYZ|FitXXX> <args..>
6348				var pageNumber = destRef instanceof Object ?
6349								 self._pagesRefCache[destRef.num + ' ' + destRef.gen + ' R'] :
6350								 (destRef + 1);
6351				if (pageNumber) {
6352					if (pageNumber > self.pagesCount) {
6353						pageNumber = self.pagesCount;
6354					}
6355					self.pdfViewer.gotoPage(pageNumber);
6356					// self.pdfViewer.scrollPageIntoView(pageNumber, dest);
6357
6358					if (self.pdfHistory) {
6359						// Update the browsing history.
6360						self.pdfHistory.push({
6361							dest: dest,
6362							hash: destString,
6363							page: pageNumber
6364						});
6365					}
6366				} else {
6367					self.pdfDocument.getPageIndex(destRef).then(function (pageIndex) {
6368						var pageNum = pageIndex + 1;
6369						var cacheKey = destRef.num + ' ' + destRef.gen + ' R';
6370						self._pagesRefCache[cacheKey] = pageNum;
6371						goToDestination(destRef);
6372					});
6373				}
6374			};
6375
6376			var destinationPromise;
6377			if (typeof dest === 'string') {
6378				destString = dest;
6379				destinationPromise = this.pdfDocument.getDestination(dest);
6380			} else {
6381				destinationPromise = Promise.resolve(dest);
6382			}
6383			destinationPromise.then(function (destination) {
6384				dest = destination;
6385				if (!(destination instanceof Array)) {
6386					return; // invalid destination
6387				}
6388				goToDestination(destination[0]);
6389			});
6390		},
6391
6392
6393		/**
6394		 * @param dest - The PDF destination object.
6395		 */
6396		customNavigateTo: function PDFLinkService_navigateTo(dest) {
6397			if (dest == '' || dest == void 0 || dest == 'void 0') return;
6398			var pageNumber = void 0;
6399			if (!isNaN(Math.round(dest))) {
6400				pageNumber = dest;
6401			}
6402			else if (typeof dest === 'string') {
6403				pageNumber = parseInt(dest.replace("#", ""), 10);
6404				if (isNaN(pageNumber)) {
6405					window.open(dest);
6406					return;
6407				}
6408			}
6409
6410			if (pageNumber !== void 0)
6411				this.pdfViewer.gotoPage(pageNumber);
6412
6413		},
6414
6415		/**
6416		 * @param dest - The PDF destination object.
6417		 * @returns {string} The hyperlink to the PDF object.
6418		 */
6419		getDestinationHash: function PDFLinkService_getDestinationHash(dest) {
6420			if (typeof dest === 'string') {
6421				return this.getAnchorUrl('#' + escape(dest));
6422			}
6423			if (dest instanceof Array) {
6424				var destRef = dest[0]; // see navigateTo method for dest format
6425				var pageNumber = destRef instanceof Object ?
6426								 this._pagesRefCache[destRef.num + ' ' + destRef.gen + ' R'] :
6427								 (destRef + 1);
6428				if (pageNumber) {
6429					var pdfOpenParams = this.getAnchorUrl('#page=' + pageNumber);
6430					var destKind = dest[1];
6431					if (typeof destKind === 'object' && 'name' in destKind &&
6432						destKind.name === 'XYZ') {
6433						var scale = (dest[4] || this.pdfViewer.currentScaleValue);
6434						var scaleNumber = parseFloat(scale);
6435						if (scaleNumber) {
6436							scale = scaleNumber * 100;
6437						}
6438						pdfOpenParams += '&zoom=' + scale;
6439						if (dest[2] || dest[3]) {
6440							pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0);
6441						}
6442					}
6443					return pdfOpenParams;
6444				}
6445			}
6446			return this.getAnchorUrl('');
6447		},
6448
6449		/**
6450		 * @param dest - The PDF destination object.
6451		 * @returns {string} The hyperlink to the PDF object.
6452		 */
6453		getCustomDestinationHash: function PDFLinkService_getCustomDestinationHash(dest) {
6454			//if (typeof dest === 'string') {
6455			return '#' + escape(dest);
6456			//}
6457			//return this.getAnchorUrl('');
6458		},
6459
6460
6461		/**
6462		 * Prefix the full url on anchor links to make sure that links are resolved
6463		 * relative to the current URL instead of the one defined in <base href>.
6464		 * @param {String} anchor The anchor hash, including the #.
6465		 * @returns {string} The hyperlink to the PDF object.
6466		 */
6467		getAnchorUrl: function PDFLinkService_getAnchorUrl(anchor) {
6468			return (this.baseUrl || '') + anchor;
6469		},
6470
6471		/**
6472		 * @param {string} hash
6473		 */
6474		setHash: function PDFLinkService_setHash(hash) {
6475			if (hash.indexOf('=') >= 0) {
6476				var params = parseQueryString(hash);
6477				// borrowing syntax from "Parameters for Opening PDF Files"
6478				if ('nameddest' in params) {
6479					if (this.pdfHistory) {
6480						this.pdfHistory.updateNextHashParam(params.nameddest);
6481					}
6482					this.navigateTo(params.nameddest);
6483					return;
6484				}
6485				var pageNumber, dest;
6486				if ('page' in params) {
6487					pageNumber = (params.page | 0) || 1;
6488				}
6489				if ('zoom' in params) {
6490					// Build the destination array.
vendor: 4,126 bytes, lines 6491-6627
6491					var zoomArgs = params.zoom.split(','); // scale,left,top
6492					var zoomArg = zoomArgs[0];
6493					var zoomArgNumber = parseFloat(zoomArg);
6494
6495					if (zoomArg.indexOf('Fit') === -1) {
6496						// If the zoomArg is a number, it has to get divided by 100. If it's
6497						// a string, it should stay as it is.
6498						dest = [null, {name: 'XYZ'},
6499							zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null,
6500							zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null,
6501							(zoomArgNumber ? zoomArgNumber / 100 : zoomArg)];
6502					} else {
6503						if (zoomArg === 'Fit' || zoomArg === 'FitB') {
6504							dest = [null, {name: zoomArg}];
6505						} else if ((zoomArg === 'FitH' || zoomArg === 'FitBH') ||
6506							(zoomArg === 'FitV' || zoomArg === 'FitBV')) {
6507							dest = [null, {name: zoomArg},
6508								zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null];
6509						} else if (zoomArg === 'FitR') {
6510							if (zoomArgs.length !== 5) {
6511								console.error('PDFLinkService_setHash: ' +
6512								'Not enough parameters for \'FitR\'.');
6513							} else {
6514								dest = [null, {name: zoomArg},
6515									(zoomArgs[1] | 0), (zoomArgs[2] | 0),
6516									(zoomArgs[3] | 0), (zoomArgs[4] | 0)];
6517							}
6518						} else {
6519							console.error('PDFLinkService_setHash: \'' + zoomArg +
6520							'\' is not a valid zoom value.');
6521						}
6522					}
6523				}
6524				if (dest) {
6525					this.pdfViewer.scrollPageIntoView(pageNumber || this.page, dest);
6526				} else if (pageNumber) {
6527					this.page = pageNumber; // simple page
6528				}
6529				if ('pagemode' in params) {
6530					var event = document.createEvent('CustomEvent');
6531					event.initCustomEvent('pagemode', true, true, {
6532						mode: params.pagemode
6533					});
6534					this.pdfViewer.container.dispatchEvent(event);
6535				}
6536			} else if (/^\d+$/.test(hash)) { // page number
6537				this.page = hash;
6538			} else { // named destination
6539				if (this.pdfHistory) {
6540					this.pdfHistory.updateNextHashParam(unescape(hash));
6541				}
6542				this.navigateTo(unescape(hash));
6543			}
6544		},
6545
6546		/**
6547		 * @param {string} action
6548		 */
6549		executeNamedAction: function PDFLinkService_executeNamedAction(action) {
6550			// See PDF reference, table 8.45 - Named action
6551			switch (action) {
6552				case 'GoBack':
6553					if (this.pdfHistory) {
6554						this.pdfHistory.back();
6555					}
6556					break;
6557
6558				case 'GoForward':
6559					if (this.pdfHistory) {
6560						this.pdfHistory.forward();
6561					}
6562					break;
6563
6564				case 'NextPage':
6565					this.page++;
6566					break;
6567
6568				case 'PrevPage':
6569					this.page--;
6570					break;
6571
6572				case 'LastPage':
6573					this.page = this.pagesCount;
6574					break;
6575
6576				case 'FirstPage':
6577					this.page = 1;
6578					break;
6579
6580				default:
6581					break; // No action according to spec
6582			}
6583
6584			var event = document.createEvent('CustomEvent');
6585			event.initCustomEvent('namedaction', true, true, {
6586				action: action
6587			});
6588			this.pdfViewer.container.dispatchEvent(event);
6589		},
6590
6591		/**
6592		 * @param {number} pageNum - page number.
6593		 * @param {Object} pageRef - reference to the page.
6594		 */
6595		cachePageRef: function PDFLinkService_cachePageRef(pageNum, pageRef) {
6596			var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
6597			this._pagesRefCache[refStr] = pageNum;
6598		}
6599	};
6600
6601	return PDFLinkService;
6602})();
6603//PDFJS.PDFLinkService = PDFLinkService;
6604
6605/**
6606 * @typedef {Object} TextLayerBuilderOptions
6607 * @property {HTMLDivElement} textLayerDiv - The text layer container.
6608 * @property {EventBus} eventBus - The application event bus.
6609 * @property {number} pageIndex - The page index.
6610 * @property {PageViewport} viewport - The viewport of the text layer.
6611 * @property {PDFFindController} findController
6612 * @property {boolean} enhanceTextSelection - Option to turn on improved
6613 *   text selection.
6614 */
6615
6616/**
6617 * TextLayerBuilder provides text-selection functionality for the PDF.
6618 * It does this by creating overlay divs over the PDF text. These divs
6619 * contain text that matches the PDF text they are overlaying. This object
6620 * also provides a way to highlight text that is being searched for.
6621 * @class
6622 */
6623DFLIP.TextLayerBuilder = (function TextLayerBuilderClosure() {
6624	function TextLayerBuilder(options) {
6625		this.textLayerDiv = options.textLayerDiv;
6626		this.renderingDone = false;
6627		this.divContentDone = false;
6628		this.pageIdx = options.pageIndex;
6629		this.pageNumber = this.pageIdx + 1;
6630		this.matches = [];
6631		this.viewport = options.viewport;
6632		this.textDivs = [];
6633		this.findController = options.findController || null;
6634		this.textLayerRenderTask = null;
6635		this.enhanceTextSelection = options.enhanceTextSelection;
6636		this._bindMouse();
6637	}
6638
6639	TextLayerBuilder.prototype = {
6640		_finishRendering: function TextLayerBuilder_finishRendering() {
6641			this.renderingDone = true;
6642
6643			if (!this.enhanceTextSelection) {
6644				var endOfContent = document.createElement('div');
6645				endOfContent.className = 'endOfContent';
6646				this.textLayerDiv.appendChild(endOfContent);
6647			}
6648
6649			/*			this.eventBus.dispatch('textlayerrendered', {
6650			 source: this,
6651			 pageNumber: this.pageNumber
6652			 });*/
6653		},
6654
6655		/**
6656		 * Renders the text layer.
6657		 * @param {number} timeout (optional) if specified, the rendering waits
6658		 *   for specified amount of ms.
6659		 */
6660		render: function TextLayerBuilder_render(timeout) {
6661			if (!this.divContentDone || this.renderingDone) {
6662				return;
6663			}
6664
6665			if (this.textLayerRenderTask) {
6666				this.textLayerRenderTask.cancel();
6667				this.textLayerRenderTask = null;
6668			}
6669
6670			this.textDivs = [];
6671			var textLayerFrag = document.createDocumentFragment();
6672			this.textLayerRenderTask = PDFJS.renderTextLayer({
6673				textContent: this.textContent,
6674				container: textLayerFrag,
6675				viewport: this.viewport,
6676				textDivs: this.textDivs,
6677				timeout: timeout,
6678				enhanceTextSelection: this.enhanceTextSelection,
6679			});
6680			this.textLayerRenderTask.promise.then(function () {
6681				this.textLayerDiv.appendChild(textLayerFrag);
6682				this._finishRendering();
6683				this.updateMatches();
6684			}.bind(this), function (reason) {
6685				// canceled or failed to render text layer -- skipping errors
6686			});
6687		},
6688
6689		setTextContent: function TextLayerBuilder_setTextContent(textContent) {
6690			if (this.textLayerRenderTask) {
6691				this.textLayerRenderTask.cancel();
6692				this.textLayerRenderTask = null;
6693			}
6694			this.textContent = textContent;
6695			this.divContentDone = true;
6696		},
6697
6698		convertMatches: function TextLayerBuilder_convertMatches(matches,
6699																 matchesLength) {
6700			var i = 0;
6701			var iIndex = 0;
6702			var bidiTexts = this.textContent.items;
6703			var end = bidiTexts.length - 1;
6704			var queryLen = (this.findController === null ?
6705							0 : this.findController.state.query.length);
6706			var ret = [];
6707			if (!matches) {
6708				return ret;
6709			}
6710			for (var m = 0, len = matches.length; m < len; m++) {
6711				// Calculate the start position.
6712				var matchIdx = matches[m];
6713
6714				// Loop over the divIdxs.
6715				while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
6716					iIndex += bidiTexts[i].str.length;
6717					i++;
6718				}
6719
6720				if (i === bidiTexts.length) {
6721					console.error('Could not find a matching mapping');
6722				}
6723
6724				var match = {
6725					begin: {
6726						divIdx: i,
6727						offset: matchIdx - iIndex
6728					}
6729				};
6730
6731				// Calculate the end position.
6732				if (matchesLength) { // multiterm search
6733					matchIdx += matchesLength[m];
6734				} else { // phrase search
6735					matchIdx += queryLen;
6736				}
6737
6738				// Somewhat the same array as above, but use > instead of >= to get
6739				// the end position right.
6740				while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
6741					iIndex += bidiTexts[i].str.length;
6742					i++;
6743				}
6744
6745				match.end = {
6746					divIdx: i,
6747					offset: matchIdx - iIndex
6748				};
6749				ret.push(match);
6750			}
6751
6752			return ret;
6753		},
6754
6755		renderMatches: function TextLayerBuilder_renderMatches(matches) {
6756			// Early exit if there is nothing to render.
6757			if (matches.length === 0) {
6758				return;
6759			}
6760
6761			var bidiTexts = this.textContent.items;
6762			var textDivs = this.textDivs;
6763			var prevEnd = null;
6764			var pageIdx = this.pageIdx;
6765			var isSelectedPage = (this.findController === null ?
6766								  false : (pageIdx === this.findController.selected.pageIdx));
6767			var selectedMatchIdx = (this.findController === null ?
6768									-1 : this.findController.selected.matchIdx);
6769			var highlightAll = (this.findController === null ?
6770								false : this.findController.state.highlightAll);
6771			var infinity = {
6772				divIdx: -1,
6773				offset: undefined
6774			};
6775
6776			function beginText(begin, className) {
6777				var divIdx = begin.divIdx;
6778				textDivs[divIdx].textContent = '';
6779				appendTextToDiv(divIdx, 0, begin.offset, className);
6780			}
6781
6782			function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
6783				var div = textDivs[divIdx];
6784				var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset);
6785				var node = document.createTextNode(content);
6786				if (className) {
6787					var span = document.createElement('span');
6788					span.className = className;
6789					span.appendChild(node);
6790					div.appendChild(span);
6791					return;
6792				}
6793				div.appendChild(node);
6794			}
6795
6796			var i0 = selectedMatchIdx, i1 = i0 + 1;
6797			if (highlightAll) {
6798				i0 = 0;
6799				i1 = matches.length;
6800			} else if (!isSelectedPage) {
6801				// Not highlighting all and this isn't the selected page, so do nothing.
6802				return;
6803			}
6804
6805			for (var i = i0; i < i1; i++) {
6806				var match = matches[i];
6807				var begin = match.begin;
6808				var end = match.end;
6809				var isSelected = (isSelectedPage && i === selectedMatchIdx);
6810				var highlightSuffix = (isSelected ? ' selected' : '');
6811
6812				if (this.findController) {
6813					this.findController.updateMatchPosition(pageIdx, i, textDivs,
6814						begin.divIdx);
6815				}
6816
6817				// Match inside new div.
6818				if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
6819					// If there was a previous div, then add the text at the end.
6820					if (prevEnd !== null) {
6821						appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
6822					}
6823					// Clear the divs and set the content until the starting point.
6824					beginText(begin);
6825				} else {
6826					appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
6827				}
6828
6829				if (begin.divIdx === end.divIdx) {
6830					appendTextToDiv(begin.divIdx, begin.offset, end.offset,
6831						'highlight' + highlightSuffix);
6832				} else {
6833					appendTextToDiv(begin.divIdx, begin.offset, infinity.offset,
6834						'highlight begin' + highlightSuffix);
6835					for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
6836						textDivs[n0].className = 'highlight middle' + highlightSuffix;
6837					}
6838					beginText(end, 'highlight end' + highlightSuffix);
6839				}
6840				prevEnd = end;
6841			}
6842
6843			if (prevEnd) {
6844				appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
6845			}
6846		},
6847
6848		updateMatches: function TextLayerBuilder_updateMatches() {
6849			// Only show matches when all rendering is done.
6850			if (!this.renderingDone) {
6851				return;
6852			}
6853
6854			// Clear all matches.
6855			var matches = this.matches;
6856			var textDivs = this.textDivs;
6857			var bidiTexts = this.textContent.items;
6858			var clearedUntilDivIdx = -1;
6859
6860			// Clear all current matches.
6861			for (var i = 0, len = matches.length; i < len; i++) {
6862				var match = matches[i];
6863				var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
6864				for (var n = begin, end = match.end.divIdx; n <= end; n++) {
6865					var div = textDivs[n];
6866					div.textContent = bidiTexts[n].str;
6867					div.className = '';
6868				}
6869				clearedUntilDivIdx = match.end.divIdx + 1;
6870			}
6871
6872			if (this.findController === null || !this.findController.active) {
6873				return;
6874			}
6875
6876			// Convert the matches on the page controller into the match format
6877			// used for the textLayer.
6878			var pageMatches, pageMatchesLength;
6879			if (this.findController !== null) {
6880				pageMatches = this.findController.pageMatches[this.pageIdx] || null;
6881				pageMatchesLength = (this.findController.pageMatchesLength) ?
6882									this.findController.pageMatchesLength[this.pageIdx] || null : null;
6883			}
6884
6885			this.matches = this.convertMatches(pageMatches, pageMatchesLength);
6886			this.renderMatches(this.matches);
6887		},
6888
6889		/**
6890		 * Fixes text selection: adds additional div where mouse was clicked.
6891		 * This reduces flickering of the content if mouse slowly dragged down/up.
6892		 * @private
6893		 */
6894		_bindMouse: function TextLayerBuilder_bindMouse() {
6895			var div = this.textLayerDiv;
6896			var self = this;
6897			div.addEventListener('mousedown', function (e) {
6898				if (self.enhanceTextSelection && self.textLayerRenderTask) {
6899					self.textLayerRenderTask.expandTextDivs(true);
6900					return;
6901				}
6902				var end = div.querySelector('.endOfContent');
6903				if (!end) {
6904					return;
6905				}
6906				// On non-Firefox browsers, the selection will feel better if the height
6907				// of the endOfContent div will be adjusted to start at mouse click
6908				// location -- this will avoid flickering when selections moves up.
6909				// However it does not work when selection started on empty space.
6910				var adjustTop = e.target !== div;
6911				adjustTop = adjustTop && window.getComputedStyle(end).
6912					getPropertyValue('-moz-user-select') !== 'none';
6913				if (adjustTop) {
6914					var divBounds = div.getBoundingClientRect();
6915					var r = Math.max(0, (e.pageY - divBounds.top) / divBounds.height);
6916					end.style.top = (r * 100).toFixed(2) + '%';
6917				}
6918				end.classList.add('active');
6919			});
6920			div.addEventListener('mouseup', function (e) {
6921				if (self.enhanceTextSelection && self.textLayerRenderTask) {
6922					self.textLayerRenderTask.expandTextDivs(false);
6923					return;
6924				}
6925				var end = div.querySelector('.endOfContent');
6926				if (!end) {
6927					return;
6928				}
6929				end.style.top = '';
6930				end.classList.remove('active');
6931			});
6932		},
6933	};
6934	return TextLayerBuilder;
6935})();
6936
6937DFLIP.ConvertPageLinks = function () {
6938
6939	var w = arguments[0] / 100, h = arguments[1] / 100;
6940
6941	var toPercent = function (_x, _y, _w, _h, _dest) {
6942		return {
6943			x: _x / w,
6944			y: _y / h,
6945			w: _w / w,
6946			h: _h / h,
6947			dest: _dest
6948		};
6949	};
6950
6951	var percents = [];
6952	var input;
6953
6954	for (var index = 2; index < arguments.length; index++) {
6955		input = arguments[index];
6956		percents[index - 2] = toPercent.apply(this, input);
6957	}
6958
6959	return percents;
6960};
6961
6962DFLIP.parseLinks = function (links) {
6963	var _links;
6964	if (links !== void 0 && links.length > 0) {
6965		for (var index = 0; index < links.length; index++) {
6966			_links = links[index];
6967
6968			if (_links !== void 0 && _links[0] !== void 0 && _links[0].dest == void 0) {
6969
6970				_links = DFLIP.ConvertPageLinks.apply(this, _links);
6971				links[index] = _links;
6972			}
6973		}
6974	}
6975	return links;
6976};
6977
6978/**
6979 * DFLIP.parseBooks
6980 */
6981(function ($) {
6982
6983	//php and javascript interpret booleans differently so we use string checks
6984	function isTrue(val) {
6985		return val == "true";
6986	}
6987
6988	function checkValues(options) {
6989
6990		//boolean values
6991		if (options.webgl !== void 0) options.webgl = isTrue(options.webgl);
6992		if (options.enableDownload !== void 0) options.enableDownload = isTrue(options.enableDownload);
6993		if (options.scrollWheel !== void 0) options.scrollWheel = isTrue(options.scrollWheel);
6994		if (options.autoEnableOutline !== void 0) options.autoEnableOutline = isTrue(options.autoEnableOutline);
6995		if (options.transparent !== void 0) options.transparent = isTrue(options.transparent);
6996		if (options.overwritePDFOutline !== void 0) options.overwritePDFOutline = isTrue(options.overwritePDFOutline);
6997		if (options.soundEnable !== void 0) options.soundEnable = isTrue(options.soundEnable);
6998
6999		//integer value
7000		if (options.minTopOffset !== void 0) options.minTopOffset = parseInt(options.minTopOffset, 10);
7001
7002		if (options.pageMode == 0 || options.pageMode == "0")
7003			options.pageMode = void 0;
7004	}
7005
7006	function parseOptions(options) {
7007
7008		//bail out if already parsed or failed
7009		if (options.parsed == true) return;
7010
7011		options.parsed = true;
7012		//options.links are in json format
7013		//{"1":[]}
7014		//convert them to array format
7015		var links = [];
7016		checkValues(options);
7017
7018		if (typeof dFlipWPGlobal !== 'undefined' && options.wpOptions == 'true') {
7019
7020			try {
7021				for (var key in options.links) {
7022					var _pagelinks = options.links[key];
7023					var pagelink = [100, 100];
7024					for (var l = 0; l < _pagelinks.length; l++) {
7025						var _link = _pagelinks[l];
7026						var _values = _link.replace("[", "").replace("]", "").split(",");
7027						var _linkarr = [];
7028						for (var v = 0; v < 5; v++) {
7029							_linkarr[v] = _values[v];
7030						}
7031						pagelink.push(_linkarr);
7032					}
7033					links[parseInt(key, 10) + 1] = pagelink;
7034				}
7035			}
7036			catch (error) {
7037				console.error(error.stack);
7038			}
7039			options.links = DFLIP.parseLinks(links);
7040
7041		} else {
7042			options.links = DFLIP.parseLinks(options.links);
7043		}
7044
7045	}
7046
7047
7048	DFLIP.getOptions = function (book) {
7049
7050		book = $(book);
7051
7052		var book_id = book.attr("id");
7053
7054		var options = "option_" + book_id,
7055			source = book.attr("source") || book.attr("df-source");
7056
7057		//verify and optimize the values
7058		options = options == void 0 || options == "" || window[options] == void 0 ? {} : window[options];
7059
7060		options.source = source == void 0 || source == "" ? options.source : source;
7061
7062		/*As of 1.2.6 attribute values are also considered as options in some cases*/
7063		var attrOptions = {
7064			webgl: book.attr("webgl"),
7065			height: book.attr("height"),
7066			soundEnable: book.attr("sound"),
7067			transparent: book.attr("transparent"),
7068			enableDownload: book.attr("download"),
7069			duration: book.attr("duration"),
7070			hard: book.attr("hard"),
7071			pageMode: book.attr("pagemode"),
7072			direction: book.attr("direction"),
7073			backgroundColor: book.attr("backgroundcolor"),
7074			scrollWheel: book.attr("scrollwheel"),
7075			backgroundImage: book.attr("backgroundimage"),
7076			minTopOffset: book.attr("mintopoffset"),
7077			wpOptions: book.attr("wpoptions")
7078		};
7079
7080		options = $.extend(true, {}, options, attrOptions);
7081
7082		parseOptions(options);
7083
7084		return options;
7085	}
7086
7087	DFLIP.parseBooks = function () {
7088
7089		$('._df_button, ._df_thumb, ._df_custom, ._df_book').each(function () {
7090
7091			var book = $(this);
7092
7093			//fetch any existing values
7094			var parsed = book.attr("parsed") || book.attr("df-parsed");
7095
7096			//skip if already parsed or failed
7097			if (parsed !== "true") {
7098				book.attr("df-parsed", "true")
7099
7100				if (book.hasClass("_df_book")) {
7101
7102					var book_id = book.attr("id");
7103					var options = DFLIP.getOptions(book);
7104					options.id = book_id;
7105					window[book_id.toString()] = $(book).flipBook(options.source, options);
7106
7107				}
7108				else {
7109
7110					book.on("click", function () {
7111
7112						//cache the book element
7113						var book = $(this);
7114
7115						if (!window.dfLightBox) {
7116							window.dfLightBox = new DFLightBox(function () {
7117
7118								window.location.hash = "";
7119								window.dfActiveLightBoxBook.dispose();
7120								window.dfActiveLightBoxBook = null;
7121							});
7122						}
7123
7124						window.dfLightBox.duration = 500;
7125
7126						if (window.dfActiveLightBoxBook && window.dfActiveLightBoxBook.dispose) {
7127							window.dfActiveLightBoxBook.dispose();
7128
7129						} else {
7130							window.dfLightBox.show(
7131								function () {
7132//                            $("body").addClass("df-no-scroll");
7133									var options = DFLIP.getOptions(book);
7134									options.transparent = false;
7135									options.id = book.attr("id");
7136									options.isLightBox = true;
7137									window.dfActiveLightBoxBook = $(window.dfLightBox.container).flipBook(options.source, options);
7138								}
7139							);
7140						}
7141
7142					});
7143
7144					if (book.hasClass("_df_thumb")) {
7145						var wrapper = $("<div class='_df_book-cover'>");
7146
7147						var text = book.html();
7148						book.html("");
7149						var title = $("<span class='_df_book-title'>").html(text).appendTo(wrapper);
7150
7151						var thumb = book.attr("thumb") || book.attr("df-thumb"),
7152							tags = book.attr("tags") || book.attr("df-tags");
7153
7154						if (tags) {
7155							tags = tags.split(",");
7156
7157							if (tags.length > 0) {
7158								for (var tagcount = 0; tagcount < tags.length; tagcount++) {
7159									book.append("<span class='_df_book-tag'>" + tags[tagcount] + "</span>");
7160								}
7161							}
7162						}
7163
7164						if (thumb !== void 0 && thumb.toString().trim() != '') {
7165							wrapper.css({
7166								backgroundImage: "url(" + thumb + ")"
7167							});
7168						} else {
7169							wrapper.addClass("_df_thumb-not-found");
7170						}
7171
7172						book.append(wrapper);
7173					}
7174
7175				}
7176
7177			}
7178		});
7179
7180	}
7181
7182	$(document).ready(function () {
7183
7184		if (typeof dFlipLocation !== 'undefined') {
7185
7186			//add ending forward slash trail for safety
7187			if (dFlipLocation.length>2 && dFlipLocation.slice(-1) !== "/") {
7188				dFlipLocation += "/";
7189			}
7190
7191			//PRESENTATION.defaults.backgroundImage = "blank"; "images/textures/white.jpg";
7192			//PRESENTATION.defaults.textureLoadFallback = dFlipLocation + "images/textures/white.jpg";
7193			DFLIP.defaults.mockupjsSrc = dFlipLocation + "js/libs/mockup.min.js";
7194			DFLIP.defaults.pdfjsSrc = dFlipLocation + "js/libs/pdf.min.js";
7195			DFLIP.defaults.pdfjsCompatibilitySrc = dFlipLocation + "js/libs/compatibility.js";
7196			DFLIP.defaults.threejsSrc = dFlipLocation + "js/libs/three.min.js";
7197			DFLIP.defaults.pdfjsWorkerSrc = dFlipLocation + "js/libs/pdf.worker.min.js";
7198			DFLIP.defaults.soundFile = dFlipLocation + "sound/turn2.mp3";
7199
7200			if (typeof dFlipWPGlobal !== 'undefined') {
7201
7202				checkValues(dFlipWPGlobal);
7203
7204				$.extend(DFLIP.defaults, dFlipWPGlobal);
7205			}
7206		}
7207
7208		DFLIP.preParseHash = window.location.hash;
7209		DFLIP.parseBooks();
7210
7211		//parse hash and check if any exists
7212		if (DFLIP.preParseHash && DFLIP.preParseHash.indexOf('dflip-') >= 0) {
7213			var id = DFLIP.preParseHash.split('dflip-')[1].split('/')[0];
7214			var page = DFLIP.preParseHash.split('dflip-')[1].split('/')[1];
7215			if (page != void 0) {
7216				page = page.split('/')[0];
7217			}
7218			var book = $('#' + id);
7219			if (book.length > 0) {
7220
7221				var oldHash = window.location.hash;
7222				window.location.hash = id;
7223				window.location.hash = DFLIP.preParseHash;
7224
7225				if (page != void 0) {
7226					book.data("page", page)
7227				}
7228				;
7229
7230				if (book.is('._df_button, ._df_thumb, ._df_custom')) {
7231					book.trigger("click");
7232				}
7233			}
7234		}
7235
7236	});
7237
7238})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.