PageSourceSearch

https://www.arbeitsinspektion.gv.at/.resources/bcisa/resources/not…/dflip~2026-09-14-15-04-11-566~cache.js

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