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