PageSourceSearch

https://clients.xlgames.pro/application/public/js/jquery.nicescroll.js?ver=3.8

js xlgames.pro collected 2026-10-08 16:55:21 UTC 124,523 bytes, 3,724 lines download raw bytes

1// Licensed to Cloudera, Inc. under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  Cloudera, Inc. licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17/* jquery.nicescroll
18-- version 3.6.8
19-- copyright 2016-02-29 InuYaksa*2016
20-- licensed under the MIT
21--
22-- http://nicescroll.areaaperta.com/
23-- https://github.com/inuyaksa/jquery.nicescroll
24--
25*/
26
27(function(factory) {
28  if (typeof define === 'function' && define.amd) {
29    // AMD. Register as anonymous module.
30    define(['jquery'], factory);
31  } else if (typeof exports === 'object') {
32    // Node/CommonJS.
33    module.exports = factory(require('jquery'));
34  } else {
35    // Browser globals.
36    factory(jQuery);
37  }
38}(function(jQuery) {
39  "use strict";
40
41  // globals
42  var domfocus = false;
43  var mousefocus = false;
44  var tabindexcounter = 0;
45  var ascrailcounter = 2000;
46  var globalmaxzindex = 0;
47
48  var $ = jQuery; // sandbox
49
50  // http://stackoverflow.com/questions/2161159/get-script-path
51  function getScriptPath() {
52    var scripts = document.getElementsByTagName('script');
53    var path = scripts.length ? scripts[scripts.length - 1].src.split('?')[0] : '';
54    return (path.split('/').length > 0) ? path.split('/').slice(0, -1).join('/') + '/' : '';
55  }
56
57  var vendors = ['webkit','ms','moz','o'];
58
59  var setAnimationFrame = window.requestAnimationFrame || false;
60  var clearAnimationFrame = window.cancelAnimationFrame || false;
61
62  if (!setAnimationFrame) {  // legacy detection
63    for (var vx in vendors) {
64      var v = vendors[vx];
65      setAnimationFrame = window[v + 'RequestAnimationFrame'];
66      if (setAnimationFrame) {
67        clearAnimationFrame = window[v + 'CancelAnimationFrame'] || window[v + 'CancelRequestAnimationFrame'];
68        break;
69      }
70    }
71  }
72
73  var ClsMutationObserver = window.MutationObserver || window.WebKitMutationObserver || false;
74
75  var _globaloptions = {
76    zindex: "auto",
77    cursoropacitymin: 0,
78    cursoropacitymax: 1,
79    cursorcolor: "#424242",
80    cursorwidth: "6px",
81    cursorborder: "1px solid #fff",
82    cursorborderradius: "5px",
83    scrollspeed: 60,
84    mousescrollstep: 8 * 3,
85    touchbehavior: false,
86    hwacceleration: true,
87    usetransition: true,
88    boxzoom: false,
89    dblclickzoom: true,
90    gesturezoom: true,
91    grabcursorenabled: true,
92    autohidemode: true,
93    background: "",
94    iframeautoresize: true,
95    cursorminheight: 32,
96    preservenativescrolling: true,
97    railoffset: false,
98    railhoffset: false,
99    bouncescroll: true,
100    spacebarenabled: true,
101    railpadding: {
102      top: 0,
103      right: 0,
104      left: 0,
105      bottom: 0
106    },
107    disableoutline: true,
108    horizrailenabled: true,
109    railalign: "right",
110    railvalign: "bottom",
111    enabletranslate3d: true,
112    enablemousewheel: true,
113    enablekeyboard: true,
114    smoothscroll: true,
115    sensitiverail: true,
116    enablemouselockapi: true,
117    //      cursormaxheight:false,
118    cursorfixedheight: false,
119    directionlockdeadzone: 6,
120    hidecursordelay: 400,
121    nativeparentscrolling: true,
122    enablescrollonselection: true,
123    overflowx: true,
124    overflowy: true,
125    cursordragspeed: 0.3,
126    rtlmode: "auto",
127    cursordragontouch: false,
128    oneaxismousemode: "auto",
129    scriptpath: getScriptPath(),
130    preventmultitouchscrolling: true,
131    disablemutationobserver:false
132  };
133
134  var browserdetected = false;
135
136  var getBrowserDetection = function() {
137
138    if (browserdetected) return browserdetected;
139
140    var _el = document.createElement('DIV'),
141        _style = _el.style,
142        _agent = navigator.userAgent,
143        _platform = navigator.platform,
144        d = {};
145
146    d.haspointerlock = "pointerLockElement" in document || "webkitPointerLockElement" in document || "mozPointerLockElement" in document;
147
148    d.isopera = ("opera" in window); // 12-
149    d.isopera12 = (d.isopera && ("getUserMedia" in navigator));
150    d.isoperamini = (Object.prototype.toString.call(window.operamini) === "[object OperaMini]");
151
152    d.isie = (("all" in document) && ("attachEvent" in _el) && !d.isopera); //IE10-
153    d.isieold = (d.isie && !("msInterpolationMode" in _style)); // IE6 and older
154    d.isie7 = d.isie && !d.isieold && (!("documentMode" in document) || (document.documentMode == 7));
155    d.isie8 = d.isie && ("documentMode" in document) && (document.documentMode == 8);
156    d.isie9 = d.isie && ("performance" in window) && (document.documentMode == 9);
157    d.isie10 = d.isie && ("performance" in window) && (document.documentMode == 10);
158    d.isie11 = ("msRequestFullscreen" in _el) && (document.documentMode >= 11); // IE11+
159    d.isieedge12 = (navigator.userAgent.match(/Edge\/12\./));  // IE Edge 12
160    d.isieedge = ("msOverflowStyle" in _el);  // IE Edge
161    d.ismodernie = d.isie11 || d.isieedge;
162
163    d.isie9mobile = /iemobile.9/i.test(_agent); //wp 7.1 mango
164    if (d.isie9mobile) d.isie9 = false;
165    d.isie7mobile = (!d.isie9mobile && d.isie7) && /iemobile/i.test(_agent); //wp 7.0
166
167    d.ismozilla = ("MozAppearance" in _style);
168
169    d.iswebkit = ("WebkitAppearance" in _style);
170
171    d.ischrome = ("chrome" in window);
172    d.ischrome38 = (d.ischrome && ("touchAction" in _style)); // behavior changed in touch emulation
173    d.ischrome22 = (!d.ischrome38)&&(d.ischrome && d.haspointerlock);
174    d.ischrome26 = (!d.ischrome38)&&(d.ischrome && ("transition" in _style)); // issue with transform detection (maintain prefix)
175
176    d.cantouch = ("ontouchstart" in document.documentElement) || ("ontouchstart" in window); // with detection for Chrome Touch Emulation
177    d.hasw3ctouch = (window.PointerEvent || false) && ((navigator.MaxTouchPoints > 0)||(navigator.msMaxTouchPoints > 0)); //IE11 pointer events, following W3C Pointer Events spec
178    d.hasmstouch = (!d.hasw3ctouch)&&(window.MSPointerEvent || false); // IE10 pointer events
179
180    d.ismac = /^mac$/i.test(_platform);
181
182    d.isios = (d.cantouch && /iphone|ipad|ipod/i.test(_platform));
183    d.isios4 = ((d.isios) && !("seal" in Object));
184    d.isios7 = ((d.isios)&&("webkitHidden" in document));  //iOS 7+
185    d.isios8 = ((d.isios)&&("hidden" in document));  //iOS 8+
186
187    d.isandroid = (/android/i.test(_agent));
188
189    d.haseventlistener = ("addEventListener" in _el);
190
191    d.trstyle = false;
192    d.hastransform = false;
193    d.hastranslate3d = false;
194    d.transitionstyle = false;
195    d.hastransition = false;
196    d.transitionend = false;
197
198    var a;
199    var check = ['transform', 'msTransform', 'webkitTransform', 'MozTransform', 'OTransform'];
200    for (a = 0; a < check.length; a++) {
201      if (_style[check[a]] !== undefined) {
202        d.trstyle = check[a];
203        break;
204      }
205    }
206    d.hastransform = (!!d.trstyle);
207    if (d.hastransform) {
208      _style[d.trstyle] = "translate3d(1px,2px,3px)";
209      d.hastranslate3d = /translate3d/.test(_style[d.trstyle]);
210    }
211
212    d.transitionstyle = false;
213    d.prefixstyle = '';
214    d.transitionend = false;
215    check = ['transition', 'webkitTransition', 'msTransition', 'MozTransition', 'OTransition', 'OTransition', 'KhtmlTransition'];
216    var prefix = ['', '-webkit-', '-ms-', '-moz-', '-o-', '-o', '-khtml-'];
217    var evs = ['transitionend', 'webkitTransitionEnd', 'msTransitionEnd', 'transitionend', 'otransitionend', 'oTransitionEnd', 'KhtmlTransitionEnd'];
218    for (a = 0; a < check.length; a++) {
219      if (check[a] in _style) {
220        d.transitionstyle = check[a];
221        d.prefixstyle = prefix[a];
222        d.transitionend = evs[a];
223        break;
224      }
225    }
226    if (d.ischrome26) {  // always use prefix
227      d.prefixstyle = prefix[1];
228    }
229
230    d.hastransition = (d.transitionstyle);
231
232    function detectCursorGrab() {
233      var lst = ['grab','-webkit-grab', '-moz-grab'];
234      if ((d.ischrome && !d.ischrome38) || d.isie) lst = []; // force setting for IE returns false positive and chrome cursor bug
235      for (var a = 0; a < lst.length; a++) {
236        var p = lst[a];
237        _style.cursor = p;
238        if (_style.cursor == p) return p;
239      }
240      return 'url(//patriciaportfolio.googlecode.com/files/openhand.cur),n-resize'; // thank you google for custom cursor!
241    }
242    d.cursorgrabvalue = detectCursorGrab();
243
244    d.hasmousecapture = ("setCapture" in _el);
245
246    d.hasMutationObserver = (ClsMutationObserver !== false);
247
248    _el = null; //memory released
249
250    browserdetected = d;
251
252    return d;
253  };
254
255  var NiceScrollClass = function(myopt, me) {
256
257    var self = this;
258
259    this.version = '3.6.8';
260    this.name = 'nicescroll';
261
262    this.me = me;
263
264    this.opt = {
265      doc: $("body"),
266      win: false
267    };
268
269    $.extend(this.opt, _globaloptions);  // clone opts
270
271    // Options for internal use
272    this.opt.snapbackspeed = 80;
273
274    if (myopt || false) {
275      for (var a in self.opt) {
276        if (myopt[a] !== undefined) self.opt[a] = myopt[a];
277      }
278    }
279
280    if (self.opt.disablemutationobserver) ClsMutationObserver = false;
281
282    this.doc = self.opt.doc;
283    this.iddoc = (this.doc && this.doc[0]) ? this.doc[0].id || '' : '';
284    this.ispage = /^BODY|HTML/.test((self.opt.win) ? self.opt.win[0].nodeName : this.doc[0].nodeName);
285    this.haswrapper = (self.opt.win !== false);
286    this.win = self.opt.win || (this.ispage ? $(window) : this.doc);
287    this.docscroll = (this.ispage && !this.haswrapper) ? $(window) : this.win;
288    this.body = $("body");
289    this.viewport = false;
290
291    this.isfixed = false;
292
293    this.iframe = false;
294    this.isiframe = ((this.doc[0].nodeName == 'IFRAME') && (this.win[0].nodeName == 'IFRAME'));
295
296    this.istextarea = (this.win[0].nodeName == 'TEXTAREA');
297
298    this.forcescreen = false; //force to use screen position on events
299
300    this.canshowonmouseevent = (self.opt.autohidemode != "scroll");
301
302    // Events jump table
303    this.onmousedown = false;
304    this.onmouseup = false;
305    this.onmousemove = false;
306    this.onmousewheel = false;
307    this.onkeypress = false;
308    this.ongesturezoom = false;
309    this.onclick = false;
310
311    // Nicescroll custom events
312    this.onscrollstart = false;
313    this.onscrollend = false;
314    this.onscrollcancel = false;
315
316    this.onzoomin = false;
317    this.onzoomout = false;
318
319    // Let's start!
320    this.view = false;
321    this.page = false;
322
323    this.scroll = {
324      x: 0,
325      y: 0
326    };
327    this.scrollratio = {
328      x: 0,
329      y: 0
330    };
331    this.cursorheight = 20;
332    this.scrollvaluemax = 0;
333
334    // http://dev.w3.org/csswg/css-writing-modes-3/#logical-to-physical
335    // http://dev.w3.org/csswg/css-writing-modes-3/#svg-writing-mode
336    if (this.opt.rtlmode == "auto") {
337      var target = this.win[0] == window ? this.body : this.win;
338      var writingMode = target.css("writing-mode") || target.css("-webkit-writing-mode") || target.css("-ms-writing-mode") || target.css("-moz-writing-mode");
339
340      if (writingMode == "horizontal-tb" || writingMode == "lr-tb" || writingMode == "") {
341        this.isrtlmode = (target.css("direction") == "rtl");
342        this.isvertical = false;
343      } else {
344        this.isrtlmode = (writingMode == "vertical-rl" || writingMode == "tb" || writingMode == "tb-rl" || writingMode == "rl-tb");
345        this.isvertical = (writingMode == "vertical-rl" || writingMode == "tb" || writingMode == "tb-rl");
346      }
347    } else {
348      this.isrtlmode = (this.opt.rtlmode === true);
349      this.isvertical = false;
350    }
351    //    this.checkrtlmode = false;
352
353    this.scrollrunning = false;
354
355    this.scrollmom = false;
356
357    this.observer        = false;  // observer div changes
358    this.observerremover = false;  // observer on parent for remove detection
359    this.observerbody    = false;  // observer on body for position change
360
361    do {
362      this.id = "ascrail" + (ascrailcounter++);
363    } while (document.getElementById(this.id));
364
365    this.rail = false;
366    this.cursor = false;
367    this.cursorfreezed = false;
368    this.selectiondrag = false;
369
370    this.zoom = false;
371    this.zoomactive = false;
372
373    this.hasfocus = false;
374    this.hasmousefocus = false;
375
376    this.visibility = true;
377    this.railslocked = false;  // locked by resize
378    this.locked = false;  // prevent lost of locked status sets by user
379    this.hidden = false; // rails always hidden
380    this.cursoractive = true; // user can interact with cursors
381
382    this.wheelprevented = false; //prevent mousewheel event
383
384    this.overflowx = self.opt.overflowx;
385    this.overflowy = self.opt.overflowy;
386
387    this.nativescrollingarea = false;
388    this.checkarea = 0;
389
390    this.events = []; // event list for unbind
391
392    this.saved = {};  // style saved
393
394    this.delaylist = {};
395    this.synclist = {};
396
397    this.lastdeltax = 0;
398    this.lastdeltay = 0;
399
400    this.detected = getBrowserDetection();
401
402    var cap = $.extend({}, this.detected);
403
404    this.canhwscroll = (cap.hastransform && self.opt.hwacceleration);
405    this.ishwscroll = (this.canhwscroll && self.haswrapper);
406
407    if (!this.isrtlmode) {
408      this.hasreversehr = false;
409    } else if (this.isvertical) { // RTL mode with reverse horizontal axis
410      this.hasreversehr = !(cap.iswebkit || cap.isie || cap.isie11);
411    } else {
412      this.hasreversehr = !(cap.iswebkit || (cap.isie && !cap.isie10 && !cap.isie11));
413    }
414
415    this.istouchcapable = false; // desktop devices with touch screen support
416
417    //## Check WebKit-based desktop with touch support
418    //## + Firefox 18 nightly build (desktop) false positive (or desktop with touch support)
419
420    if (!cap.cantouch && (cap.hasw3ctouch||cap.hasmstouch)) {  // desktop device with multiple input
421      this.istouchcapable = true;
422    } else if (cap.cantouch && !cap.isios && !cap.isandroid && (cap.iswebkit || cap.ismozilla)) {
423      this.istouchcapable = true;
424//      cap.cantouch = false; // parse normal desktop events
425    }
426
427    //## disable MouseLock API on user request
428    if (!self.opt.enablemouselockapi) {
429      cap.hasmousecapture = false;
430      cap.haspointerlock = false;
431    }
432
433/* deprecated
434    this.delayed = function(name, fn, tm, lazy) {
435    };
436*/
437
438/*
439    this.debounced = function(name, fn, tm) {
440		if (!self) return;
441      var dd = self.delaylist[name];
442      self.delaylist[name] = fn;
443      if (!dd) {
444        self.debouncedelayed =  setTimeout(function() {
445					if (!self) return;
446          var fn = self.delaylist[name];
447          self.delaylist[name] = false;
448          fn.call(self);
449        }, tm);
450      }
451    };
452*/
453
454		this.debounced = function(name, fn, tm) {
455      if (!self) return;
456			var dd = self.delaylist[name]||false;
457			if (!dd) {
458				fn.call(self);
459				self.delaylist[name] = {
460					h: setAnimationFrame(function(){
461						self.delaylist[name].fn.call(self);
462					  self.delaylist[name] = false;
463					}, tm)
464				};
465			}
466			self.delaylist[name].fn = fn;
467		};
468
469    var _onsync = false;
470
471    this.synched = function(name, fn) {
472
473      function requestSync() {
474        if (_onsync) return;
475        setAnimationFrame(function() {
476          if (!self) return;
477          _onsync = false;
478          for (var nn in self.synclist) {
479            var fn = self.synclist[nn];
480            if (fn) fn.call(self);
481            self.synclist[nn] = false;
482          }
483        });
484        _onsync = true;
485      }
486
487      self.synclist[name] = fn;
488      requestSync();
489      return name;
490    };
491
492    this.unsynched = function(name) {
493      if (self.synclist[name]) self.synclist[name] = false;
494    };
495
496    this.css = function(el, pars) { // save & set
497      for (var n in pars) {
498        self.saved.css.push([el, n, el.css(n)]);
499        el.css(n, pars[n]);
500      }
501    };
502
503    this.scrollTop = function(val) {
504      return (val === undefined) ? self.getScrollTop() : self.setScrollTop(val);
505    };
506
507    this.scrollLeft = function(val) {
508      return (val === undefined) ? self.getScrollLeft() : self.setScrollLeft(val);
509    };
510
511    // derived by by Dan Pupius www.pupius.net
512    var BezierClass = function(st, ed, spd, p1, p2, p3, p4) {
513
514      this.st = st;
515      this.ed = ed;
516      this.spd = spd;
517
518      this.p1 = p1 || 0;
519      this.p2 = p2 || 1;
520      this.p3 = p3 || 0;
521      this.p4 = p4 || 1;
522
523      this.ts = (new Date()).getTime();
524      this.df = this.ed - this.st;
525    };
526    BezierClass.prototype = {
527      B2: function(t) {
528        return 3 * t * t * (1 - t);
529      },
530      B3: function(t) {
531        return 3 * t * (1 - t) * (1 - t);
532      },
533      B4: function(t) {
534        return (1 - t) * (1 - t) * (1 - t);
535      },
536      getNow: function() {
537        var nw = (new Date()).getTime();
538        var pc = 1 - ((nw - this.ts) / this.spd);
539        var bz = this.B2(pc) + this.B3(pc) + this.B4(pc);
540        return (pc < 0) ? this.ed : this.st + Math.round(this.df * bz);
541      },
542      update: function(ed, spd) {
543        this.st = this.getNow();
544        this.ed = ed;
545        this.spd = spd;
546        this.ts = (new Date()).getTime();
547        this.df = this.ed - this.st;
548        return this;
549      }
550    };
551
552    //derived from http://stackoverflow.com/questions/11236090/
553    function getMatrixValues() {
554      var tr = self.doc.css(cap.trstyle);
555      if (tr && (tr.substr(0, 6) == "matrix")) {
556        return tr.replace(/^.*\((.*)\)$/g, "$1").replace(/px/g, '').split(/, +/);
557      }
558      return false;
559    }
560
561    if (this.ishwscroll) {
562      // hw accelerated scroll
563      this.doc.translate = {
564        x: 0,
565        y: 0,
566        tx: "0px",
567        ty: "0px"
568      };
569
570      //this one can help to enable hw accel on ios6 http://indiegamr.com/ios6-html-hardware-acceleration-changes-and-how-to-fix-them/
571      if (cap.hastranslate3d && cap.isios) this.doc.css("-webkit-backface-visibility", "hidden"); // prevent flickering http://stackoverflow.com/questions/3461441/
572
vendor: 11,077 bytes, lines 573-880
573      this.getScrollTop = function(last) {
574        if (!last) {
575          var mtx = getMatrixValues();
576          if (mtx) return (mtx.length == 16) ? -mtx[13] : -mtx[5]; //matrix3d 16 on IE10
577          if (self.timerscroll && self.timerscroll.bz) return self.timerscroll.bz.getNow();
578        }
579        return self.doc.translate.y;
580      };
581
582      this.getScrollLeft = function(last) {
583        if (!last) {
584          var mtx = getMatrixValues();
585          if (mtx) return (mtx.length == 16) ? -mtx[12] : -mtx[4]; //matrix3d 16 on IE10
586          if (self.timerscroll && self.timerscroll.bh) return self.timerscroll.bh.getNow();
587        }
588        return self.doc.translate.x;
589      };
590
591      this.notifyScrollEvent = function(el) {
592        var e = document.createEvent("UIEvents");
593        e.initUIEvent("scroll", false, true, window, 1);
594        e.niceevent = true;
595        el.dispatchEvent(e);
596      };
597
598      var cxscrollleft = (this.isrtlmode) ? 1 : -1;
599
600      if (cap.hastranslate3d && self.opt.enabletranslate3d) {
601        this.setScrollTop = function(val, silent) {
602          self.doc.translate.y = val;
603          self.doc.translate.ty = (val * -1) + "px";
604          self.doc.css(cap.trstyle, "translate3d(" + self.doc.translate.tx + "," + self.doc.translate.ty + ",0px)");
605          if (!silent) self.notifyScrollEvent(self.win[0]);
606        };
607        this.setScrollLeft = function(val, silent) {
608          self.doc.translate.x = val;
609          self.doc.translate.tx = (val * cxscrollleft) + "px";
610          self.doc.css(cap.trstyle, "translate3d(" + self.doc.translate.tx + "," + self.doc.translate.ty + ",0px)");
611          if (!silent) self.notifyScrollEvent(self.win[0]);
612        };
613      } else {
614        this.setScrollTop = function(val, silent) {
615          self.doc.translate.y = val;
616          self.doc.translate.ty = (val * -1) + "px";
617          self.doc.css(cap.trstyle, "translate(" + self.doc.translate.tx + "," + self.doc.translate.ty + ")");
618          if (!silent) self.notifyScrollEvent(self.win[0]);
619        };
620        this.setScrollLeft = function(val, silent) {
621          self.doc.translate.x = val;
622          self.doc.translate.tx = (val * cxscrollleft) + "px";
623          self.doc.css(cap.trstyle, "translate(" + self.doc.translate.tx + "," + self.doc.translate.ty + ")");
624          if (!silent) self.notifyScrollEvent(self.win[0]);
625        };
626      }
627    } else {
628      // native scroll
629      this.getScrollTop = function() {
630        return self.docscroll.scrollTop();
631      };
632      this.setScrollTop = function(val) {
633        return setTimeout(function() {(self)&&self.docscroll.scrollTop(val)}, 1);
634      };
635      this.getScrollLeft = function() {
636        var val;
637        if (!self.hasreversehr) {
638          val = self.docscroll.scrollLeft();
639        } else if (self.detected.ismozilla) {
640          val = self.page.maxw - Math.abs(self.docscroll.scrollLeft());
641        } else {
642          val = self.page.maxw - self.docscroll.scrollLeft();
643        }
644        return val;
645      };
646      this.setScrollLeft = function(val) {
647        return setTimeout(function() {
648          if (!self) return;
649					if (self.hasreversehr) {
650						if (self.detected.ismozilla) {
651							val = -(self.page.maxw - val);
652						} else {
653							val = self.page.maxw - val;
654						}
655					}
656					return self.docscroll.scrollLeft(val);
657				}, 1);
658      };
659    }
660
661    this.getTarget = function(e) {
662      if (!e) return false;
663      if (e.target) return e.target;
664      if (e.srcElement) return e.srcElement;
665      return false;
666    };
667
668    this.hasParent = function(e, id) {
669      if (!e) return false;
670      var el = e.target || e.srcElement || e || false;
671      while (el && el.id != id) {
672        el = el.parentNode || false;
673      }
674      return (el !== false);
675    };
676
677    function getZIndex() {
678      var dom = self.win;
679      if ("zIndex" in dom) return dom.zIndex(); // use jQuery UI method when available
680      while (dom.length > 0) {
681        if (dom[0].nodeType == 9) return false;
682        var zi = dom.css('zIndex');
683        if (!isNaN(zi) && zi != 0) return parseInt(zi);
684        dom = dom.parent();
685      }
686      return false;
687    }
688
689    //inspired by http://forum.jquery.com/topic/width-includes-border-width-when-set-to-thin-medium-thick-in-ie
690    var _convertBorderWidth = {
691      "thin": 1,
692      "medium": 3,
693      "thick": 5
694    };
695
696    function getWidthToPixel(dom, prop, chkheight) {
697      var wd = dom.css(prop);
698      var px = parseFloat(wd);
699      if (isNaN(px)) {
700        px = _convertBorderWidth[wd] || 0;
701        var brd = (px == 3) ? ((chkheight) ? (self.win.outerHeight() - self.win.innerHeight()) : (self.win.outerWidth() - self.win.innerWidth())) : 1; //DON'T TRUST CSS
702        if (self.isie8 && px) px += 1;
703        return (brd) ? px : 0;
704      }
705      return px;
706    }
707
708    this.getDocumentScrollOffset = function() {
709      return {
710        top: window.pageYOffset || document.documentElement.scrollTop,
711        left: window.pageXOffset || document.documentElement.scrollLeft
712      };
713    };
714
715    this.getOffset = function() {
716      if (self.isfixed) {
717        var ofs = self.win.offset();  // fix Chrome auto issue (when right/bottom props only)
718        var scrl = self.getDocumentScrollOffset();
719        ofs.top-=scrl.top;
720        ofs.left-=scrl.left;
721        return ofs;
722      }
723      var ww = self.win.offset();
724      if (!self.viewport) return ww;
725      var vp = self.viewport.offset();
726      return {
727        top: ww.top - vp.top,// + self.viewport.scrollTop(),
728        left: ww.left - vp.left // + self.viewport.scrollLeft()
729      };
730    };
731
732    this.updateScrollBar = function(len) {
733      var pos, off;
734      if (self.ishwscroll) {
735        self.rail.css({  //**
736          height: self.win.innerHeight() - (self.opt.railpadding.top + self.opt.railpadding.bottom)
737        });
738        if (self.railh) self.railh.css({  //**
739          width: self.win.innerWidth() - (self.opt.railpadding.left + self.opt.railpadding.right)
740        });
741
742      } else {
743        var wpos = self.getOffset();
744        pos = {
745          top: wpos.top,
746          left: wpos.left - (self.opt.railpadding.left + self.opt.railpadding.right)
747        };
748        pos.top += getWidthToPixel(self.win, 'border-top-width', true);
749        pos.left += (self.rail.align) ? self.win.outerWidth() - getWidthToPixel(self.win, 'border-right-width') - self.rail.width : getWidthToPixel(self.win, 'border-left-width');
750
751        off = self.opt.railoffset;
752        if (off) {
753          if (off.top) pos.top += off.top;
754          if (off.left) pos.left += off.left;
755        }
756
757        if (!self.railslocked) self.rail.css({
758          top: pos.top,
759          left: pos.left,
760          height: ((len) ? len.h : self.win.innerHeight()) - (self.opt.railpadding.top + self.opt.railpadding.bottom)
761        });
762
763        if (self.zoom) {
764          self.zoom.css({
765            top: pos.top + 1,
766            left: (self.rail.align == 1) ? pos.left - 20 : pos.left + self.rail.width + 4
767          });
768        }
769
770        if (self.railh && !self.railslocked) {
771          pos = {
772            top: wpos.top,
773            left: wpos.left
774          };
775          off = self.opt.railhoffset;
776          if (off) {
777            if (off.top) pos.top += off.top;
778            if (off.left) pos.left += off.left;
779          }
780          var y = (self.railh.align) ? pos.top + getWidthToPixel(self.win, 'border-top-width', true) + self.win.innerHeight() - self.railh.height : pos.top + getWidthToPixel(self.win, 'border-top-width', true);
781          var x = pos.left + getWidthToPixel(self.win, 'border-left-width');
782          self.railh.css({
783            top: y - (self.opt.railpadding.top + self.opt.railpadding.bottom),
784            left: x,
785            width: self.railh.width
786          });
787        }
788
789      }
790    };
791
792    this.doRailClick = function(e, dbl, hr) {
793      var fn, pg, cur, pos;
794
795      if (self.railslocked) return;
796      self.cancelEvent(e);
797
798      if (dbl) {
799        fn = (hr) ? self.doScrollLeft : self.doScrollTop;
800        cur = (hr) ? ((e.pageX - self.railh.offset().left - (self.cursorwidth / 2)) * self.scrollratio.x) : ((e.pageY - self.rail.offset().top - (self.cursorheight / 2)) * self.scrollratio.y);
801        fn(cur);
802      } else {
803        fn = (hr) ? self.doScrollLeftBy : self.doScrollBy;
804        cur = (hr) ? self.scroll.x : self.scroll.y;
805        pos = (hr) ? e.pageX - self.railh.offset().left : e.pageY - self.rail.offset().top;
806        pg = (hr) ? self.view.w : self.view.h;
807        fn((cur >= pos) ? pg: -pg);//   (cur >= pos) ? fn(pg): fn(-pg);
808      }
809
810    };
811
812    self.hasanimationframe = (setAnimationFrame);
813    self.hascancelanimationframe = (clearAnimationFrame);
814
815    if (!self.hasanimationframe) {
816      setAnimationFrame = function(fn) {
817        return setTimeout(fn, 15 - Math.floor((+new Date()) / 1000) % 16);
818      }; // 1000/60)};
819      clearAnimationFrame = clearTimeout;
820    } else if (!self.hascancelanimationframe) clearAnimationFrame = function() {
821      self.cancelAnimationFrame = true;
822    };
823
824    this.init = function() {
825
826      self.saved.css = [];
827
828      if (cap.isie7mobile) return true; // SORRY, DO NOT WORK!
829      if (cap.isoperamini) return true; // SORRY, DO NOT WORK!
830
831      var _touchaction = (cap.isie10) ? '-ms-touch-action' : 'touch-action';
832      if (cap.hasmstouch) self.css((self.ispage) ? $("html") : self.win, {
833        _touchaction: 'none'
834      });
835
836      var _scrollyhidden =  (cap.ismodernie||cap.isie10) ? {'-ms-overflow-style':'none'} : {'overflow-y':'hidden'};  // IE is always a world apart!
837
838      self.zindex = "auto";
839      if (!self.ispage && self.opt.zindex == "auto") {
840        self.zindex = getZIndex() || "auto";
841      } else {
842        self.zindex = self.opt.zindex;
843      }
844
845      if (!self.ispage && self.zindex != "auto" && self.zindex > globalmaxzindex) {
846        globalmaxzindex = self.zindex;
847      }
848
849      if (self.isie && self.zindex == 0 && self.opt.zindex == "auto") { // fix IE auto == 0
850        self.zindex = "auto";
851      }
852
853      if (!self.ispage || (!cap.cantouch && !cap.isieold && !cap.isie9mobile)) {
854
855        var cont = self.docscroll;
856        if (self.ispage) cont = (self.haswrapper) ? self.win : self.doc;
857
858        if (!cap.isie9mobile) self.css(cont, _scrollyhidden);
859
860        if (self.ispage && cap.isie7) {
861          if (self.doc[0].nodeName == 'BODY') self.css($("html"), {
862            'overflow-y': 'hidden'
863          }); //IE7 double scrollbar issue
864          else if (self.doc[0].nodeName == 'HTML') self.css($("body"), _scrollyhidden); //IE7 double scrollbar issue
865        }
866
867        if (cap.isios && !self.ispage && !self.haswrapper) self.css($("body"), {
868          "-webkit-overflow-scrolling": "touch"
869        }); //force hw acceleration
870
871        var cursor = $(document.createElement('div'));
872        cursor.css({
873          position: "relative",
874          top: 0,
875          "float": "right",
876          width: self.opt.cursorwidth,
877          height: 0,
878          'background-color': self.opt.cursorcolor,
879          border: self.opt.cursorborder,
880          'background-clip': 'padding-box',
881          '-webkit-border-radius': self.opt.cursorborderradius,
882          '-moz-border-radius': self.opt.cursorborderradius,
883          'border-radius': self.opt.cursorborderradius
884        });
885
886        cursor.hborder = parseFloat(cursor.outerHeight() - cursor.innerHeight());
887
888        cursor.addClass('nicescroll-cursors');
889
890        self.cursor = cursor;
891
892        var rail = $(document.createElement('div'));
893        rail.attr('id', self.id);
894        rail.addClass('nicescroll-rails nicescroll-rails-vr');
895
896        var v, a, kp = ["left","right","top","bottom"];  //**
897        for (var n in kp) {
898          a = kp[n];
899          v = self.opt.railpadding[a];
900          (v) ? rail.css("padding-"+a,v+"px") : self.opt.railpadding[a] = 0;
901        }
902
903        rail.append(cursor);
904
905        rail.width = Math.max(parseFloat(self.opt.cursorwidth), cursor.outerWidth());
906        rail.css({
907          width: rail.width + "px",
908          zIndex: self.zindex,
909          background: self.opt.background,
910          cursor: "default"
911        });
912
913        rail.visibility = true;
914        rail.scrollable = true;
915
916        rail.align = (self.opt.railalign == "left") ? 0 : 1;
917
918        self.rail = rail;
919
920        self.rail.drag = false;
921
922        var zoom = false;
923        if (self.opt.boxzoom && !self.ispage && !cap.isieold) {
924          zoom = document.createElement('div');
925
926          self.bind(zoom, "click", self.doZoom);
927          self.bind(zoom, "mouseenter", function() {
928            self.zoom.css('opacity', self.opt.cursoropacitymax);
929          });
930          self.bind(zoom, "mouseleave", function() {
931            self.zoom.css('opacity', self.opt.cursoropacitymin);
932          });
933
934          self.zoom = $(zoom);
935          self.zoom.css({
936            cursor: "pointer",
937            zIndex: self.zindex,
938            backgroundImage: 'url(' + self.opt.scriptpath + 'zoomico.png)',
939            height: 18,
940            width: 18,
941            backgroundPosition: '0px 0px'
942          });
943          if (self.opt.dblclickzoom) self.bind(self.win, "dblclick", self.doZoom);
944          if (cap.cantouch && self.opt.gesturezoom) {
945            self.ongesturezoom = function(e) {
946              if (e.scale > 1.5) self.doZoomIn(e);
947              if (e.scale < 0.8) self.doZoomOut(e);
948              return self.cancelEvent(e);
949            };
950            self.bind(self.win, "gestureend", self.ongesturezoom);
951          }
952        }
953
954        // init HORIZ
955
956        self.railh = false;
957        var railh;
958
959        if (self.opt.horizrailenabled) {
960
961          self.css(cont, {
962            overflowX: 'hidden'
963          });
964
965          var cursor = $(document.createElement('div'));
966          cursor.css({
967            position: "absolute",
968            top: 0,
969            height: self.opt.cursorwidth,
970            width: 0,
971            backgroundColor: self.opt.cursorcolor,
972            border: self.opt.cursorborder,
973            backgroundClip: 'padding-box',
974            '-webkit-border-radius': self.opt.cursorborderradius,
975            '-moz-border-radius': self.opt.cursorborderradius,
976            'border-radius': self.opt.cursorborderradius
977          });
978
979          if (cap.isieold) cursor.css('overflow', 'hidden');  //IE6 horiz scrollbar issue
980
981          cursor.wborder = parseFloat(cursor.outerWidth() - cursor.innerWidth());
982
983          cursor.addClass('nicescroll-cursors');
984
985          self.cursorh = cursor;
986
987          railh = $(document.createElement('div'));
988          railh.attr('id', self.id + '-hr');
989          railh.addClass('nicescroll-rails nicescroll-rails-hr');
990          railh.height = Math.max(parseFloat(self.opt.cursorwidth), cursor.outerHeight());
991          railh.css({
992            height: railh.height + "px",
993            'zIndex': self.zindex,
994            "background": self.opt.background
995          });
996
997          railh.append(cursor);
998
999          railh.visibility = true;
1000          railh.scrollable = true;
1001
1002          railh.align = (self.opt.railvalign == "top") ? 0 : 1;
1003
1004          self.railh = railh;
1005
1006          self.railh.drag = false;
1007
1008        }
1009
1010        //
1011
1012        if (self.ispage) {
1013          rail.css({
1014            position: "fixed",
1015            top: 0,
1016            height: "100%"
1017          });
1018          (rail.align) ? rail.css({
1019            right: 0
1020          }): rail.css({
1021            left: 0
1022          });
1023          self.body.append(rail);
1024          if (self.railh) {
1025            railh.css({
1026              position: "fixed",
1027              left: 0,
1028              width: "100%"
1029            });
1030            (railh.align) ? railh.css({
1031              bottom: 0
1032            }): railh.css({
1033              top: 0
1034            });
1035            self.body.append(railh);
1036          }
1037        } else {
1038          if (self.ishwscroll) {
1039            if (self.win.css('position') == 'static') self.css(self.win, {
1040              'position': 'relative'
1041            });
1042            var bd = (self.win[0].nodeName == 'HTML') ? self.body : self.win;
1043            $(bd).scrollTop(0).scrollLeft(0);  // fix rail position if content already scrolled
1044            if (self.zoom) {
1045              self.zoom.css({
1046                position: "absolute",
1047                top: 1,
1048                right: 0,
1049                "margin-right": rail.width + 4
1050              });
1051              bd.append(self.zoom);
1052            }
1053            rail.css({
1054              position: "absolute",
1055              top: 0
1056            });
1057            (rail.align) ? rail.css({
1058              right: 0
1059            }): rail.css({
1060              left: 0
1061            });
1062            bd.append(rail);
1063            if (railh) {
1064              railh.css({
1065                position: "absolute",
1066                left: 0,
1067                bottom: 0
1068              });
1069              (railh.align) ? railh.css({
1070                bottom: 0
1071              }): railh.css({
1072                top: 0
1073              });
1074              bd.append(railh);
1075            }
1076          } else {
1077            self.isfixed = (self.win.css("position") == "fixed");
1078            var rlpos = (self.isfixed) ? "fixed" : "absolute";
1079
1080            if (!self.isfixed) self.viewport = self.getViewport(self.win[0]);
1081            if (self.viewport) {
1082              self.body = self.viewport;
1083              if ((/fixed|absolute/.test(self.viewport.css("position"))) == false) self.css(self.viewport, {
1084                "position": "relative"
1085              });
1086            }
1087
1088            rail.css({
1089              position: rlpos
1090            });
1091            if (self.zoom) self.zoom.css({
1092              position: rlpos
1093            });
1094            self.updateScrollBar();
1095            self.body.append(rail);
1096            if (self.zoom) self.body.append(self.zoom);
1097            if (self.railh) {
1098              railh.css({
1099                position: rlpos
1100              });
1101              self.body.append(railh);
1102            }
1103          }
1104
1105          if (cap.isios) self.css(self.win, {
1106            '-webkit-tap-highlight-color': 'rgba(0,0,0,0)',
1107            '-webkit-touch-callout': 'none'
1108          }); // prevent grey layer on click
1109
1110          if (cap.isie && self.opt.disableoutline) self.win.attr("hideFocus", "true"); // IE, prevent dotted rectangle on focused div
1111          if (cap.iswebkit && self.opt.disableoutline) self.win.css('outline', 'none');  // Webkit outline
1112          //if (cap.isopera&&self.opt.disableoutline) self.win.css({"outline":"0"});  // Opera 12- to test [TODO]
1113
1114        }
1115
1116        if (self.opt.autohidemode === false) {
1117          self.autohidedom = false;
1118          self.rail.css({
1119            opacity: self.opt.cursoropacitymax
1120          });
1121          if (self.railh) self.railh.css({
1122            opacity: self.opt.cursoropacitymax
1123          });
1124        } else if ((self.opt.autohidemode === true) || (self.opt.autohidemode === "leave")) {
1125          self.autohidedom = $().add(self.rail);
1126          if (cap.isie8) self.autohidedom = self.autohidedom.add(self.cursor);
1127          if (self.railh) self.autohidedom = self.autohidedom.add(self.railh);
1128          if (self.railh && cap.isie8) self.autohidedom = self.autohidedom.add(self.cursorh);
1129        } else if (self.opt.autohidemode == "scroll") {
1130          self.autohidedom = $().add(self.rail);
1131          if (self.railh) self.autohidedom = self.autohidedom.add(self.railh);
1132        } else if (self.opt.autohidemode == "cursor") {
1133          self.autohidedom = $().add(self.cursor);
1134          if (self.railh) self.autohidedom = self.autohidedom.add(self.cursorh);
1135        } else if (self.opt.autohidemode == "hidden") {
1136          self.autohidedom = false;
1137          self.hide();
1138          self.railslocked = false;
1139        }
1140
1141        if (cap.isie9mobile) {
1142
1143          self.scrollmom = new ScrollMomentumClass2D(self);
1144
1145          self.onmangotouch = function() {
1146            var py = self.getScrollTop();
1147            var px = self.getScrollLeft();
1148
1149            if ((py == self.scrollmom.lastscrolly) && (px == self.scrollmom.lastscrollx)) return true;
1150
1151            var dfy = py - self.mangotouch.sy;
1152            var dfx = px - self.mangotouch.sx;
1153            var df = Math.round(Math.sqrt(Math.pow(dfx, 2) + Math.pow(dfy, 2)));
1154            if (df == 0) return;
1155
1156            var dry = (dfy < 0) ? -1 : 1;
1157            var drx = (dfx < 0) ? -1 : 1;
1158
1159            var tm = +new Date();
1160            if (self.mangotouch.lazy) clearTimeout(self.mangotouch.lazy);
1161
1162            if (((tm - self.mangotouch.tm) > 80) || (self.mangotouch.dry != dry) || (self.mangotouch.drx != drx)) {
1163              self.scrollmom.stop();
1164              self.scrollmom.reset(px, py);
1165              self.mangotouch.sy = py;
1166              self.mangotouch.ly = py;
1167              self.mangotouch.sx = px;
1168              self.mangotouch.lx = px;
1169              self.mangotouch.dry = dry;
1170              self.mangotouch.drx = drx;
1171              self.mangotouch.tm = tm;
1172            } else {
1173
1174              self.scrollmom.stop();
1175              self.scrollmom.update(self.mangotouch.sx - dfx, self.mangotouch.sy - dfy);
1176              self.mangotouch.tm = tm;
1177
1178              var ds = Math.max(Math.abs(self.mangotouch.ly - py), Math.abs(self.mangotouch.lx - px));
1179              self.mangotouch.ly = py;
1180              self.mangotouch.lx = px;
1181
1182              if (ds > 2) {
1183                self.mangotouch.lazy = setTimeout(function() {
1184                  self.mangotouch.lazy = false;
1185                  self.mangotouch.dry = 0;
1186                  self.mangotouch.drx = 0;
1187                  self.mangotouch.tm = 0;
1188                  self.scrollmom.doMomentum(30);
1189                }, 100);
1190              }
1191            }
1192          };
1193
1194          var top = self.getScrollTop();
1195          var lef = self.getScrollLeft();
1196          self.mangotouch = {
1197            sy: top,
1198            ly: top,
1199            dry: 0,
1200            sx: lef,
1201            lx: lef,
1202            drx: 0,
1203            lazy: false,
1204            tm: 0
1205          };
1206
1207          self.bind(self.docscroll, "scroll", self.onmangotouch);
1208
1209        } else {
1210
1211          if (cap.cantouch || self.istouchcapable || self.opt.touchbehavior || cap.hasmstouch) {
1212
1213            self.scrollmom = new ScrollMomentumClass2D(self);
1214
1215            self.ontouchstart = function(e) {
1216              if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
1217
1218              self.hasmoving = false;
1219
1220              if (!self.railslocked) {
1221                var tg;
1222                if (cap.hasmstouch) {
1223                  tg = (e.target) ? e.target : false;
1224                  while (tg) {
1225                    var nc = $(tg).getNiceScroll();
1226                    if ((nc.length > 0) && (nc[0].me == self.me)) break;
1227                    if (nc.length > 0) return false;
1228                    if ((tg.nodeName == 'DIV') && (tg.id == self.id)) break;
1229                    tg = (tg.parentNode) ? tg.parentNode : false;
1230                  }
1231                }
1232
1233                self.cancelScroll();
1234
1235                tg = self.getTarget(e);
1236
1237                if (tg) {
1238                  var skp = (/INPUT/i.test(tg.nodeName)) && (/range/i.test(tg.type));
1239                  if (skp) return self.stopPropagation(e);
1240                }
1241
1242                if (!("clientX" in e) && ("changedTouches" in e)) {
1243                  e.clientX = e.changedTouches[0].clientX;
1244                  e.clientY = e.changedTouches[0].clientY;
1245                }
1246
1247                if (self.forcescreen) {
1248                  var le = e;
1249                  e = {
1250                    "original": (e.original) ? e.original : e
1251                  };
1252                  e.clientX = le.screenX;
1253                  e.clientY = le.screenY;
1254                }
1255
1256                self.rail.drag = {
1257                  x: e.clientX,
1258                  y: e.clientY,
1259                  sx: self.scroll.x,
1260                  sy: self.scroll.y,
1261                  st: self.getScrollTop(),
1262                  sl: self.getScrollLeft(),
1263                  pt: 2,
1264                  dl: false
1265                };
1266
1267                if (self.ispage || !self.opt.directionlockdeadzone) {
1268                  self.rail.drag.dl = "f";
1269                } else {
1270
1271                  var view = {
1272                    w: $(window).width(),
1273                    h: $(window).height()
1274                  };
1275
1276                  var page = {
1277                    w: Math.max(document.body.scrollWidth, document.documentElement.scrollWidth),
1278                    h: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)
1279                  };
1280
1281                  var maxh = Math.max(0, page.h - view.h);
1282                  var maxw = Math.max(0, page.w - view.w);
1283
1284                  if (!self.rail.scrollable && self.railh.scrollable) self.rail.drag.ck = (maxh > 0) ? "v" : false;
1285                  else if (self.rail.scrollable && !self.railh.scrollable) self.rail.drag.ck = (maxw > 0) ? "h" : false;
1286                  else self.rail.drag.ck = false;
1287                  if (!self.rail.drag.ck) self.rail.drag.dl = "f";
1288                }
1289
1290                if (self.opt.touchbehavior && self.isiframe && cap.isie) {
1291                  var wp = self.win.position();
1292                  self.rail.drag.x += wp.left;
1293                  self.rail.drag.y += wp.top;
1294                }
1295
1296                self.hasmoving = false;
1297                self.lastmouseup = false;
1298                self.scrollmom.reset(e.clientX, e.clientY);
1299
1300                if (!cap.cantouch && !this.istouchcapable && !e.pointerType) {
1301
1302                  var ip = (tg) ? /INPUT|SELECT|TEXTAREA/i.test(tg.nodeName) : false;
1303                  if (!ip) {
1304                    if (!self.ispage && cap.hasmousecapture) tg.setCapture();
1305                    if (self.opt.touchbehavior) {
1306                      if (tg.onclick && !(tg._onclick || false)) { // intercept DOM0 onclick event
1307                        tg._onclick = tg.onclick;
1308                        tg.onclick = function(e) {
1309                          if (self.hasmoving) return false;
1310                          tg._onclick.call(this, e);
1311                        };
1312                      }
1313                      return self.cancelEvent(e);
1314                    }
1315                    return self.stopPropagation(e);
1316                  }
1317
1318                  if (/SUBMIT|CANCEL|BUTTON/i.test($(tg).attr('type'))) {
1319                    pc = {
1320                      "tg": tg,
1321                      "click": false
1322                    };
1323                    self.preventclick = pc;
1324                  }
1325
1326                }
1327              }
1328
1329            };
1330
1331            self.ontouchend = function(e) {
1332              if (!self.rail.drag) return true;
1333              if (self.rail.drag.pt == 2) {
1334                if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
1335
1336                self.scrollmom.doMomentum();
1337                self.rail.drag = false;
1338                if (self.hasmoving) {
1339                  self.lastmouseup = true;
1340                  self.hideCursor();
1341                  if (cap.hasmousecapture) document.releaseCapture();
1342                  if (!cap.cantouch) return self.cancelEvent(e);
1343                }
1344              }
1345              else if (self.rail.drag.pt == 1) {
1346                return self.onmouseup(e);
1347              }
1348
1349            };
1350
1351            var moveneedoffset = (self.opt.touchbehavior && self.isiframe && !cap.hasmousecapture);
1352
1353            self.ontouchmove = function(e, byiframe) {
1354
1355              if (!self.rail.drag) return false;
1356
1357              if (e.targetTouches && self.opt.preventmultitouchscrolling) {
1358                if (e.targetTouches.length > 1) return false; // multitouch
1359              }
1360
1361              if (e.pointerType && e.pointerType != 2 && e.pointerType != "touch") return false;
1362
1363              if (self.rail.drag.pt == 2) {
1364                if (cap.cantouch && (cap.isios) && e.original === undefined) return true; // prevent ios "ghost" events by clickable elements
1365
1366                self.hasmoving = true;
1367
1368                if (self.preventclick && !self.preventclick.click) {
1369                  self.preventclick.click = self.preventclick.tg.onclick || false;
1370                  self.preventclick.tg.onclick = self.onpreventclick;
1371                }
1372
1373                var ev = $.extend({
1374                  "original": e
1375                }, e);
1376                e = ev;
1377
1378                if (("changedTouches" in e)) {
1379                  e.clientX = e.changedTouches[0].clientX;
1380                  e.clientY = e.changedTouches[0].clientY;
1381                }
1382
1383                if (self.forcescreen) {
1384                  var le = e;
1385                  e = {
1386                    "original": (e.original) ? e.original : e
1387                  };
1388                  e.clientX = le.screenX;
1389                  e.clientY = le.screenY;
1390                }
1391
1392                var ofy,ofx;
1393                ofx = ofy = 0;
1394
1395                if (moveneedoffset && !byiframe) {
1396                  var wp = self.win.position();
1397                  ofx = -wp.left;
1398                  ofy = -wp.top;
1399                }
1400
1401                var fy = e.clientY + ofy;
1402                var my = (fy - self.rail.drag.y);
1403                var fx = e.clientX + ofx;
1404                var mx = (fx - self.rail.drag.x);
1405
1406                var ny = self.rail.drag.st - my;
1407
1408                if (self.ishwscroll && self.opt.bouncescroll) {
1409                  if (ny < 0) {
1410                    ny = Math.round(ny / 2);
1411                    //                    fy = 0;
1412                  } else if (ny > self.page.maxh) {
1413                    ny = self.page.maxh + Math.round((ny - self.page.maxh) / 2);
1414                    //                    fy = 0;
1415                  }
1416                } else {
1417                  if (ny < 0) {
1418                    ny = 0;
1419                    fy = 0;
1420                  }
1421                  if (ny > self.page.maxh) {
1422                    ny = self.page.maxh;
1423                    fy = 0;
1424                  }
1425                }
1426
1427                var nx;
1428                if (self.railh && self.railh.scrollable) {
1429                  nx = (self.isrtlmode) ? mx - self.rail.drag.sl : self.rail.drag.sl - mx;
1430
1431                  if (self.ishwscroll && self.opt.bouncescroll) {
1432                    if (nx < 0) {
1433                      nx = Math.round(nx / 2);
1434                      //                      fx = 0;
1435                    } else if (nx > self.page.maxw) {
1436                      nx = self.page.maxw + Math.round((nx - self.page.maxw) / 2);
1437                      //                      fx = 0;
1438                    }
1439                  } else {
1440                    if (nx < 0) {
1441                      nx = 0;
1442                      fx = 0;
1443                    }
1444                    if (nx > self.page.maxw) {
1445                      nx = self.page.maxw;
1446                      fx = 0;
1447                    }
1448                  }
1449
1450                }
1451
1452                var grabbed = false;
1453                if (self.rail.drag.dl) {
1454                  grabbed = true;
1455                  if (self.rail.drag.dl == "v") nx = self.rail.drag.sl;
1456                  else if (self.rail.drag.dl == "h") ny = self.rail.drag.st;
1457                } else {
1458                  var ay = Math.abs(my);
1459                  var ax = Math.abs(mx);
1460                  var dz = self.opt.directionlockdeadzone;
1461                  if (self.rail.drag.ck == "v") {
1462                    if (ay > dz && (ax <= (ay * 0.3))) {
1463                      self.rail.drag = false;
1464                      return true;
1465                    } else if (ax > dz) {
1466                      self.rail.drag.dl = "f";
1467                      $("body").scrollTop($("body").scrollTop()); // stop iOS native scrolling (when active javascript has blocked)
1468                    }
1469                  } else if (self.rail.drag.ck == "h") {
1470                    if (ax > dz && (ay <= (ax * 0.3))) {
1471                      self.rail.drag = false;
1472                      return true;
1473                    } else if (ay > dz) {
1474                      self.rail.drag.dl = "f";
1475                      $("body").scrollLeft($("body").scrollLeft()); // stop iOS native scrolling (when active javascript has blocked)
1476                    }
1477                  }
1478                }
1479
1480                self.synched("touchmove", function() {
1481                  if (self.rail.drag && (self.rail.drag.pt == 2)) {
1482                    if (self.prepareTransition) self.prepareTransition(0);
1483                    if (self.rail.scrollable) self.setScrollTop(ny);
1484                    self.scrollmom.update(fx, fy);
1485                    if (self.railh && self.railh.scrollable) {
1486                      self.setScrollLeft(nx);
1487                      self.showCursor(ny, nx);
1488                    } else {
1489                      self.showCursor(ny);
1490                    }
1491                    if (cap.isie10) document.selection.clear();
1492                  }
1493                });
1494
1495                if (cap.ischrome && self.istouchcapable) grabbed = false; //chrome touch emulation doesn't like!
1496                if (grabbed) return self.cancelEvent(e);
1497              }
1498              else if (self.rail.drag.pt == 1) { // drag on cursor
1499                return self.onmousemove(e);
1500              }
1501
1502            };
1503
1504          }
1505
1506          self.onmousedown = function(e, hronly) {
1507            if (self.rail.drag && self.rail.drag.pt != 1) return;
1508            if (self.railslocked) return self.cancelEvent(e);
1509            self.cancelScroll();
1510            self.rail.drag = {
1511              x: e.clientX,
1512              y: e.clientY,
1513              sx: self.scroll.x,
1514              sy: self.scroll.y,
1515              pt: 1,
1516              hr: (!!hronly)
1517            };
1518            var tg = self.getTarget(e);
1519            if (!self.ispage && cap.hasmousecapture) tg.setCapture();
1520            if (self.isiframe && !cap.hasmousecapture) {
1521              self.saved.csspointerevents = self.doc.css("pointer-events");
1522              self.css(self.doc, {
1523                "pointer-events": "none"
1524              });
1525            }
1526            self.hasmoving = false;
1527            return self.cancelEvent(e);
1528          };
1529
1530          self.onmouseup = function(e) {
1531            if (self.rail.drag) {
1532              if (self.rail.drag.pt != 1) return true;
1533
1534              if (cap.hasmousecapture) document.releaseCapture();
1535              if (self.isiframe && !cap.hasmousecapture) self.doc.css("pointer-events", self.saved.csspointerevents);
1536              self.rail.drag = false;
1537              //if (!self.rail.active) self.hideCursor();
1538              if (self.hasmoving) self.triggerScrollEnd(); // TODO - check &&!self.scrollrunning
1539              return self.cancelEvent(e);
1540            }
1541          };
1542
1543          self.onmousemove = function(e) {
1544            if (self.rail.drag) {
1545              if (self.rail.drag.pt != 1) return;
1546
1547              if (cap.ischrome && e.which == 0) return self.onmouseup(e);
1548
1549              self.cursorfreezed = true;
1550              self.hasmoving = true;
1551
1552              if (self.rail.drag.hr) {
1553                self.scroll.x = self.rail.drag.sx + (e.clientX - self.rail.drag.x);
1554                if (self.scroll.x < 0) self.scroll.x = 0;
1555                var mw = self.scrollvaluemaxw;
1556                if (self.scroll.x > mw) self.scroll.x = mw;
1557              } else {
1558                self.scroll.y = self.rail.drag.sy + (e.clientY - self.rail.drag.y);
1559                if (self.scroll.y < 0) self.scroll.y = 0;
1560                var my = self.scrollvaluemax;
1561                if (self.scroll.y > my) self.scroll.y = my;
1562              }
1563
1564              self.synched('mousemove', function() {
1565                if (self.rail.drag && (self.rail.drag.pt == 1)) {
1566                  self.showCursor();
1567                  if (self.rail.drag.hr) {
1568                    if (self.hasreversehr) {
1569                      self.doScrollLeft(self.scrollvaluemaxw-Math.round(self.scroll.x * self.scrollratio.x), self.opt.cursordragspeed);
1570                    } else {
1571                      self.doScrollLeft(Math.round(self.scroll.x * self.scrollratio.x), self.opt.cursordragspeed);
1572                    }
1573                  }
1574                  else self.doScrollTop(Math.round(self.scroll.y * self.scrollratio.y), self.opt.cursordragspeed);
1575                }
1576              });
1577
1578              return self.cancelEvent(e);
1579            }
1580            else {
1581              self.checkarea = 0;
1582            }
1583          };
1584
1585          if (cap.cantouch || self.opt.touchbehavior) {
1586
1587            self.onpreventclick = function(e) {
1588              if (self.preventclick) {
vendor: 10,215 bytes, lines 1589-1851
1589                self.preventclick.tg.onclick = self.preventclick.click;
1590                self.preventclick = false;
1591                return self.cancelEvent(e);
1592              }
1593            };
1594
1595            self.bind(self.win, "mousedown", self.ontouchstart); // control content dragging
1596
1597            self.onclick = (cap.isios) ? false : function(e) {  // it needs to check IE11 ???
1598              if (self.lastmouseup) {
1599                self.lastmouseup = false;
1600                return self.cancelEvent(e);
1601              } else {
1602                return true;
1603              }
1604            };
1605
1606            if (self.opt.grabcursorenabled && cap.cursorgrabvalue) {
1607              self.css((self.ispage) ? self.doc : self.win, {
1608                'cursor': cap.cursorgrabvalue
1609              });
1610              self.css(self.rail, {
1611                'cursor': cap.cursorgrabvalue
1612              });
1613            }
1614
1615          } else {
1616
1617            var checkSelectionScroll = function(e) {
1618              if (!self.selectiondrag) return;
1619
1620              if (e) {
1621                var ww = self.win.outerHeight();
1622                var df = (e.pageY - self.selectiondrag.top);
1623                if (df > 0 && df < ww) df = 0;
1624                if (df >= ww) df -= ww;
1625                self.selectiondrag.df = df;
1626              }
1627              if (self.selectiondrag.df == 0) return;
1628
1629              var rt = -Math.floor(self.selectiondrag.df / 6) * 2;
1630              self.doScrollBy(rt);
1631
1632              self.debounced("doselectionscroll", function() {
1633                checkSelectionScroll();
1634              }, 50);
1635            };
1636
1637            if ("getSelection" in document) { // A grade - Major browsers
1638              self.hasTextSelected = function() {
1639                return (document.getSelection().rangeCount > 0);
1640              };
1641            } else if ("selection" in document) { //IE9-
1642              self.hasTextSelected = function() {
1643                return (document.selection.type != "None");
1644              };
1645            } else {
1646              self.hasTextSelected = function() { // no support
1647                return false;
1648              };
1649            }
1650
1651            self.onselectionstart = function(e) {
1652/*  More testing - severe chrome issues
1653              if (!self.haswrapper&&(e.which&&e.which==2)) {  // fool browser to manage middle button scrolling
1654                self.win.css({'overflow':'auto'});
1655                setTimeout(function(){
1656                  self.win.css({'overflow':''});
1657                },10);
1658                return true;
1659              }
1660*/
1661              if (self.ispage) return;
1662              self.selectiondrag = self.win.offset();
1663            };
1664
1665            self.onselectionend = function(e) {
1666              self.selectiondrag = false;
1667            };
1668            self.onselectiondrag = function(e) {
1669              if (!self.selectiondrag) return;
1670              if (self.hasTextSelected()) self.debounced("selectionscroll", function() {
1671                checkSelectionScroll(e);
1672              }, 250);
1673            };
1674
1675
1676          }
1677
1678          if (cap.hasw3ctouch) { //IE11+
1679            self.css(self.rail, {
1680              'touch-action': 'none'
1681            });
1682            self.css(self.cursor, {
1683              'touch-action': 'none'
1684            });
1685            self.bind(self.win, "pointerdown", self.ontouchstart);
1686            self.bind(document, "pointerup", self.ontouchend);
1687            self.bind(document, "pointermove", self.ontouchmove);
1688          } else if (cap.hasmstouch) { //IE10
1689            self.css(self.rail, {
1690              '-ms-touch-action': 'none'
1691            });
1692            self.css(self.cursor, {
1693              '-ms-touch-action': 'none'
1694            });
1695            self.bind(self.win, "MSPointerDown", self.ontouchstart);
1696            self.bind(document, "MSPointerUp", self.ontouchend);
1697            self.bind(document, "MSPointerMove", self.ontouchmove);
1698            self.bind(self.cursor, "MSGestureHold", function(e) {
1699              e.preventDefault();
1700            });
1701            self.bind(self.cursor, "contextmenu", function(e) {
1702              e.preventDefault();
1703            });
1704          } else if (this.istouchcapable) { //desktop with screen touch enabled
1705            self.bind(self.win, "touchstart", self.ontouchstart);
1706            self.bind(document, "touchend", self.ontouchend);
1707            self.bind(document, "touchcancel", self.ontouchend);
1708            self.bind(document, "touchmove", self.ontouchmove);
1709          }
1710
1711
1712          if (self.opt.cursordragontouch || (!cap.cantouch && !self.opt.touchbehavior)) {
1713
1714            self.rail.css({
1715              cursor: "default"
1716            });
1717            self.railh && self.railh.css({
1718              cursor: "default"
1719            });
1720
1721            self.jqbind(self.rail, "mouseenter", function() {
1722              if (!self.ispage && !self.win.is(":visible")) return false;
1723              if (self.canshowonmouseevent) self.showCursor();
1724              self.rail.active = true;
1725            });
1726            self.jqbind(self.rail, "mouseleave", function() {
1727              self.rail.active = false;
1728              if (!self.rail.drag) self.hideCursor();
1729            });
1730
1731            if (self.opt.sensitiverail) {
1732              self.bind(self.rail, "click", function(e) {
1733                self.doRailClick(e, false, false);
1734              });
1735              self.bind(self.rail, "dblclick", function(e) {
1736                self.doRailClick(e, true, false);
1737              });
1738              self.bind(self.cursor, "click", function(e) {
1739                self.cancelEvent(e);
1740              });
1741              self.bind(self.cursor, "dblclick", function(e) {
1742                self.cancelEvent(e);
1743              });
1744            }
1745
1746            if (self.railh) {
1747              self.jqbind(self.railh, "mouseenter", function() {
1748                if (!self.ispage && !self.win.is(":visible")) return false;
1749                if (self.canshowonmouseevent) self.showCursor();
1750                self.rail.active = true;
1751              });
1752              self.jqbind(self.railh, "mouseleave", function() {
1753                self.rail.active = false;
1754                if (!self.rail.drag) self.hideCursor();
1755              });
1756
1757              if (self.opt.sensitiverail) {
1758                self.bind(self.railh, "click", function(e) {
1759                  self.doRailClick(e, false, true);
1760                });
1761                self.bind(self.railh, "dblclick", function(e) {
1762                  self.doRailClick(e, true, true);
1763                });
1764                self.bind(self.cursorh, "click", function(e) {
1765                  self.cancelEvent(e);
1766                });
1767                self.bind(self.cursorh, "dblclick", function(e) {
1768                  self.cancelEvent(e);
1769                });
1770              }
1771
1772            }
1773
1774          }
1775
1776          if (!cap.cantouch && !self.opt.touchbehavior) {
1777
1778            self.bind((cap.hasmousecapture) ? self.win : document, "mouseup", self.onmouseup);
1779            self.bind(document, "mousemove", self.onmousemove);
1780            if (self.onclick) self.bind(document, "click", self.onclick);
1781
1782            self.bind(self.cursor, "mousedown", self.onmousedown);
1783            self.bind(self.cursor, "mouseup", self.onmouseup);
1784
1785            if (self.railh) {
1786              self.bind(self.cursorh, "mousedown", function(e) {
1787                self.onmousedown(e, true);
1788              });
1789              self.bind(self.cursorh, "mouseup", self.onmouseup);
1790            }
1791
1792            if (!self.ispage && self.opt.enablescrollonselection) {
1793              self.bind(self.win[0], "mousedown", self.onselectionstart);
1794              self.bind(document, "mouseup", self.onselectionend);
1795              self.bind(self.cursor, "mouseup", self.onselectionend);
1796              if (self.cursorh) self.bind(self.cursorh, "mouseup", self.onselectionend);
1797              self.bind(document, "mousemove", self.onselectiondrag);
1798            }
1799
1800            if (self.zoom) {
1801              self.jqbind(self.zoom, "mouseenter", function() {
1802                if (self.canshowonmouseevent) self.showCursor();
1803                self.rail.active = true;
1804              });
1805              self.jqbind(self.zoom, "mouseleave", function() {
1806                self.rail.active = false;
1807                if (!self.rail.drag) self.hideCursor();
1808              });
1809            }
1810
1811          } else {
1812
1813            self.bind((cap.hasmousecapture) ? self.win : document, "mouseup", self.ontouchend);
1814            self.bind(document, "mousemove", self.ontouchmove);
1815            if (self.onclick) self.bind(document, "click", self.onclick);
1816
1817            if (self.opt.cursordragontouch) {
1818              self.bind(self.cursor, "mousedown", self.onmousedown);
1819              self.bind(self.cursor, "mouseup", self.onmouseup);
1820              //self.bind(self.cursor, "mousemove", self.onmousemove);
1821              self.cursorh && self.bind(self.cursorh, "mousedown", function(e) {
1822                self.onmousedown(e, true);
1823              });
1824              //self.cursorh && self.bind(self.cursorh, "mousemove", self.onmousemove);
1825              self.cursorh && self.bind(self.cursorh, "mouseup", self.onmouseup);
1826            } else {
1827              self.bind(self.rail, "mousedown", function(e){e.preventDefault();});  // prevent text selection
1828							self.railh&&self.bind(self.railh, "mousedown", function(e){e.preventDefault();});
1829            }
1830
1831          }
1832
1833
1834          if (self.opt.enablemousewheel) {
1835            if (!self.isiframe) self.mousewheel((cap.isie && self.ispage) ? document : self.win , self.onmousewheel);
1836            self.mousewheel(self.rail, self.onmousewheel);
1837            if (self.railh) self.mousewheel(self.railh, self.onmousewheelhr);
1838          }
1839
1840          if (!self.ispage && !cap.cantouch && !(/HTML|^BODY/.test(self.win[0].nodeName))) {
1841            if (!self.win.attr("tabindex")) self.win.attr({
1842              "tabindex": tabindexcounter++
1843            });
1844
1845            self.jqbind(self.win, "focus", function(e) {
1846              domfocus = (self.getTarget(e)).id || true;
1847              self.hasfocus = true;
1848              if (self.canshowonmouseevent) self.noticeCursor();
1849            });
1850            self.jqbind(self.win, "blur", function(e) {
1851              domfocus = false;
1852              self.hasfocus = false;
1853            });
1854
1855            self.jqbind(self.win, "mouseenter", function(e) {
1856              mousefocus = (self.getTarget(e)).id || true;
1857              self.hasmousefocus = true;
1858              if (self.canshowonmouseevent) self.noticeCursor();
1859            });
1860            self.jqbind(self.win, "mouseleave", function() {
1861              mousefocus = false;
1862              self.hasmousefocus = false;
1863              if (!self.rail.drag) self.hideCursor();
1864            });
1865
1866          }
1867
1868        } // !ie9mobile
1869
1870        //Thanks to http://www.quirksmode.org !!
1871        self.onkeypress = function(e) {
1872          if (self.railslocked && self.page.maxh == 0) return true;
1873
1874          e = (e) ? e : window.e;
1875          var tg = self.getTarget(e);
1876          if (tg && /INPUT|TEXTAREA|SELECT|OPTION/.test(tg.nodeName)) {
1877            var tp = tg.getAttribute('type') || tg.type || false;
1878            if ((!tp) || !(/submit|button|cancel/i.tp)) return true;
1879          }
1880
1881          if ($(tg).attr('contenteditable')) return true;
1882
1883          if (self.hasfocus || (self.hasmousefocus && !domfocus) || (self.ispage && !domfocus && !mousefocus)) {
1884            var key = e.keyCode;
1885
1886            if (self.railslocked && key != 27) return self.cancelEvent(e);
1887
1888            var ctrl = e.ctrlKey || false;
1889            var shift = e.shiftKey || false;
1890
1891            var ret = false;
vendor: 4,937 bytes, lines 1892-2021
1892            switch (key) {
1893              case 38:
1894              case 63233: //safari
1895                self.doScrollBy(24 * 3);
1896                ret = true;
1897                break;
1898              case 40:
1899              case 63235: //safari
1900                self.doScrollBy(-24 * 3);
1901                ret = true;
1902                break;
1903              case 37:
1904              case 63232: //safari
1905                if (self.railh) {
1906                  (ctrl) ? self.doScrollLeft(0): self.doScrollLeftBy(24 * 3);
1907                  ret = true;
1908                }
1909                break;
1910              case 39:
1911              case 63234: //safari
1912                if (self.railh) {
1913                  (ctrl) ? self.doScrollLeft(self.page.maxw): self.doScrollLeftBy(-24 * 3);
1914                  ret = true;
1915                }
1916                break;
1917              case 33:
1918              case 63276: // safari
1919                self.doScrollBy(self.view.h);
1920                ret = true;
1921                break;
1922              case 34:
1923              case 63277: // safari
1924                self.doScrollBy(-self.view.h);
1925                ret = true;
1926                break;
1927              case 36:
1928              case 63273: // safari
1929                (self.railh && ctrl) ? self.doScrollPos(0, 0): self.doScrollTo(0);
1930                ret = true;
1931                break;
1932              case 35:
1933              case 63275: // safari
1934                (self.railh && ctrl) ? self.doScrollPos(self.page.maxw, self.page.maxh): self.doScrollTo(self.page.maxh);
1935                ret = true;
1936                break;
1937              case 32:
1938                if (self.opt.spacebarenabled) {
1939                  (shift) ? self.doScrollBy(self.view.h): self.doScrollBy(-self.view.h);
1940                  ret = true;
1941                }
1942                break;
1943              case 27: // ESC
1944                if (self.zoomactive) {
1945                  self.doZoom();
1946                  ret = true;
1947                }
1948                break;
1949            }
1950            if (ret) return self.cancelEvent(e);
1951          }
1952        };
1953
1954        if (self.opt.enablekeyboard) self.bind(document, (cap.isopera && !cap.isopera12) ? "keypress" : "keydown", self.onkeypress);
1955
1956        self.bind(document, "keydown", function(e) {
1957          var ctrl = e.ctrlKey || false;
1958          if (ctrl) self.wheelprevented = true;
1959        });
1960        self.bind(document, "keyup", function(e) {
1961          var ctrl = e.ctrlKey || false;
1962          if (!ctrl) self.wheelprevented = false;
1963        });
1964        self.bind(window,"blur",function(e){
1965          self.wheelprevented = false;
1966        });
1967
1968        self.bind(window, 'resize', self.lazyResize);
1969        self.bind(window, 'orientationchange', self.lazyResize);
1970
1971        self.bind(window, "load", self.lazyResize);
1972
1973        if (cap.ischrome && !self.ispage && !self.haswrapper) { //chrome void scrollbar bug - it persists in version 26
1974          var tmp = self.win.attr("style");
1975          var ww = parseFloat(self.win.css("width")) + 1;
1976          self.win.css('width', ww);
1977          self.synched("chromefix", function() {
1978            self.win.attr("style", tmp);
1979          });
1980        }
1981
1982
1983        // Trying a cross-browser implementation - good luck!
1984
1985        self.onAttributeChange = function(e) {
1986          self.lazyResize(self.isieold ? 250 : 30);
1987        };
1988
1989        if ((!self.isie11) && (ClsMutationObserver !== false)) {  // IE11 crashes  #568
1990          self.observerbody = new ClsMutationObserver(function(mutations) {
1991            mutations.forEach(function(mut){
1992              if (mut.type=="attributes") {
1993                return ($("body").hasClass("modal-open") && $("body").hasClass("modal-dialog") && !$.contains($('.modal-dialog')[0],self.doc[0])) ? self.hide() : self.show();  // Support for Bootstrap modal; Added check if the nice scroll element is inside a modal
1994              }
1995            });
1996            if (document.body.scrollHeight!=self.page.maxh) return self.lazyResize(30);
1997          });
1998          self.observerbody.observe(document.body, {
1999            childList: true,
2000            subtree: true,
2001            characterData: false,
2002            attributes: true,
2003            attributeFilter: ['class']
2004          });
2005        }
2006
2007        if (!self.ispage && !self.haswrapper) {
2008          // redesigned MutationObserver for Chrome18+/Firefox14+/iOS6+ with support for: remove div, add/remove content
2009          if (ClsMutationObserver !== false) {
2010            self.observer = new ClsMutationObserver(function(mutations) {
2011              mutations.forEach(self.onAttributeChange);
2012            });
2013            self.observer.observe(self.win[0], {
2014              childList: true,
2015              characterData: false,
2016              attributes: true,
2017              subtree: false
2018            });
2019            self.observerremover = new ClsMutationObserver(function(mutations) {
2020              mutations.forEach(function(mo) {
2021                if (mo.removedNodes.length > 0) {
2022                  for (var dd in mo.removedNodes) {
2023                    if (!!self && (mo.removedNodes[dd] == self.win[0])) return self.remove();
2024                  }
2025                }
2026              });
2027            });
2028            self.observerremover.observe(self.win[0].parentNode, {
2029              childList: true,
2030              characterData: false,
2031              attributes: false,
2032              subtree: false
2033            });
2034          } else {
2035            self.bind(self.win, (cap.isie && !cap.isie9) ? "propertychange" : "DOMAttrModified", self.onAttributeChange);
2036            if (cap.isie9) self.win[0].attachEvent("onpropertychange", self.onAttributeChange); //IE9 DOMAttrModified bug
2037            self.bind(self.win, "DOMNodeRemoved", function(e) {
2038              if (e.target == self.win[0]) self.remove();
2039            });
2040          }
2041        }
2042
2043        //
2044
2045        if (!self.ispage && self.opt.boxzoom) self.bind(window, "resize", self.resizeZoom);
2046				if (self.istextarea) {
2047					self.bind(self.win, "keydown", self.lazyResize);
2048					self.bind(self.win, "mouseup", self.lazyResize);
2049				}
2050
2051        //        self.checkrtlmode = true;
2052        self.lazyResize(30);
2053
2054      }
2055
2056      if (this.doc[0].nodeName == 'IFRAME') {
2057        var oniframeload = function() {
2058          self.iframexd = false;
2059          var doc;
2060          try {
2061            doc = 'contentDocument' in this ? this.contentDocument : this.contentWindow.document;
2062            var a = doc.domain;
2063          } catch (e) {
2064            self.iframexd = true;
2065            doc = false;
2066          }
2067
2068          if (self.iframexd) {
2069            if ("console" in window) console.log('NiceScroll error: policy restriced iframe');
2070            return true; //cross-domain - I can't manage this
2071          }
2072
2073          self.forcescreen = true;
2074
2075          if (self.isiframe) {
2076            self.iframe = {
2077              "doc": $(doc),
2078              "html": self.doc.contents().find('html')[0],
2079              "body": self.doc.contents().find('body')[0]
2080            };
2081            self.getContentSize = function() {
2082              return {
2083                w: Math.max(self.iframe.html.scrollWidth, self.iframe.body.scrollWidth),
2084                h: Math.max(self.iframe.html.scrollHeight, self.iframe.body.scrollHeight)
2085              };
2086            };
2087            self.docscroll = $(self.iframe.body); //$(this.contentWindow);
2088          }
2089
2090          if (!cap.isios && self.opt.iframeautoresize && !self.isiframe) {
2091            self.win.scrollTop(0); // reset position
2092            self.doc.height(""); //reset height to fix browser bug
2093            var hh = Math.max(doc.getElementsByTagName('html')[0].scrollHeight, doc.body.scrollHeight);
2094            self.doc.height(hh);
2095          }
2096          self.lazyResize(30);
2097
2098          if (cap.isie7) self.css($(self.iframe.html), _scrollyhidden);
2099          self.css($(self.iframe.body), _scrollyhidden);
2100
2101          if (cap.isios && self.haswrapper) {
2102            self.css($(doc.body), {
2103              '-webkit-transform': 'translate3d(0,0,0)'
2104            }); // avoid iFrame content clipping - thanks to http://blog.derraab.com/2012/04/02/avoid-iframe-content-clipping-with-css-transform-on-ios/
2105          }
2106
2107          if ('contentWindow' in this) {
2108            self.bind(this.contentWindow, "scroll", self.onscroll); //IE8 & minor
2109          } else {
2110            self.bind(doc, "scroll", self.onscroll);
2111          }
2112
2113          if (self.opt.enablemousewheel) {
2114            self.mousewheel(doc, self.onmousewheel);
2115          }
2116
2117          if (self.opt.enablekeyboard) self.bind(doc, (cap.isopera) ? "keypress" : "keydown", self.onkeypress);
2118
2119          if (cap.cantouch || self.opt.touchbehavior) {
2120            self.bind(doc, "mousedown", self.ontouchstart);
2121            self.bind(doc, "mousemove", function(e) {
2122              return self.ontouchmove(e, true);
2123            });
2124            if (self.opt.grabcursorenabled && cap.cursorgrabvalue) self.css($(doc.body), {
2125              'cursor': cap.cursorgrabvalue
2126            });
2127          }
2128
2129          self.bind(doc, "mouseup", self.ontouchend);
2130
2131          if (self.zoom) {
2132            if (self.opt.dblclickzoom) self.bind(doc, 'dblclick', self.doZoom);
2133            if (self.ongesturezoom) self.bind(doc, "gestureend", self.ongesturezoom);
2134          }
2135        };
2136
2137        if (this.doc[0].readyState && this.doc[0].readyState == "complete") {
2138          setTimeout(function() {
2139            oniframeload.call(self.doc[0], false);
2140          }, 500);
2141        }
2142        self.bind(this.doc, "load", oniframeload);
2143
2144      }
2145
2146    };
2147
2148    this.showCursor = function(py, px) {
2149      if (self.cursortimeout) {
2150        clearTimeout(self.cursortimeout);
2151        self.cursortimeout = 0;
2152      }
2153      if (!self.rail) return;
2154      if (self.autohidedom) {
2155        self.autohidedom.stop().css({
2156          opacity: self.opt.cursoropacitymax
2157        });
2158        self.cursoractive = true;
2159      }
2160
2161      if (!self.rail.drag || self.rail.drag.pt != 1) {
2162        if (py !== undefined && py !== false) {
2163          self.scroll.y = Math.round(py * 1 / self.scrollratio.y);
2164        }
2165        if (px !== undefined) {
2166          self.scroll.x = Math.round(px * 1 / self.scrollratio.x);
2167        }
2168      }
2169
2170      self.cursor.css({
2171        height: self.cursorheight,
2172        top: self.scroll.y
2173      });
2174      if (self.cursorh) {
2175        var lx = (self.hasreversehr) ? self.scrollvaluemaxw-self.scroll.x : self.scroll.x;
2176        (!self.rail.align && self.rail.visibility) ? self.cursorh.css({
2177          width: self.cursorwidth,
2178          left: lx + self.rail.width
2179        }): self.cursorh.css({
2180          width: self.cursorwidth,
2181          left: lx
2182        });
2183        self.cursoractive = true;
2184      }
2185
2186      if (self.zoom) self.zoom.stop().css({
2187        opacity: self.opt.cursoropacitymax
2188      });
2189    };
2190
2191    this.hideCursor = function(tm) {
2192      if (self.cursortimeout) return;
2193      if (!self.rail) return;
2194      if (!self.autohidedom) return;
2195      if (self.hasmousefocus && self.opt.autohidemode == "leave") return;
2196      self.cursortimeout = setTimeout(function() {
2197        if (!self.rail.active || !self.showonmouseevent) {
2198          self.autohidedom.stop().animate({
2199            opacity: self.opt.cursoropacitymin
2200          });
2201          if (self.zoom) self.zoom.stop().animate({
2202            opacity: self.opt.cursoropacitymin
2203          });
2204          self.cursoractive = false;
2205        }
2206        self.cursortimeout = 0;
2207      }, tm || self.opt.hidecursordelay);
2208    };
2209
2210    this.noticeCursor = function(tm, py, px) {
2211      self.showCursor(py, px);
2212      if (!self.rail.active) self.hideCursor(tm);
2213    };
2214
2215    this.getContentSize =
2216      (self.ispage) ?
2217      function() {
2218        return {
2219          w: Math.max(document.body.scrollWidth, document.documentElement.scrollWidth),
2220          h: Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)
2221        };
2222      } : (self.haswrapper) ?
2223      function() {
2224        return {
2225          w: self.doc.outerWidth() + parseInt(self.win.css('paddingLeft')) + parseInt(self.win.css('paddingRight')),
2226          h: self.doc.outerHeight() + parseInt(self.win.css('paddingTop')) + parseInt(self.win.css('paddingBottom'))
2227        };
2228      } : function() {
2229        return {
2230          w: self.docscroll[0].scrollWidth,
2231          h: self.docscroll[0].scrollHeight
2232        };
2233      };
2234
2235    this.onResize = function(e, page) {
2236
2237      if (!self || !self.win) return false;
2238
2239      if (!self.haswrapper && !self.ispage) {
2240        if (self.win.css('display') == 'none') {
2241          if (self.visibility) self.hideRail().hideRailHr();
2242          return false;
2243        } else {
2244          if (!self.hidden && !self.visibility) self.showRail().showRailHr();
2245        }
2246      }
2247
2248      var premaxh = self.page.maxh;
2249      var premaxw = self.page.maxw;
2250
2251      var preview = {
2252        h: self.view.h,
2253        w: self.view.w
2254      };
2255
2256      self.view = {
2257        w: (self.ispage) ? self.win.width() : parseInt(self.win[0].clientWidth),
2258        h: (self.ispage) ? self.win.height() : parseInt(self.win[0].clientHeight)
2259      };
2260
2261      self.page = (page) ? page : self.getContentSize();
2262
2263      self.page.maxh = Math.max(0, self.page.h - self.view.h);
2264      self.page.maxw = Math.max(0, self.page.w - self.view.w);
2265
2266      if ((self.page.maxh == premaxh) && (self.page.maxw == premaxw) && (self.view.w == preview.w) && (self.view.h == preview.h)) {
2267        // test position
2268        if (!self.ispage) {
2269          var pos = self.win.offset();
2270          if (self.lastposition) {
2271            var lst = self.lastposition;
2272            if ((lst.top == pos.top) && (lst.left == pos.left)) return self; //nothing to do
2273          }
2274          self.lastposition = pos;
2275        } else {
2276          return self; //nothing to do
2277        }
2278      }
2279
2280      if (self.page.maxh == 0) {
2281        self.hideRail();
2282        self.scrollvaluemax = 0;
2283        self.scroll.y = 0;
2284        self.scrollratio.y = 0;
2285        self.cursorheight = 0;
2286        self.setScrollTop(0);
2287        if (self.rail) self.rail.scrollable = false;
2288      } else {
2289        self.page.maxh -= (self.opt.railpadding.top + self.opt.railpadding.bottom);  //**
2290        self.rail.scrollable = true;
2291      }
2292
2293      if (self.page.maxw == 0) {
2294        self.hideRailHr();
2295        self.scrollvaluemaxw = 0;
2296        self.scroll.x = 0;
2297        self.scrollratio.x = 0;
2298        self.cursorwidth = 0;
2299        self.setScrollLeft(0);
2300        if (self.railh) {
2301          self.railh.scrollable = false;
2302        }
2303      } else {
2304          self.page.maxw -= (self.opt.railpadding.left + self.opt.railpadding.right);  //**
2305          if (self.railh) self.railh.scrollable = (self.opt.horizrailenabled);
2306      }
2307
2308      self.railslocked = (self.locked) || ((self.page.maxh == 0) && (self.page.maxw == 0));
2309      if (self.railslocked) {
2310        if (!self.ispage) self.updateScrollBar(self.view);
2311        return false;
2312      }
2313
2314      if (!self.hidden && !self.visibility) {
2315        self.showRail().showRailHr();
2316      }
2317      else if (self.railh && (!self.hidden && !self.railh.visibility)) self.showRailHr();
2318
2319      if (self.istextarea && self.win.css('resize') && self.win.css('resize') != 'none') self.view.h -= 20;
2320
2321      self.cursorheight = Math.min(self.view.h, Math.round(self.view.h * (self.view.h / self.page.h)));
2322      self.cursorheight = (self.opt.cursorfixedheight) ? self.opt.cursorfixedheight : Math.max(self.opt.cursorminheight, self.cursorheight);
2323
2324      self.cursorwidth = Math.min(self.view.w, Math.round(self.view.w * (self.view.w / self.page.w)));
2325      self.cursorwidth = (self.opt.cursorfixedheight) ? self.opt.cursorfixedheight : Math.max(self.opt.cursorminheight, self.cursorwidth);
2326
2327      self.scrollvaluemax = self.view.h - self.cursorheight - self.cursor.hborder - (self.opt.railpadding.top + self.opt.railpadding.bottom);  //**
2328
2329      if (self.railh) {
2330        self.railh.width = (self.page.maxh > 0) ? (self.view.w - self.rail.width) : self.view.w;
2331        self.scrollvaluemaxw = self.railh.width - self.cursorwidth - self.cursorh.wborder - (self.opt.railpadding.left + self.opt.railpadding.right);  //**
2332      }
2333
2334      /*
2335      if (self.checkrtlmode&&self.railh) {
2336        self.checkrtlmode = false;
2337        if (self.opt.rtlmode&&self.scroll.x==0) self.setScrollLeft(self.page.maxw);
2338      }
2339*/
2340
2341      if (!self.ispage) self.updateScrollBar(self.view);
2342
2343      self.scrollratio = {
2344        x: (self.page.maxw / self.scrollvaluemaxw),
2345        y: (self.page.maxh / self.scrollvaluemax)
2346      };
2347
2348      var sy = self.getScrollTop();
2349      if (sy > self.page.maxh) {
2350        self.doScrollTop(self.page.maxh);
2351      } else {
2352        self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y));
2353        self.scroll.x = Math.round(self.getScrollLeft() * (1 / self.scrollratio.x));
2354        if (self.cursoractive) self.noticeCursor();
2355      }
2356
2357      if (self.scroll.y && (self.getScrollTop() == 0)) self.doScrollTo(Math.floor(self.scroll.y * self.scrollratio.y));
2358
2359      return self;
2360    };
2361
2362    this.resize = self.onResize;
2363
2364		this.hlazyresize = 0;
2365
2366    this.lazyResize = function(tm) { // event debounce
2367			if (self.hlazyresize) clearTimeout(self.hlazyresize);
2368			self.hlazyresize = setTimeout(function(){
2369				self && self.show().resize();
2370			}, 1000);
2371      return self;
2372    };
2373
2374    // modified by MDN https://developer.mozilla.org/en-US/docs/DOM/Mozilla_event_reference/wheel
2375    function _modernWheelEvent(dom, name, fn, bubble) {
2376      self._bind(dom, name, function(e) {
2377        var e = (e) ? e : window.event;
2378        var event = {
2379          original: e,
2380          target: e.target || e.srcElement,
2381          type: "wheel",
2382          deltaMode: e.type == "MozMousePixelScroll" ? 0 : 1,
2383          deltaX: 0,
2384          deltaZ: 0,
2385          preventDefault: function() {
2386            e.preventDefault ? e.preventDefault() : e.returnValue = false;
2387            return false;
2388          },
2389          stopImmediatePropagation: function() {
2390            (e.stopImmediatePropagation) ? e.stopImmediatePropagation(): e.cancelBubble = true;
2391          }
2392        };
2393
2394        if (name == "mousewheel") {
2395          e.wheelDeltaX && (event.deltaX = -1 / 40 * e.wheelDeltaX);
2396					e.wheelDeltaY && (event.deltaY = -1 / 40 * e.wheelDeltaY);
2397					!event.deltaY && !event.deltaX && (event.deltaY = -1 / 40 * e.wheelDelta);
2398        } else {
2399          event.deltaY = e.detail;
2400        }
2401
2402        return fn.call(dom, event);
2403      }, bubble);
2404    }
2405
2406
2407
2408    this.jqbind = function(dom, name, fn) { // use jquery bind for non-native events (mouseenter/mouseleave)
2409      self.events.push({
2410        e: dom,
2411        n: name,
2412        f: fn,
2413        q: true
2414      });
2415      $(dom).bind(name, fn);
2416    };
2417
2418    this.mousewheel = function(dom, fn, bubble) { // bind mousewheel
2419      var el = ("jquery" in dom) ? dom[0] : dom;
2420      if ("onwheel" in document.createElement("div")) { // Modern browsers support "wheel"
2421        self._bind(el, "wheel", fn, bubble || false);
2422      } else {
2423        var wname = (document.onmousewheel !== undefined) ? "mousewheel" : "DOMMouseScroll"; // older Webkit+IE support or older Firefox
2424        _modernWheelEvent(el, wname, fn, bubble || false);
2425        if (wname == "DOMMouseScroll") _modernWheelEvent(el, "MozMousePixelScroll", fn, bubble || false); // Firefox legacy
2426      }
2427    };
2428
2429    if (cap.haseventlistener) {  // W3C standard event model
2430
2431      this.bind = function(dom, name, fn, bubble) {  // W3C
2432        var el = ("jquery" in dom) ? dom[0] : dom;
2433        self._bind(el, name, fn, bubble || false);
2434      };
2435
2436      this._bind = function(el, name, fn, bubble) { // primitive bind
2437        self.events.push({
2438          e: el,
2439          n: name,
2440          f: fn,
2441          b: bubble,
2442          q: false
2443        });
2444        el.addEventListener(name, fn, bubble || false);
2445      };
2446      this.cancelEvent = function(e) {
2447        if (!e) return false;
2448        var e = (e.original) ? e.original : e;
2449        if (e.cancelable) e.preventDefault();
2450        e.stopPropagation();
2451        if (e.preventManipulation) e.preventManipulation(); //IE10
2452        return false;
2453      };
2454      this.stopPropagation = function(e) {
2455        if (!e) return false;
2456        var e = (e.original) ? e.original : e;
2457        e.stopPropagation();
2458        return false;
2459      };
2460      this._unbind = function(el, name, fn, bub) { // primitive unbind
2461        el.removeEventListener(name, fn, bub);
2462      };
2463    } else {  // old IE model
2464
2465      this.bind = function(dom, name, fn, bubble) {  // legacy IE
2466        var el = ("jquery" in dom) ? dom[0] : dom;
2467        self._bind(el, name, function(e) {
2468          e = e || window.event || false;
2469          if (e && e.srcElement) {
2470            e.target = e.srcElement;
2471          }
2472          if (!("pageY" in e)) {
2473            e.pageX = e.clientX + document.documentElement.scrollLeft;
2474            e.pageY = e.clientY + document.documentElement.scrollTop;
2475          }
2476          return ((fn.call(el, e) === false) || bubble === false) ? self.cancelEvent(e) : true;
2477        });
2478      };
2479
2480      this._bind = function(el, name, fn, bubble) { // primitive bind
2481        self.events.push({
2482          e: el,
2483          n: name,
2484          f: fn,
2485          b: bubble,
2486          q: false
2487        });
2488        if (el.attachEvent) {
2489          el.attachEvent("on" + name, fn);
2490        } else {
2491          el["on" + name] = fn;
2492        }
2493      };
2494      // Thanks to http://www.switchonthecode.com !!
2495      this.cancelEvent = function(e) {
2496        var e = window.event || false;
2497        if (!e) return false;
vendor: 4,718 bytes, lines 2498-2662
2498        e.cancelBubble = true;
2499        e.cancel = true;
2500        e.returnValue = false;
2501        return false;
2502      };
2503      this.stopPropagation = function(e) {
2504        var e = window.event || false;
2505        if (!e) return false;
2506        e.cancelBubble = true;
2507        return false;
2508      };
2509      this._unbind = function(el, name, fn, bub) { // primitive unbind IE old
2510        if (el.detachEvent) {
2511          el.detachEvent('on' + name, fn);
2512        } else {
2513          el['on' + name] = false;
2514        }
2515      };
2516    }
2517
2518    this.unbindAll = function() {
2519      for (var a = 0; a < self.events.length; a++) {
2520        var r = self.events[a];
2521        (r.q) ? r.e.unbind(r.n, r.f): self._unbind(r.e, r.n, r.f, r.b);
2522      }
2523    };
2524
2525    this.showRail = function() {
2526      if ((self.page.maxh != 0) && (self.ispage || self.win.css('display') != 'none')) {
2527        self.visibility = true;
2528        self.rail.visibility = true;
2529        self.rail.css('display', 'block');
2530      }
2531      return self;
2532    };
2533
2534    this.showRailHr = function() {
2535      if (!self.railh) return self;
2536      if ((self.page.maxw != 0) && (self.ispage || self.win.css('display') != 'none')) {
2537        self.railh.visibility = true;
2538        self.railh.css('display', 'block');
2539      }
2540      return self;
2541    };
2542
2543    this.hideRail = function() {
2544      self.visibility = false;
2545      self.rail.visibility = false;
2546      self.rail.css('display', 'none');
2547      return self;
2548    };
2549
2550    this.hideRailHr = function() {
2551      if (!self.railh) return self;
2552      self.railh.visibility = false;
2553      self.railh.css('display', 'none');
2554      return self;
2555    };
2556
2557    this.show = function() {
2558      self.hidden = false;
2559      self.railslocked = false;
2560      return self.showRail().showRailHr();
2561    };
2562
2563    this.hide = function() {
2564      self.hidden = true;
2565      self.railslocked = true;
2566      return self.hideRail().hideRailHr();
2567    };
2568
2569    this.toggle = function() {
2570      return (self.hidden) ? self.show() : self.hide();
2571    };
2572
2573    this.remove = function() {
2574      self.stop();
2575      if (self.cursortimeout) clearTimeout(self.cursortimeout);
2576//      if (self.debouncedelayed) clearTimeout(self.debouncedelayed);
2577			for(var n in self.delaylist) if (self.delaylist[n]) clearAnimationFrame(self.delaylist[n].h);
2578      self.doZoomOut();
2579      self.unbindAll();
2580
2581      if (cap.isie9) self.win[0].detachEvent("onpropertychange", self.onAttributeChange); //IE9 DOMAttrModified bug
2582
2583      if (self.observer !== false) self.observer.disconnect();
2584      if (self.observerremover !== false) self.observerremover.disconnect();
2585      if (self.observerbody !== false) self.observerbody.disconnect();
2586
2587      self.events = null;
2588
2589      if (self.cursor) {
2590        self.cursor.remove();
2591      }
2592      if (self.cursorh) {
2593        self.cursorh.remove();
2594      }
2595      if (self.rail) {
2596        self.rail.remove();
2597      }
2598      if (self.railh) {
2599        self.railh.remove();
2600      }
2601      if (self.zoom) {
2602        self.zoom.remove();
2603      }
2604      for (var a = 0; a < self.saved.css.length; a++) {
2605        var d = self.saved.css[a];
2606        d[0].css(d[1], (d[2] === undefined) ? '' : d[2]);
2607      }
2608      self.saved = false;
2609      self.me.data('__nicescroll', ''); //erase all traces
2610
2611      // memory leak fixed by GianlucaGuarini - thanks a lot!
2612      // remove the current nicescroll from the $.nicescroll array & normalize array
2613      var lst = $.nicescroll;
2614      lst.each(function(i) {
2615        if (!this) return;
2616        if (this.id === self.id) {
2617          delete lst[i];
2618          for (var b = ++i; b < lst.length; b++, i++) lst[i] = lst[b];
2619          lst.length--;
2620          if (lst.length) delete lst[lst.length];
2621        }
2622      });
2623
2624      for (var i in self) {
2625        self[i] = null;
2626        delete self[i];
2627      }
2628
2629      self = null;
2630
2631    };
2632
2633    this.scrollstart = function(fn) {
2634      this.onscrollstart = fn;
2635      return self;
2636    };
2637    this.scrollend = function(fn) {
2638      this.onscrollend = fn;
2639      return self;
2640    };
2641    this.scrollcancel = function(fn) {
2642      this.onscrollcancel = fn;
2643      return self;
2644    };
2645
2646    this.zoomin = function(fn) {
2647      this.onzoomin = fn;
2648      return self;
2649    };
2650    this.zoomout = function(fn) {
2651      this.onzoomout = fn;
2652      return self;
2653    };
2654
2655    this.isScrollable = function(e) {
2656      var dom = (e.target) ? e.target : e;
2657      if (dom.nodeName == 'OPTION') return true;
2658      while (dom && (dom.nodeType == 1) && !(/^BODY|HTML/.test(dom.nodeName))) {
2659        var dd = $(dom);
2660        var ov = dd.css('overflowY') || dd.css('overflowX') || dd.css('overflow') || '';
2661        if (/scroll|auto/.test(ov)) return (dom.clientHeight != dom.scrollHeight);
2662        dom = (dom.parentNode) ? dom.parentNode : false;
2663      }
2664      return false;
2665    };
2666
2667    this.getViewport = function(me) {
2668      var dom = (me && me.parentNode) ? me.parentNode : false;
2669      while (dom && (dom.nodeType == 1) && !(/^BODY|HTML/.test(dom.nodeName))) {
2670        var dd = $(dom);
2671        if (/fixed|absolute/.test(dd.css("position"))) return dd;
2672        var ov = dd.css('overflowY') || dd.css('overflowX') || dd.css('overflow') || '';
2673        if ((/scroll|auto/.test(ov)) && (dom.clientHeight != dom.scrollHeight)) return dd;
2674        if (dd.getNiceScroll().length > 0) return dd;
2675        dom = (dom.parentNode) ? dom.parentNode : false;
2676      }
2677      return false; //(dom) ? $(dom) : false;
2678    };
2679
2680    this.triggerScrollEnd = function() {
2681      if (!self.onscrollend) return;
2682
2683      var px = self.getScrollLeft();
2684      var py = self.getScrollTop();
2685
2686      var info = {
2687        type: "scrollend",
2688        current: {
2689          x: px,
2690          y: py
2691        },
2692        end: {
2693          x: px,
2694          y: py
2695        }
2696      };
2697      self.onscrollend.call(self, info);
2698    };
2699
2700    function execScrollWheel(e, hr, chkscroll) {
2701      var px, py;
2702
2703      if (e.deltaMode == 0) { // PIXEL
2704        px = -Math.floor(e.deltaX * (self.opt.mousescrollstep / (18 * 3)));
2705        py = -Math.floor(e.deltaY * (self.opt.mousescrollstep / (18 * 3)));
2706      } else if (e.deltaMode == 1) { // LINE
2707        px = -Math.floor(e.deltaX * self.opt.mousescrollstep);
2708        py = -Math.floor(e.deltaY * self.opt.mousescrollstep);
2709      }
2710
2711      if (hr && self.opt.oneaxismousemode && (px == 0) && py) { // classic vertical-only mousewheel + browser with x/y support
2712        px = py;
2713        py = 0;
2714
2715        if (chkscroll) {
2716          var hrend = (px < 0) ? (self.getScrollLeft() >= self.page.maxw) : (self.getScrollLeft() <= 0);
2717          if (hrend) {  // preserve vertical scrolling
2718            py = px;
2719            px = 0;
2720          }
2721        }
2722
2723      }
2724
2725      // invert horizontal direction for rtl mode
2726      if (self.isrtlmode) px = -px;
2727
2728      if (px) {
2729        if (self.scrollmom) {
2730          self.scrollmom.stop();
2731        }
2732        self.lastdeltax += px;
2733        self.debounced("mousewheelx", function() {
2734          var dt = self.lastdeltax;
2735          self.lastdeltax = 0;
2736          if (!self.rail.drag) {
2737            self.doScrollLeftBy(dt);
2738          }
2739        }, 15);
2740      }
2741      if (py) {
2742        if (self.opt.nativeparentscrolling && chkscroll && !self.ispage && !self.zoomactive) {
2743          if (py < 0) {
2744            if (self.getScrollTop() >= self.page.maxh) return true;
2745          } else {
2746            if (self.getScrollTop() <= 0) return true;
2747          }
2748        }
2749        if (self.scrollmom) {
2750          self.scrollmom.stop();
2751        }
2752        self.lastdeltay += py;
2753//        self.debounced("mousewheely", function() {
2754	      self.synched("mousewheely", function() {
2755          var dt = self.lastdeltay;
2756          self.lastdeltay = 0;
2757          if (!self.rail.drag) {
2758            self.doScrollBy(dt);
2759          }
2760        }, 15);
2761      }
2762
2763      e.stopImmediatePropagation();
2764      //return e.preventDefault();
2765    }
2766
2767    this.onmousewheel = function(e) {
2768      if (self.wheelprevented) return;
2769      if (self.railslocked) {
2770        self.debounced("checkunlock", self.resize, 250);
2771        return true;
2772      }
2773      if (self.rail.drag) return self.cancelEvent(e);
2774
2775      if (self.opt.oneaxismousemode == "auto" && e.deltaX != 0) self.opt.oneaxismousemode = false; // check two-axis mouse support (not very elegant)
2776
2777      if (self.opt.oneaxismousemode && e.deltaX == 0) {
2778        if (!self.rail.scrollable) {
2779          if (self.railh && self.railh.scrollable) {
2780            return self.onmousewheelhr(e);
2781          } else {
2782            return true;
2783          }
2784        }
2785      }
2786
2787      var nw = +(new Date());
2788      var chk = false;
2789      if (self.opt.preservenativescrolling && ((self.checkarea + 600) < nw)) {
2790        self.nativescrollingarea = self.isScrollable(e);
2791        chk = true;
2792      }
2793      self.checkarea = nw;
2794      if (self.nativescrollingarea) return true; // this isn't my business
2795      var ret = execScrollWheel(e, false, chk);
2796      if (ret) self.checkarea = 0;
2797      return ret;
2798    };
2799
2800    this.onmousewheelhr = function(e) {
2801      if (self.wheelprevented) return;
2802      if (self.railslocked || !self.railh.scrollable) return true;
2803      if (self.rail.drag) return self.cancelEvent(e);
2804
2805      var nw = +(new Date());
2806      var chk = false;
2807      if (self.opt.preservenativescrolling && ((self.checkarea + 600) < nw)) {
2808        self.nativescrollingarea = self.isScrollable(e);
2809        chk = true;
2810      }
2811      self.checkarea = nw;
2812      if (self.nativescrollingarea) return true; // this isn't my business
2813      if (self.railslocked) return self.cancelEvent(e);
2814
2815      return execScrollWheel(e, true, chk);
2816    };
2817
2818    this.stop = function() {
2819      self.cancelScroll();
2820      if (self.scrollmon) self.scrollmon.stop();
2821      self.cursorfreezed = false;
2822      self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y));
2823      self.noticeCursor();
2824      return self;
2825    };
2826
2827    this.getTransitionSpeed = function(dif) {
2828      var sp = Math.round(self.opt.scrollspeed * 10);
2829      var ex = Math.min(sp, Math.round((dif / 20) * self.opt.scrollspeed));
2830      return (ex > 20) ? ex : 0;
2831    };
2832
2833    if (!self.opt.smoothscroll) {
2834      this.doScrollLeft = function(x, spd) { //direct
2835        var y = self.getScrollTop();
2836        self.doScrollPos(x, y, spd);
2837      };
2838      this.doScrollTop = function(y, spd) { //direct
2839        var x = self.getScrollLeft();
2840        self.doScrollPos(x, y, spd);
2841      };
2842      this.doScrollPos = function(x, y, spd) { //direct
2843        var nx = (x > self.page.maxw) ? self.page.maxw : x;
2844        if (nx < 0) nx = 0;
2845        var ny = (y > self.page.maxh) ? self.page.maxh : y;
2846        if (ny < 0) ny = 0;
2847        self.synched('scroll', function() {
2848          self.setScrollTop(ny);
2849          self.setScrollLeft(nx);
2850        });
2851      };
2852      this.cancelScroll = function() {}; // direct
2853    } else if (self.ishwscroll && cap.hastransition && self.opt.usetransition && !!self.opt.smoothscroll) {
2854      this.prepareTransition = function(dif, istime) {
2855        var ex = (istime) ? ((dif > 20) ? dif : 0) : self.getTransitionSpeed(dif);
2856        var trans = (ex) ? cap.prefixstyle + 'transform ' + ex + 'ms ease-out' : '';
2857        if (!self.lasttransitionstyle || self.lasttransitionstyle != trans) {
2858          self.lasttransitionstyle = trans;
2859          self.doc.css(cap.transitionstyle, trans);
2860        }
2861        return ex;
2862      };
2863
2864      this.doScrollLeft = function(x, spd) { //trans
2865        var y = (self.scrollrunning) ? self.newscrolly : self.getScrollTop();
2866        self.doScrollPos(x, y, spd);
2867      };
2868
2869      this.doScrollTop = function(y, spd) { //trans
2870        var x = (self.scrollrunning) ? self.newscrollx : self.getScrollLeft();
2871        self.doScrollPos(x, y, spd);
2872      };
2873
2874      this.doScrollPos = function(x, y, spd) { //trans
2875
2876        var py = self.getScrollTop();
2877        var px = self.getScrollLeft();
2878
2879        if (((self.newscrolly - py) * (y - py) < 0) || ((self.newscrollx - px) * (x - px) < 0)) self.cancelScroll(); //inverted movement detection
2880
2881        if (self.opt.bouncescroll == false) {
2882          if (y < 0) y = 0;
2883          else if (y > self.page.maxh) y = self.page.maxh;
2884          if (x < 0) x = 0;
2885          else if (x > self.page.maxw) x = self.page.maxw;
2886        }
2887
2888        if (self.scrollrunning && x == self.newscrollx && y == self.newscrolly) return false;
2889
2890        self.newscrolly = y;
2891        self.newscrollx = x;
2892
2893        self.newscrollspeed = spd || false;
2894
2895        if (self.timer) return false;
2896
2897        self.timer = setTimeout(function() {
2898
2899          var top = self.getScrollTop();
2900          var lft = self.getScrollLeft();
2901
2902          var dst = {};
2903          dst.x = x - lft;
2904          dst.y = y - top;
2905          dst.px = lft;
2906          dst.py = top;
2907
2908          var dd = Math.round(Math.sqrt(Math.pow(dst.x, 2) + Math.pow(dst.y, 2)));
2909          var ms = (self.newscrollspeed && self.newscrollspeed > 1) ? self.newscrollspeed : self.getTransitionSpeed(dd);
2910          if (self.newscrollspeed && self.newscrollspeed <= 1) ms *= self.newscrollspeed;
2911
2912          self.prepareTransition(ms, true);
2913
2914          if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm);
2915
2916          if (ms > 0) {
2917
2918            if (!self.scrollrunning && self.onscrollstart) {
2919              var info = {
2920                "type": "scrollstart",
2921                "current": {
2922                  "x": lft,
2923                  "y": top
2924                },
2925                "request": {
2926                  "x": x,
2927                  "y": y
2928                },
2929                "end": {
2930                  "x": self.newscrollx,
2931                  "y": self.newscrolly
2932                },
2933                "speed": ms
2934              };
2935              self.onscrollstart.call(self, info);
2936            }
2937
2938            if (cap.transitionend) {
2939              if (!self.scrollendtrapped) {
2940                self.scrollendtrapped = true;
2941                self.bind(self.doc, cap.transitionend, self.onScrollTransitionEnd, false); //I have got to do something usefull!!
2942              }
2943            } else {
2944              if (self.scrollendtrapped) clearTimeout(self.scrollendtrapped);
2945              self.scrollendtrapped = setTimeout(self.onScrollTransitionEnd, ms); // simulate transitionend event
2946            }
2947
2948            var py = top;
2949            var px = lft;
2950            self.timerscroll = {
2951              bz: new BezierClass(py, self.newscrolly, ms, 0, 0, 0.58, 1),
2952              bh: new BezierClass(px, self.newscrollx, ms, 0, 0, 0.58, 1)
2953            };
2954            if (!self.cursorfreezed) self.timerscroll.tm = setInterval(function() {
2955              self.showCursor(self.getScrollTop(), self.getScrollLeft());
2956            }, 60);
2957
2958          }
2959
2960          self.synched("doScroll-set", function() {
2961            self.timer = 0;
2962            if (self.scrollendtrapped) self.scrollrunning = true;
2963            self.setScrollTop(self.newscrolly);
2964            self.setScrollLeft(self.newscrollx);
2965            if (!self.scrollendtrapped) self.onScrollTransitionEnd();
2966          });
2967
2968
2969        }, 50);
2970
2971      };
2972
2973      this.cancelScroll = function() {
2974        if (!self.scrollendtrapped) return true;
2975        var py = self.getScrollTop();
2976        var px = self.getScrollLeft();
2977        self.scrollrunning = false;
2978        if (!cap.transitionend) clearTimeout(cap.transitionend);
2979        self.scrollendtrapped = false;
2980        self._unbind(self.doc[0], cap.transitionend, self.onScrollTransitionEnd);
2981        self.prepareTransition(0);
2982        self.setScrollTop(py); // fire event onscroll
2983        if (self.railh) self.setScrollLeft(px);
2984        if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm);
2985        self.timerscroll = false;
2986
2987        self.cursorfreezed = false;
2988
2989        self.showCursor(py, px);
2990        return self;
2991      };
2992      this.onScrollTransitionEnd = function() {
2993        if (self.scrollendtrapped) self._unbind(self.doc[0], cap.transitionend, self.onScrollTransitionEnd);
2994        self.scrollendtrapped = false;
2995        self.prepareTransition(0);
2996        if (self.timerscroll && self.timerscroll.tm) clearInterval(self.timerscroll.tm);
2997        self.timerscroll = false;
2998        var py = self.getScrollTop();
2999        var px = self.getScrollLeft();
3000        self.setScrollTop(py); // fire event onscroll
3001        if (self.railh) self.setScrollLeft(px); // fire event onscroll left
3002
3003        self.noticeCursor(false, py, px);
3004
3005        self.cursorfreezed = false;
3006
3007        if (py < 0) py = 0;
3008        else if (py > self.page.maxh) py = self.page.maxh;
3009        if (px < 0) px = 0;
3010        else if (px > self.page.maxw) px = self.page.maxw;
3011        if ((py != self.newscrolly) || (px != self.newscrollx)) return self.doScrollPos(px, py, self.opt.snapbackspeed);
3012
3013        if (self.onscrollend && self.scrollrunning) {
3014          self.triggerScrollEnd();
3015        }
3016        self.scrollrunning = false;
3017
3018      };
3019
3020    } else {
3021
3022      this.doScrollLeft = function(x, spd) { //no-trans
3023        var y = (self.scrollrunning) ? self.newscrolly : self.getScrollTop();
3024        self.doScrollPos(x, y, spd);
3025      };
3026
3027      this.doScrollTop = function(y, spd) { //no-trans
3028        var x = (self.scrollrunning) ? self.newscrollx : self.getScrollLeft();
3029        self.doScrollPos(x, y, spd);
3030      };
3031
3032      this.doScrollPos = function(x, y, spd) { //no-trans
3033        var y = (y === undefined || y === false) ? self.getScrollTop(true) : y;
3034
3035        if ((self.timer) && (self.newscrolly == y) && (self.newscrollx == x)) return true;
3036
3037        if (self.timer) clearAnimationFrame(self.timer);
3038        self.timer = 0;
3039
3040        var py = self.getScrollTop();
3041        var px = self.getScrollLeft();
3042
3043        if (((self.newscrolly - py) * (y - py) < 0) || ((self.newscrollx - px) * (x - px) < 0)) self.cancelScroll(); //inverted movement detection
3044
3045        self.newscrolly = y;
3046        self.newscrollx = x;
3047
3048        if (!self.bouncescroll || !self.rail.visibility) {
3049          if (self.newscrolly < 0) {
3050            self.newscrolly = 0;
3051          } else if (self.newscrolly > self.page.maxh) {
3052            self.newscrolly = self.page.maxh;
3053          }
3054        }
3055        if (!self.bouncescroll || !self.railh.visibility) {
3056          if (self.newscrollx < 0) {
3057            self.newscrollx = 0;
3058          } else if (self.newscrollx > self.page.maxw) {
3059            self.newscrollx = self.page.maxw;
3060          }
3061        }
3062
3063        self.dst = {};
3064        self.dst.x = x - px;
3065        self.dst.y = y - py;
3066        self.dst.px = px;
3067        self.dst.py = py;
3068
3069        var dst = Math.round(Math.sqrt(Math.pow(self.dst.x, 2) + Math.pow(self.dst.y, 2)));
3070
3071        self.dst.ax = self.dst.x / dst;
3072        self.dst.ay = self.dst.y / dst;
3073
3074        var pa = 0;
3075        var pe = dst;
3076
3077        if (self.dst.x == 0) {
3078          pa = py;
3079          pe = y;
3080          self.dst.ay = 1;
3081          self.dst.py = 0;
3082        } else if (self.dst.y == 0) {
3083          pa = px;
3084          pe = x;
3085          self.dst.ax = 1;
3086          self.dst.px = 0;
3087        }
3088
3089        var ms = self.getTransitionSpeed(dst);
3090        if (spd && spd <= 1) ms *= spd;
3091        if (ms > 0) {
3092          self.bzscroll = (self.bzscroll) ? self.bzscroll.update(pe, ms) : new BezierClass(pa, pe, ms, 0, 1, 0, 1);
3093        } else {
3094          self.bzscroll = false;
3095        }
3096
3097        if (self.timer) return;
3098
3099        if ((py == self.page.maxh && y >= self.page.maxh) || (px == self.page.maxw && x >= self.page.maxw)) self.checkContentSize();
3100
3101        var sync = 1;
3102
3103        function scrolling() {
3104          if (self.cancelAnimationFrame) return true;
3105
3106          self.scrollrunning = true;
3107
3108          sync = 1 - sync;
3109          if (sync) return (self.timer = setAnimationFrame(scrolling) || 1);
3110
3111          var done = 0;
3112          var sx, sy;
3113
3114          var sc = sy = self.getScrollTop();
3115          if (self.dst.ay) {
3116            sc = (self.bzscroll) ? self.dst.py + (self.bzscroll.getNow() * self.dst.ay) : self.newscrolly;
3117            var dr = sc - sy;
3118            if ((dr < 0 && sc < self.newscrolly) || (dr > 0 && sc > self.newscrolly)) sc = self.newscrolly;
3119            self.setScrollTop(sc);
3120            if (sc == self.newscrolly) done = 1;
3121          } else {
3122            done = 1;
3123          }
3124
3125          var scx = sx = self.getScrollLeft();
3126          if (self.dst.ax) {
3127            scx = (self.bzscroll) ? self.dst.px + (self.bzscroll.getNow() * self.dst.ax) : self.newscrollx;
3128            var dr = scx - sx;
3129            if ((dr < 0 && scx < self.newscrollx) || (dr > 0 && scx > self.newscrollx)) scx = self.newscrollx;
3130            self.setScrollLeft(scx);
3131            if (scx == self.newscrollx) done += 1;
3132          } else {
3133            done += 1;
3134          }
3135
3136          if (done == 2) {
3137            self.timer = 0;
3138            self.cursorfreezed = false;
3139            self.bzscroll = false;
3140            self.scrollrunning = false;
3141            if (sc < 0) sc = 0;
3142            else if (sc > self.page.maxh) sc = Math.max(0,self.page.maxh);
3143            if (scx < 0) scx = 0;
3144            else if (scx > self.page.maxw) scx = self.page.maxw;
3145            if ((scx != self.newscrollx) || (sc != self.newscrolly)) self.doScrollPos(scx, sc);
3146            else {
3147              if (self.onscrollend) {
3148                self.triggerScrollEnd();
3149              }
3150            }
3151          } else {
3152            self.timer = setAnimationFrame(scrolling) || 1;
3153          }
3154        }
3155        self.cancelAnimationFrame = false;
3156        self.timer = 1;
3157
3158        if (self.onscrollstart && !self.scrollrunning) {
3159          var info = {
3160            "type": "scrollstart",
3161            "current": {
3162              "x": px,
3163              "y": py
3164            },
3165            "request": {
3166              "x": x,
3167              "y": y
3168            },
3169            "end": {
3170              "x": self.newscrollx,
3171              "y": self.newscrolly
3172            },
3173            "speed": ms
3174          };
3175          self.onscrollstart.call(self, info);
3176        }
3177
3178        scrolling();
3179
3180        if ((py == self.page.maxh && y >= py) || (px == self.page.maxw && x >= px)) self.checkContentSize();
3181
3182        self.noticeCursor();
3183      };
3184
3185      this.cancelScroll = function() {
3186        if (self.timer) clearAnimationFrame(self.timer);
3187        self.timer = 0;
3188        self.bzscroll = false;
3189        self.scrollrunning = false;
3190        return self;
3191      };
3192
3193    }
3194
3195    this.doScrollBy = function(stp, relative) {
3196      var ny = 0;
3197      if (relative) {
3198        ny = Math.floor((self.scroll.y - stp) * self.scrollratio.y);
3199      } else {
3200        var sy = (self.timer) ? self.newscrolly : self.getScrollTop(true);
3201        ny = sy - stp;
3202      }
3203      if (self.bouncescroll) {
3204        var haf = Math.round(self.view.h / 2);
3205        if (ny < -haf) ny = -haf;
3206        else if (ny > (self.page.maxh + haf)) ny = (self.page.maxh + haf);
3207      }
3208      self.cursorfreezed = false;
3209
3210      var py = self.getScrollTop(true);
3211      if (ny < 0 && py <= 0) return self.noticeCursor();
3212      else if (ny > self.page.maxh && py >= self.page.maxh) {
3213        self.checkContentSize();
3214        return self.noticeCursor();
3215      }
3216
3217      self.doScrollTop(ny);
3218    };
3219
3220    this.doScrollLeftBy = function(stp, relative) {
3221      var nx = 0;
3222      if (relative) {
3223        nx = Math.floor((self.scroll.x - stp) * self.scrollratio.x);
3224      } else {
3225        var sx = (self.timer) ? self.newscrollx : self.getScrollLeft(true);
3226        nx = sx - stp;
3227      }
3228      if (self.bouncescroll) {
3229        var haf = Math.round(self.view.w / 2);
3230        if (nx < -haf) nx = -haf;
3231        else if (nx > (self.page.maxw + haf)) nx = (self.page.maxw + haf);
3232      }
3233      self.cursorfreezed = false;
3234
3235      var px = self.getScrollLeft(true);
3236      if (nx < 0 && px <= 0) return self.noticeCursor();
3237      else if (nx > self.page.maxw && px >= self.page.maxw) return self.noticeCursor();
3238
3239      self.doScrollLeft(nx);
3240    };
3241
3242    this.doScrollTo = function(pos, relative) {
3243      var ny = (relative) ? Math.round(pos * self.scrollratio.y) : pos;
3244      if (ny < 0) ny = 0;
3245      else if (ny > self.page.maxh) ny = self.page.maxh;
3246      self.cursorfreezed = false;
3247      self.doScrollTop(pos);
3248    };
3249
3250    this.checkContentSize = function() {
3251      var pg = self.getContentSize();
3252      if ((pg.h != self.page.h) || (pg.w != self.page.w)) self.resize(false, pg);
3253    };
3254
3255    self.onscroll = function(e) {
3256      if (self.rail.drag) return;
3257      if (!self.cursorfreezed) {
3258        self.synched('scroll', function() {
3259          self.scroll.y = Math.round(self.getScrollTop() * (1 / self.scrollratio.y));
3260          if (self.railh) self.scroll.x = Math.round(self.getScrollLeft() * (1 / self.scrollratio.x));
3261          self.noticeCursor();
3262        });
3263      }
3264    };
3265    self.bind(self.docscroll, "scroll", self.onscroll);
3266
3267    this.doZoomIn = function(e) {
3268      if (self.zoomactive) return;
3269      self.zoomactive = true;
3270
3271      self.zoomrestore = {
3272        style: {}
3273      };
3274      var lst = ['position', 'top', 'left', 'zIndex', 'backgroundColor', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight'];
3275      var win = self.win[0].style;
3276      for (var a in lst) {
3277        var pp = lst[a];
3278        self.zoomrestore.style[pp] = (win[pp] !== undefined) ? win[pp] : '';
3279      }
3280
3281      self.zoomrestore.style.width = self.win.css('width');
3282      self.zoomrestore.style.height = self.win.css('height');
3283
3284      self.zoomrestore.padding = {
3285        w: self.win.outerWidth() - self.win.width(),
3286        h: self.win.outerHeight() - self.win.height()
3287      };
3288
3289      if (cap.isios4) {
3290        self.zoomrestore.scrollTop = $(window).scrollTop();
3291        $(window).scrollTop(0);
3292      }
3293
3294      self.win.css({
3295        position: (cap.isios4) ? "absolute" : "fixed",
3296        top: 0,
3297        left: 0,
3298        zIndex: globalmaxzindex + 100,
3299        margin: 0
3300      });
3301      var bkg = self.win.css("backgroundColor");
vendor: 10,279 bytes, lines 3302-3688
3302      if (bkg == "" || /transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(bkg)) self.win.css("backgroundColor", "#fff");
3303      self.rail.css({
3304        zIndex: globalmaxzindex + 101
3305      });
3306      self.zoom.css({
3307        zIndex: globalmaxzindex + 102
3308      });
3309      self.zoom.css('backgroundPosition', '0px -18px');
3310      self.resizeZoom();
3311
3312      if (self.onzoomin) self.onzoomin.call(self);
3313
3314      return self.cancelEvent(e);
3315    };
3316
3317    this.doZoomOut = function(e) {
3318      if (!self.zoomactive) return;
3319      self.zoomactive = false;
3320
3321      self.win.css("margin", "");
3322      self.win.css(self.zoomrestore.style);
3323
3324      if (cap.isios4) {
3325        $(window).scrollTop(self.zoomrestore.scrollTop);
3326      }
3327
3328      self.rail.css({
3329        "z-index": self.zindex
3330      });
3331      self.zoom.css({
3332        "z-index": self.zindex
3333      });
3334      self.zoomrestore = false;
3335      self.zoom.css('backgroundPosition', '0px 0px');
3336      self.onResize();
3337
3338      if (self.onzoomout) self.onzoomout.call(self);
3339
3340      return self.cancelEvent(e);
3341    };
3342
3343    this.doZoom = function(e) {
3344      return (self.zoomactive) ? self.doZoomOut(e) : self.doZoomIn(e);
3345    };
3346
3347    this.resizeZoom = function() {
3348      if (!self.zoomactive) return;
3349
3350      var py = self.getScrollTop(); //preserve scrolling position
3351      self.win.css({
3352        width: $(window).width() - self.zoomrestore.padding.w + "px",
3353        height: $(window).height() - self.zoomrestore.padding.h + "px"
3354      });
3355      self.onResize();
3356
3357      self.setScrollTop(Math.min(self.page.maxh, py));
3358    };
3359
3360    this.init();
3361
3362    $.nicescroll.push(this);
3363
3364  };
3365
3366  // Inspired by the work of Kin Blas
3367  // http://webpro.host.adobe.com/people/jblas/momentum/includes/jquery.momentum.0.7.js
3368
3369
3370  var ScrollMomentumClass2D = function(nc) {
3371    var self = this;
3372    this.nc = nc;
3373
3374    this.lastx = 0;
3375    this.lasty = 0;
3376    this.speedx = 0;
3377    this.speedy = 0;
3378    this.lasttime = 0;
3379    this.steptime = 0;
3380    this.snapx = false;
3381    this.snapy = false;
3382    this.demulx = 0;
3383    this.demuly = 0;
3384
3385    this.lastscrollx = -1;
3386    this.lastscrolly = -1;
3387
3388    this.chkx = 0;
3389    this.chky = 0;
3390
3391    this.timer = 0;
3392
3393    this.time = function() {
3394      return +new Date(); //beautifull hack
3395    };
3396
3397    this.reset = function(px, py) {
3398      self.stop();
3399      var now = self.time();
3400      self.steptime = 0;
3401      self.lasttime = now;
3402      self.speedx = 0;
3403      self.speedy = 0;
3404      self.lastx = px;
3405      self.lasty = py;
3406      self.lastscrollx = -1;
3407      self.lastscrolly = -1;
3408    };
3409
3410    this.update = function(px, py) {
3411      var now = self.time();
3412      self.steptime = now - self.lasttime;
3413      self.lasttime = now;
3414      var dy = py - self.lasty;
3415      var dx = px - self.lastx;
3416      var sy = self.nc.getScrollTop();
3417      var sx = self.nc.getScrollLeft();
3418      var newy = sy + dy;
3419      var newx = sx + dx;
3420      self.snapx = (newx < 0) || (newx > self.nc.page.maxw);
3421      self.snapy = (newy < 0) || (newy > self.nc.page.maxh);
3422      self.speedx = dx;
3423      self.speedy = dy;
3424      self.lastx = px;
3425      self.lasty = py;
3426    };
3427
3428    this.stop = function() {
3429      self.nc.unsynched("domomentum2d");
3430      if (self.timer) clearTimeout(self.timer);
3431      self.timer = 0;
3432      self.lastscrollx = -1;
3433      self.lastscrolly = -1;
3434    };
3435
3436    this.doSnapy = function(nx, ny) {
3437      var snap = false;
3438
3439      if (ny < 0) {
3440        ny = 0;
3441        snap = true;
3442      } else if (ny > self.nc.page.maxh) {
3443        ny = self.nc.page.maxh;
3444        snap = true;
3445      }
3446
3447      if (nx < 0) {
3448        nx = 0;
3449        snap = true;
3450      } else if (nx > self.nc.page.maxw) {
3451        nx = self.nc.page.maxw;
3452        snap = true;
3453      }
3454
3455      (snap) ? self.nc.doScrollPos(nx, ny, self.nc.opt.snapbackspeed): self.nc.triggerScrollEnd();
3456    };
3457
3458    this.doMomentum = function(gp) {
3459      var t = self.time();
3460      var l = (gp) ? t + gp : self.lasttime;
3461
3462      var sl = self.nc.getScrollLeft();
3463      var st = self.nc.getScrollTop();
3464
3465      var pageh = self.nc.page.maxh;
3466      var pagew = self.nc.page.maxw;
3467
3468      self.speedx = (pagew > 0) ? Math.min(60, self.speedx) : 0;
3469      self.speedy = (pageh > 0) ? Math.min(60, self.speedy) : 0;
3470
3471      var chk = l && (t - l) <= 60;
3472
3473      if ((st < 0) || (st > pageh) || (sl < 0) || (sl > pagew)) chk = false;
3474
3475      var sy = (self.speedy && chk) ? self.speedy : false;
3476      var sx = (self.speedx && chk) ? self.speedx : false;
3477
3478      if (sy || sx) {
3479        var tm = Math.max(16, self.steptime); //timeout granularity
3480
3481        if (tm > 50) { // do smooth
3482          var xm = tm / 50;
3483          self.speedx *= xm;
3484          self.speedy *= xm;
3485          tm = 50;
3486        }
3487
3488        self.demulxy = 0;
3489
3490        self.lastscrollx = self.nc.getScrollLeft();
3491        self.chkx = self.lastscrollx;
3492        self.lastscrolly = self.nc.getScrollTop();
3493        self.chky = self.lastscrolly;
3494
3495        var nx = self.lastscrollx;
3496        var ny = self.lastscrolly;
3497
3498        var onscroll = function() {
3499          var df = ((self.time() - t) > 600) ? 0.04 : 0.02;
3500
3501          if (self.speedx) {
3502            nx = Math.floor(self.lastscrollx - (self.speedx * (1 - self.demulxy)));
3503            self.lastscrollx = nx;
3504            if ((nx < 0) || (nx > pagew)) df = 0.10;
3505          }
3506
3507          if (self.speedy) {
3508            ny = Math.floor(self.lastscrolly - (self.speedy * (1 - self.demulxy)));
3509            self.lastscrolly = ny;
3510            if ((ny < 0) || (ny > pageh)) df = 0.10;
3511          }
3512
3513          self.demulxy = Math.min(1, self.demulxy + df);
3514
3515          self.nc.synched("domomentum2d", function() {
3516
3517            if (self.speedx) {
3518              var scx = self.nc.getScrollLeft();
3519//              if (scx != self.chkx) self.stop();
3520              self.chkx = nx;
3521              self.nc.setScrollLeft(nx);
3522            }
3523
3524            if (self.speedy) {
3525              var scy = self.nc.getScrollTop();
3526//              if (scy != self.chky) self.stop();
3527              self.chky = ny;
3528              self.nc.setScrollTop(ny);
3529            }
3530
3531            if (!self.timer) {
3532              self.nc.hideCursor();
3533              self.doSnapy(nx, ny);
3534            }
3535
3536          });
3537
3538          if (self.demulxy < 1) {
3539            self.timer = setTimeout(onscroll, tm);
3540          } else {
3541            self.stop();
3542            self.nc.hideCursor();
3543            self.doSnapy(nx, ny);
3544          }
3545        };
3546
3547        onscroll();
3548
3549      } else {
3550        self.doSnapy(self.nc.getScrollLeft(), self.nc.getScrollTop());
3551      }
3552
3553    };
3554
3555  };
3556
3557
3558  // override jQuery scrollTop
3559
3560  var _scrollTop = jQuery.fn.scrollTop; // preserve original function
3561
3562  jQuery.cssHooks.pageYOffset = {
3563    get: function(elem, computed, extra) {
3564      var nice = $.data(elem, '__nicescroll') || false;
3565      return (nice && nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(elem);
3566    },
3567    set: function(elem, value) {
3568      var nice = $.data(elem, '__nicescroll') || false;
3569      (nice && nice.ishwscroll) ? nice.setScrollTop(parseInt(value)): _scrollTop.call(elem, value);
3570      return this;
3571    }
3572  };
3573
3574  /*
3575  $.fx.step["scrollTop"] = function(fx){
3576    $.cssHooks["scrollTop"].set( fx.elem, fx.now + fx.unit );
3577  };
3578*/
3579
3580  jQuery.fn.scrollTop = function(value) {
3581    if (value === undefined) {
3582      var nice = (this[0]) ? $.data(this[0], '__nicescroll') || false : false;
3583      return (nice && nice.ishwscroll) ? nice.getScrollTop() : _scrollTop.call(this);
3584    } else {
3585      return this.each(function() {
3586        var nice = $.data(this, '__nicescroll') || false;
3587        (nice && nice.ishwscroll) ? nice.setScrollTop(parseInt(value)): _scrollTop.call($(this), value);
3588      });
3589    }
3590  };
3591
3592  // override jQuery scrollLeft
3593
3594  var _scrollLeft = jQuery.fn.scrollLeft; // preserve original function
3595
3596  $.cssHooks.pageXOffset = {
3597    get: function(elem, computed, extra) {
3598      var nice = $.data(elem, '__nicescroll') || false;
3599      return (nice && nice.ishwscroll) ? nice.getScrollLeft() : _scrollLeft.call(elem);
3600    },
3601    set: function(elem, value) {
3602      var nice = $.data(elem, '__nicescroll') || false;
3603      (nice && nice.ishwscroll) ? nice.setScrollLeft(parseInt(value)): _scrollLeft.call(elem, value);
3604      return this;
3605    }
3606  };
3607
3608  /*
3609  $.fx.step["scrollLeft"] = function(fx){
3610    $.cssHooks["scrollLeft"].set( fx.elem, fx.now + fx.unit );
3611  };
3612*/
3613
3614  jQuery.fn.scrollLeft = function(value) {
3615    if (value === undefined) {
3616      var nice = (this[0]) ? $.data(this[0], '__nicescroll') || false : false;
3617      return (nice && nice.ishwscroll) ? nice.getScrollLeft() : _scrollLeft.call(this);
3618    } else {
3619      return this.each(function() {
3620        var nice = $.data(this, '__nicescroll') || false;
3621        (nice && nice.ishwscroll) ? nice.setScrollLeft(parseInt(value)): _scrollLeft.call($(this), value);
3622      });
3623    }
3624  };
3625
3626  var NiceScrollArray = function(doms) {
3627    var self = this;
3628    this.length = 0;
3629    this.name = "nicescrollarray";
3630
3631    this.each = function(fn) {
3632      $.each(self, fn);
3633      return self;
3634    };
3635
3636    this.push = function(nice) {
3637      self[self.length] = nice;
3638      self.length++;
3639    };
3640
3641    this.eq = function(idx) {
3642      return self[idx];
3643    };
3644
3645    if (doms) {
3646      for (var a = 0; a < doms.length; a++) {
3647        var nice = $.data(doms[a], '__nicescroll') || false;
3648        if (nice) {
3649          this[this.length] = nice;
3650          this.length++;
3651        }
3652      }
3653    }
3654
3655    return this;
3656  };
3657
3658  function mplex(el, lst, fn) {
3659    for (var a = 0; a < lst.length; a++) fn(el, lst[a]);
3660  }
3661  mplex(
3662    NiceScrollArray.prototype, ['show', 'hide', 'toggle', 'onResize', 'resize', 'remove', 'stop', 'doScrollPos'],
3663    function(e, n) {
3664      e[n] = function() {
3665        var args = arguments;
3666        return this.each(function() {
3667          this[n].apply(this, args);
3668        });
3669      };
3670    }
3671  );
3672
3673  jQuery.fn.getNiceScroll = function(index) {
3674    if (index === undefined) {
3675      return new NiceScrollArray(this);
3676    } else {
3677      return this[index] && $.data(this[index], '__nicescroll') || false;
3678    }
3679  };
3680
3681  jQuery.expr[':'].nicescroll = function(a) {
3682    return $.data(a, '__nicescroll') !== undefined;
3683  };
3684
3685  $.fn.niceScroll = function(wrapper, opt) {
3686    if (opt === undefined && typeof wrapper == "object" && !("jquery" in wrapper)) {
3687      opt = wrapper;
3688      wrapper = false;
3689    }
3690    opt = $.extend({},opt); // cloning
3691    var ret = new NiceScrollArray();
3692    if (opt === undefined) opt = {};
3693
3694    if (wrapper || false) {
3695      opt.doc = $(wrapper);
3696      opt.win = $(this);
3697    }
3698    var docundef = !("doc" in opt);
3699    if (!docundef && !("win" in opt)) opt.win = $(this);
3700
3701    this.each(function() {
3702      var nice = $(this).data('__nicescroll') || false;
3703      if (!nice) {
3704        opt.doc = (docundef) ? $(this) : opt.doc;
3705        nice = new NiceScrollClass(opt, $(this));
3706        $(this).data('__nicescroll', nice);
3707      }
3708      ret.push(nice);
3709    });
3710    return (ret.length == 1) ? ret[0] : ret;
3711  };
3712
3713  window.NiceScroll = {
3714    getjQuery: function() {
3715      return jQuery;
3716    }
3717  };
3718
3719  if (!$.nicescroll) {
3720    $.nicescroll = new NiceScrollArray();
3721    $.nicescroll.options = _globaloptions;
3722  }
3723
3724}));

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.