PageSourceSearch

https://www.32red.com/blog/wp-content/themes/click-mag/js/scripts.js

js 32red.com collected 2026-10-02 04:22:31 UTC 109,805 bytes, 3,236 lines download raw bytes

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

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