PageSourceSearch

https://www.radiolocalitiz.fr/wp-content/themes/kreativa/js/jquery.nicescroll.min.js

js radiolocalitiz.fr collected 2026-10-02 11:18:46 UTC 130,927 bytes, 3,847 lines download raw bytes

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

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.