PageSourceSearch

https://hrvatski-vojnik.hr/wp-content/plugins/dflip/assets/js/dflip.js?ver=1.2.8

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