1/*! 2 * OverlayScrollbars 3 * https://github.com/KingSora/OverlayScrollbars 4 * 5 * Version: 1.13.3 6 * 7 * Copyright KingSora | Rene Haas. 8 * https://github.com/KingSora 9 * 10 * Released under the MIT license. 11 * Date: 20.07.2022 12 */ 13 14(function (global, factory) { 15 if (typeof define === "function" && define.amd) 16 define(function () { 17 return factory(global, global.document, undefined); 18 }); 19 else if (typeof module === "object" && typeof module.exports === "object") 20 module.exports = factory(global, global.document, undefined); 21 else factory(global, global.document, undefined); 22})( 23 typeof window !== "undefined" ? window : this, 24 function (window, document, undefined) { 25 "use strict"; 26 var PLUGINNAME = "OverlayScrollbars"; 27 var TYPES = { 28 o: "object", 29 f: "function", 30 a: "array", 31 s: "string", 32 b: "boolean", 33 n: "number", 34 u: "undefined", 35 z: "null", 36 //d : 'date', 37 //e : 'error', 38 //r : 'regexp', 39 //y : 'symbol' 40 }; 41 var LEXICON = { 42 c: "class", 43 s: "style", 44 i: "id", 45 l: "length", 46 p: "prototype", 47 ti: "tabindex", 48 oH: "offsetHeight", 49 cH: "clientHeight", 50 sH: "scrollHeight", 51 oW: "offsetWidth", 52 cW: "clientWidth", 53 sW: "scrollWidth", 54 hOP: "hasOwnProperty", 55 bCR: "getBoundingClientRect", 56 }; 57 var VENDORS = (function () { 58 //https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix 59 var jsCache = {}; 60 var cssCache = {}; 61 var cssPrefixes = ["-webkit-", "-moz-", "-o-", "-ms-"]; 62 var jsPrefixes = ["WebKit", "Moz", "O", "MS"]; 63 function firstLetterToUpper(str) { 64 return str.charAt(0).toUpperCase() + str.slice(1); 65 } 66 67 return { 68 _cssPrefixes: cssPrefixes, 69 _jsPrefixes: jsPrefixes, 70 _cssProperty: function (name) { 71 var result = cssCache[name]; 72 73 if (cssCache[LEXICON.hOP](name)) return result; 74 75 var uppercasedName = firstLetterToUpper(name); 76 var elmStyle = document.createElement("div")[LEXICON.s]; 77 var resultPossibilities; 78 var i = 0; 79 var v; 80 var currVendorWithoutDashes; 81 82 for (; i < cssPrefixes.length; i++) { 83 currVendorWithoutDashes = cssPrefixes[i].replace(/-/g, ""); 84 resultPossibilities = [ 85 name, //transition 86 cssPrefixes[i] + name, //-webkit-transition 87 currVendorWithoutDashes + uppercasedName, //webkitTransition 88 firstLetterToUpper(currVendorWithoutDashes) + uppercasedName, //WebkitTransition 89 ]; 90 for (v = 0; v < resultPossibilities[LEXICON.l]; v++) { 91 if (elmStyle[resultPossibilities[v]] !== undefined) { 92 result = resultPossibilities[v]; 93 break; 94 } 95 } 96 } 97 98 cssCache[name] = result; 99 return result; 100 }, 101 _cssPropertyValue: function (property, values, suffix) { 102 var name = property + " " + values; 103 var result = cssCache[name]; 104 105 if (cssCache[LEXICON.hOP](name)) return result; 106 107 var dummyStyle = document.createElement("div")[LEXICON.s]; 108 var possbleValues = values.split(" "); 109 var preparedSuffix = suffix || ""; 110 var i = 0; 111 var v = -1; 112 var prop; 113 114 for (; i < possbleValues[LEXICON.l]; i++) { 115 for (; v < VENDORS._cssPrefixes[LEXICON.l]; v++) { 116 prop = 117 v < 0 118 ? possbleValues[i] 119 : VENDORS._cssPrefixes[v] + possbleValues[i]; 120 dummyStyle.cssText = property + ":" + prop + preparedSuffix; 121 if (dummyStyle[LEXICON.l]) { 122 result = prop; 123 break; 124 } 125 } 126 } 127 128 cssCache[name] = result; 129 return result; 130 }, 131 _jsAPI: function (name, isInterface, fallback) { 132 var i = 0; 133 var result = jsCache[name]; 134 135 if (!jsCache[LEXICON.hOP](name)) { 136 result = window[name]; 137 for (; i < jsPrefixes[LEXICON.l]; i++) 138 result = 139 result || 140 window[ 141 (isInterface ? jsPrefixes[i] : jsPrefixes[i].toLowerCase()) + 142 firstLetterToUpper(name) 143 ]; 144 jsCache[name] = result; 145 } 146 return result || fallback; 147 }, 148 }; 149 })(); 150 var COMPATIBILITY = (function () { 151 function windowSize(x) { 152 return x 153 ? window.innerWidth || 154 document.documentElement[LEXICON.cW] || 155 document.body[LEXICON.cW] 156 : window.innerHeight || 157 document.documentElement[LEXICON.cH] || 158 document.body[LEXICON.cH]; 159 } 160 function bind(func, thisObj) { 161 if (typeof func != TYPES.f) { 162 throw "Can't bind function!"; 163 // closest thing possible to the ECMAScript 5 164 // internal IsCallable function 165 //throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 166 } 167 var proto = LEXICON.p; 168 var aArgs = Array[proto].slice.call(arguments, 2); 169 var fNOP = function () {}; 170 var fBound = function () { 171 return func.apply( 172 this instanceof fNOP ? this : thisObj, 173 aArgs.concat(Array[proto].slice.call(arguments)) 174 ); 175 }; 176 177 if (func[proto]) fNOP[proto] = func[proto]; // Function.prototype doesn't have a prototype property 178 fBound[proto] = new fNOP(); 179 180 return fBound; 181 } 182 183 return { 184 /** 185 * Gets the current window width. 186 * @returns {Number|number} The current window width in pixel. 187 */ 188 wW: bind(windowSize, 0, true), 189 190 /** 191 * Gets the current window height. 192 * @returns {Number|number} The current window height in pixel. 193 */ 194 wH: bind(windowSize, 0), 195 196 /** 197 * Gets the MutationObserver Object or undefined if not supported. 198 * @returns {MutationObserver|*|undefined} The MutationsObserver Object or undefined. 199 */ 200 mO: bind(VENDORS._jsAPI, 0, "MutationObserver", true), 201 202 /** 203 * Gets the ResizeObserver Object or undefined if not supported. 204 * @returns {MutationObserver|*|undefined} The ResizeObserver Object or undefined. 205 */ 206 rO: bind(VENDORS._jsAPI, 0, "ResizeObserver", true), 207 208 /** 209 * Gets the RequestAnimationFrame method or it's corresponding pol
209yfill. 210 * @returns {*|Function} The RequestAnimationFrame method or it's corresponding polyfill. 211 */ 212 rAF: bind( 213 VENDORS._jsAPI, 214 0, 215 "requestAnimationFrame", 216 false, 217 function (func) { 218 return window.setTimeout(func, 1000 / 60); 219 } 220 ), 221 222 /** 223 * Gets the CancelAnimationFrame method or it's corresponding polyfill. 224 * @returns {*|Function} The CancelAnimationFrame method or it's corresponding polyfill. 225 */ 226 cAF: bind( 227 VENDORS._jsAPI, 228 0, 229 "cancelAnimationFrame", 230 false, 231 function (id) { 232 return window.clearTimeout(id); 233 } 234 ), 235 236 /** 237 * Gets the current time. 238 * @returns {number} The current time. 239 */ 240 now: function () { 241 return (Date.now && Date.now()) || new Date().getTime(); 242 }, 243 244 /** 245 * Stops the propagation of the given event. 246 * @param event The event of which the propagation shall be stoped. 247 */ 248 stpP: function (event) { 249 if (event.stopPropagation) event.stopPropagation(); 250 else event.cancelBubble = true; 251 }, 252 253 /** 254 * Prevents the default action of the given event. 255 * @param event The event of which the default action shall be prevented. 256 */ 257 prvD: function (event) { 258 if (event.preventDefault && event.cancelable) event.preventDefault(); 259 else event.returnValue = false; 260 }, 261 262 /** 263 * Gets the pageX and pageY values of the given mouse event. 264 * @param event The mouse event of which the pageX and pageX shall be got. 265 * @returns {{x: number, y: number}} x = pageX value, y = pageY value. 266 */ 267 page: function (event) { 268 event = event.originalEvent || event; 269 270 var strPage = "page"; 271 var strClient = "client"; 272 var strX = "X"; 273 var strY = "Y"; 274 var target = event.target || event.srcElement || document; 275 var eventDoc = target.ownerDocument || document; 276 var doc = eventDoc.documentElement; 277 var body = eventDoc.body; 278 279 //if touch event return return pageX/Y of it 280 if (event.touches !== undefined) { 281 var touch = event.touches[0]; 282 return { 283 x: touch[strPage + strX], 284 y: touch[strPage + strY], 285 }; 286 } 287 288 // Calculate pageX/Y if not native supported 289 if ( 290 !event[strPage + strX] && 291 event[strClient + strX] && 292 event[strClient + strX] != null 293 ) { 294 return { 295 x: 296 event[strClient + strX] + 297 ((doc && doc.scrollLeft) || (body && body.scrollLeft) || 0) - 298 ((doc && doc.clientLeft) || (body && body.clientLeft) || 0), 299 y: 300 event[strClient + strY] + 301 ((doc && doc.scrollTop) || (body && body.scrollTop) || 0) - 302 ((doc && doc.clientTop) || (body && body.clientTop) || 0), 303 }; 304 } 305 return { 306 x: event[strPage + strX], 307 y: event[strPage + strY], 308 }; 309 }, 310 311 /** 312 * Gets the clicked mouse button of the given mouse event. 313 * @param event The mouse event of which the clicked button shal be got. 314 * @returns {number} The number of the clicked mouse button. (0 : none | 1 : leftButton | 2 : middleButton | 3 : rightButton) 315 */ 316 mBtn: function (event) { 317 var button = event.button; 318 if (!event.which && button !== undefined) 319 return button & 1 ? 1 : button & 2 ? 3 : button & 4 ? 2 : 0; 320 else return event.which; 321 }, 322 323 /** 324 * Checks whether a item is in the given array and returns its index. 325 * @param item The item of which the position in the array shall be determined. 326 * @param arr The array. 327 * @returns {number} The zero based index of the item or -1 if the item isn't in the array. 328 */ 329 inA: function (item, arr) { 330 for (var i = 0; i < arr[LEXICON.l]; i++) 331 //Sometiems in IE a "SCRIPT70" Permission denied error occurs if HTML elements in a iFrame are compared 332 try { 333 if (arr[i] === item) return i; 334 } catch (e) {} 335 return -1; 336 }, 337 338 /** 339 * Returns true if the given value is a array.
340 * @param arr The potential array. 341 * @returns {boolean} True if the given value is a array, false otherwise. 342 */ 343 isA: function (arr) { 344 var def = Array.isArray; 345 return def ? def(arr) : this.type(arr) == TYPES.a; 346 }, 347 348 /** 349 * Determine the internal JavaScript [[Class]] of the given object. 350 * @param obj The object of which the type shall be determined. 351 * @returns {string} The type of the given object. 352 */ 353 type: function (obj) { 354 if (obj === undefined) return obj + ""; 355 if (obj === null) return obj + ""; 356 return Object[LEXICON.p].toString 357 .call(obj) 358 .replace(/^\[object (.+)\]$/, "$1") 359 .toLowerCase(); 360 }, 361 362 bind: bind, 363 364 /** 365 * Gets the vendor-prefixed CSS property by the given name. 366 * For example the given name is "transform" and you're using a old Firefox browser then the returned value would be "-moz-transform". 367 * If the browser doesn't need a vendor-prefix, then the returned string is the given name. 368 * If the browser doesn't support the given property name at all (not even with a vendor-prefix) the returned value is null. 369 * @param propName The unprefixed CSS property name. 370 * @returns {string|null} The vendor-prefixed CSS property or null if the browser doesn't support the given CSS property. 371 372 cssProp: function(propName) { 373 return VENDORS._cssProperty(propName); 374 } 375 */ 376 }; 377 })(); 378 379 var MATH = Math; 380 var JQUERY = window.jQuery; 381 var EASING = (function () { 382 var _easingsMath = { 383 p: MATH.PI, 384 c: MATH.cos, 385 s: MATH.sin, 386 w: MATH.pow, 387 t: MATH.sqrt, 388 n: MATH.asin, 389 a: MATH.abs, 390 o: 1.70158, 391 }; 392 393 /* 394 x : current percent (0 - 1), 395 t : current time (duration * percent), 396 b : start value (from), 397 c : end value (to), 398 d : duration 399 400 easingName : function(x, t, b, c, d) { return easedValue; } 401 */ 402 403 return { 404 swing: function (x, t, b, c, d) { 405 return 0.5 - _easingsMath.c(x * _easingsMath.p) / 2; 406 }, 407 linear: function (x, t, b, c, d) { 408 return x; 409 }, 410 easeInQuad: function (x, t, b, c, d) { 411 return c * (t /= d) * t + b; 412 }, 413 easeOutQuad: function (x, t, b, c, d) { 414 return -c * (t /= d) * (t - 2) + b; 415 }, 416 easeInOutQuad: function (x, t, b, c, d) { 417 return (t /= d / 2) < 1 418 ? (c / 2) * t * t + b 419 : (-c / 2) * (--t * (t - 2) - 1) + b; 420 }, 421 easeInCubic: function (x, t, b, c, d) { 422 return c * (t /= d) * t * t + b; 423 }, 424 easeOutCubic: function (x, t, b, c, d) { 425 return c * ((t = t / d - 1) * t * t + 1) + b; 426 }, 427 easeInOutCubic: function (x, t, b, c, d) { 428 return (t /= d / 2) < 1 429 ? (c / 2) * t * t * t + b 430 : (c / 2) * ((t -= 2) * t * t + 2) + b; 431 }, 432 easeInQuart: function (x, t, b, c, d) { 433 return c * (t /= d) * t * t * t + b; 434 }, 435 easeOutQuart: function (x, t, b, c, d) { 436 return -c * ((t = t / d - 1) * t * t * t - 1) + b; 437 }, 438 easeInOutQuart: function (x, t, b, c, d) { 439 return (t /= d / 2) < 1 440 ? (c / 2) * t * t * t * t + b 441 : (-c / 2) * ((t -= 2) * t * t * t - 2) + b; 442 }, 443 easeInQuint: function (x, t, b, c, d) { 444 return c * (t /= d) * t * t * t * t + b; 445 }, 446 easeOutQuint: function (x, t, b, c, d) { 447 return c * ((t = t / d - 1) * t * t * t * t + 1) + b; 448 }, 449 easeInOutQuint: function (x, t, b, c, d) { 450 return (t /= d / 2) < 1 451 ? (c / 2) * t * t * t * t * t + b 452 : (c / 2) * ((t -= 2) * t * t * t * t + 2) + b; 453 }, 454 easeInSine: function (x, t, b, c, d) { 455 return -c * _easingsMath.c((t / d) * (_easingsMath.p / 2)) + c + b; 456 }, 457 easeOutSine: function (x, t, b, c, d) { 458 return c * _easingsMath.s((t / d) * (_easingsMath.p / 2)) + b; 459 }, 460 easeInOutSine: function (x, t, b, c, d) { 461 return (-c / 2) * (_easingsMath.c((_easingsMath.p * t) / d) - 1) + b; 462 }, 463 easeInExpo: function (x, t, b, c, d) { 464 return t == 0 ? b : c * _easingsMath.w(2, 10 * (t / d - 1)) + b; 465 }, 466 easeOutExpo: function (x, t, b, c, d) { 467 return t == d 468 ? b + c 469 : c * (-_easingsMath.w(2, (-10 * t) / d) + 1) + b; 470 }, 471 easeInOutExpo: function (x, t, b, c, d) { 472 if (t == 0) return b; 473 if (t == d) return b + c; 474 if ((t /= d / 2) < 1) 475 return (c / 2) * _easingsMath.w(2, 10 * (t - 1)) + b; 476 return (c / 2) * (-_easingsMath.w(2, -10 * --t) + 2) + b; 477 }, 478 easeInCirc: function (x, t, b, c, d) { 479 return -c * (_easingsMath.t(1 - (t /= d) * t) - 1) + b; 480 }, 481 easeOutCirc: function (x, t, b, c, d) { 482 return c * _easingsMath.t(1 - (t = t / d - 1) * t) + b; 483 }, 484 easeInOutCirc: function (x, t, b, c, d) { 485 return (t /= d / 2) < 1 486 ? (-c / 2) * (_easingsMath.t(1 - t * t) - 1) + b 487 : (c / 2) * (_easingsMath.t(1 - (t -= 2) * t) + 1) + b; 488 }, 489 easeInElastic: function (x, t, b, c, d) { 490 var s = _easingsMath.o; 491 var p = 0; 492 var a = c; 493 if (t == 0) return b; 494 if ((t /= d) == 1) return b + c; 495 if (!p) p = d * 0.3; 496 if (a < _easingsMath.a(c)) { 497 a = c; 498 s = p / 4; 499 } else s = (p / (2 * _easingsMath.p)) * _easingsMath.n(c / a); 500 return ( 501 -( 502 a * 503 _easingsMath.w(2, 10 * (t -= 1)) * 504 _easingsMath.s(((t * d - s) * (2 * _easingsMath.p)) / p) 505 ) + b 506 ); 507 }, 508 easeOutElastic: function (x, t, b, c, d) { 509 var s = _easingsMath.o; 510 var p = 0; 511 var a = c; 512 if (t == 0) return b; 513 if ((t /= d) == 1) return b + c; 514 if (!p) p = d * 0.3; 515 if (a < _easingsMath.a(c)) { 516 a = c; 517 s = p / 4; 518 } else s = (p / (2 * _easingsMath.p)) * _easingsMath.n(c / a); 519 return ( 520 a * 521 _easingsMath.w(2, -10 * t) * 522 _easingsMath.s(((t * d - s) * (2 * _easingsMath.p)) / p) + 523 c + 524 b 525 ); 526 }, 527 easeInOutElastic: function (x, t, b, c, d) { 528 var s = _easingsMath.o; 529 var p = 0; 530 var a = c; 531 if (t == 0) return b; 532 if ((t /= d / 2) == 2) return b + c; 533 if (!p) p = d * (0.3 * 1.5); 534 if (a < _easingsMath.a(c)) { 535 a = c; 536 s = p / 4; 537 } else s = (p / (2 * _easingsMath.p)) * _easingsMath.n(c / a); 538 if (t < 1) 539 return ( 540 -0.5 * 541 (a * 542 _easingsMath.w(2, 10 * (t -= 1)) * 543 _easingsMath.s(((t * d - s) * (2 * _easingsMath.p)) / p)) + 544 b 545 ); 546 return ( 547 a * 548 _easingsMath.w(2, -10 * (t -= 1)) * 549 _easingsMath.s(((t * d - s) * (2 * _easingsMath.p)) / p) * 550 0.5 + 551 c + 552 b 553 ); 554 }, 555 easeInBack: function (x, t, b, c, d, s) { 556 s = s || _easingsMath.o; 557 return c * (t /= d) * t * ((s + 1) * t - s) + b; 558 }, 559 easeOutBack: function (x, t, b, c, d, s) { 560 s = s || _easingsMath.o;
561 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; 562 }, 563 easeInOutBack: function (x, t, b, c, d, s) { 564 s = s || _easingsMath.o; 565 return (t /= d / 2) < 1 566 ? (c / 2) * (t * t * (((s *= 1.525) + 1) * t - s)) + b 567 : (c / 2) * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b; 568 }, 569 easeInBounce: function (x, t, b, c, d) { 570 return c - this.easeOutBounce(x, d - t, 0, c, d) + b; 571 }, 572 easeOutBounce: function (x, t, b, c, d) { 573 var o = 7.5625; 574 if ((t /= d) < 1 / 2.75) { 575 return c * (o * t * t) + b; 576 } else if (t < 2 / 2.75) { 577 return c * (o * (t -= 1.5 / 2.75) * t + 0.75) + b; 578 } else if (t < 2.5 / 2.75) { 579 return c * (o * (t -= 2.25 / 2.75) * t + 0.9375) + b; 580 } else { 581 return c * (o * (t -= 2.625 / 2.75) * t + 0.984375) + b; 582 } 583 }, 584 easeInOutBounce: function (x, t, b, c, d) { 585 return t < d / 2 586 ? this.easeInBounce(x, t * 2, 0, c, d) * 0.5 + b 587 : this.easeOutBounce(x, t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b; 588 }, 589 }; 590 /* 591 * 592 * TERMS OF USE - EASING EQUATIONS 593 * 594 * Open source under the BSD License. 595 * 596 * Copyright © 2001 Robert Penner 597 * All rights reserved. 598 * 599 * Redistribution and use in source and binary forms, with or without modification, 600 * are permitted provided that the following conditions are met: 601 * 602 * Redistributions of source code must retain the above copyright notice, this list of 603 * conditions and the following disclaimer. 604 * Redistributions in binary form must reproduce the above copyright notice, this list 605 * of conditions and the following disclaimer in the documentation and/or other materials 606 * provided with the distribution. 607 * 608 * Neither the name of the author nor the names of contributors may be used to endorse 609 * or promote products derived from this software without specific prior written permission. 610 * 611 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 612 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 613 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 614 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 615 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 616 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 617 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 618 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 619 * OF THE POSSIBILITY OF SUCH DAMAGE. 620 * 621 */ 622 })(); 623 var FRAMEWORK = (function () { 624 var _rnothtmlwhite = /[^\x20\t\r\n\f]+/g; 625 var _strSpace = " "; 626 var _strEmpty = ""; 627 var _strScrollLeft = "scrollLeft"; 628 var _strScrollTop = "scrollTop"; 629 var _animations = []; 630 var _type = COMPATIBILITY.type; 631 var _cssNumber = { 632 animationIterationCount: true, 633 columnCount: true, 634 fillOpacity: true, 635 flexGrow: true, 636 flexShrink: true, 637 fontWeight: true, 638 lineHeight: true, 639 opacity: true, 640 order: true, 641 orphans: true, 642 widows: true, 643 zIndex: true, 644 zoom: true, 645 }; 646 647 function extend() { 648 var src, 649 copyIsArray, 650 copy, 651 name, 652 options, 653 clone, 654 target = arguments[0] || {}, 655 i = 1, 656 length = arguments[LEXICON.l], 657 deep = false; 658 659 // Handle a deep copy situation 660 if (_type(target) == TYPES.b) { 661 deep = target; 662 target = arguments[1] || {}; 663 // skip the boolean and the target 664 i = 2; 665 } 666 667 // Handle case when target is a string or something (possible in deep copy) 668 if (_type(target) != TYPES.o && !_type(target) == TYPES.f) { 669 target = {}; 670 } 671 672 // extend jQuery itself if only one argument is passed 673 if (length === i) { 674 target = FakejQuery; 675 --i; 676 } 677 678 for (; i < length; i++) { 679 // Only deal with non-null/undefined values 680 if ((options = arguments[i]) != null) { 681 // Extend the base object 682 for (name in options) { 683 src = target[name]; 684 copy = options[name]; 685 686 // Prevent never-ending loop 687 if (target === copy) { 688 continue; 689 } 690 691 // Recurse if we're merging plain objects or arrays 692 if ( 693 deep && 694 copy && 695 (isPlainObject(copy) || (copyIsArray = COMPATIBILITY.isA(copy))) 696 ) { 697 if (copyIsArray) { 698 copyIsArray = false;
699 clone = src && COMPATIBILITY.isA(src) ? src : []; 700 } else { 701 clone = src && isPlainObject(src) ? src : {}; 702 } 703 704 // Never move original objects, clone them 705 target[name] = extend(deep, clone, copy); 706 707 // Don't bring in undefined values 708 } else if (copy !== undefined) { 709 target[name] = copy; 710 } 711 } 712 } 713 } 714 715 // Return the modified object 716 return target; 717 } 718 719 function inArray(item, arr, fromIndex) { 720 for (var i = fromIndex || 0; i < arr[LEXICON.l]; i++) 721 if (arr[i] === item) return i; 722 return -1; 723 } 724 725 function isFunction(obj) { 726 return _type(obj) == TYPES.f; 727 } 728 729 function isEmptyObject(obj) { 730 for (var name in obj) return false; 731 return true; 732 } 733 734 function isPlainObject(obj) { 735 if (!obj || _type(obj) != TYPES.o) return false; 736 737 var key; 738 var proto = LEXICON.p; 739 var hasOwnProperty = Object[proto].hasOwnProperty; 740 var hasOwnConstructor = hasOwnProperty.call(obj, "constructor"); 741 var hasIsPrototypeOf = 742 obj.constructor && 743 obj.constructor[proto] && 744 hasOwnProperty.call(obj.constructor[proto], "isPrototypeOf"); 745 746 if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { 747 return false; 748 } 749 750 for (key in obj) { 751 /**/ 752 } 753 754 return _type(key) == TYPES.u || hasOwnProperty.call(obj, key); 755 } 756 757 function each(obj, callback) { 758 var i = 0; 759 760 if (isArrayLike(obj)) { 761 for (; i < obj[LEXICON.l]; i++) { 762 if (callback.call(obj[i], i, obj[i]) === false) break; 763 } 764 } else { 765 for (i in obj) { 766 if (callback.call(obj[i], i, obj[i]) === false) break; 767 } 768 } 769 770 return obj; 771 } 772 773 function isArrayLike(obj) { 774 var length = !!obj && [LEXICON.l] in obj && obj[LEXICON.l]; 775 var t = _type(obj); 776 return isFunction(t) 777 ? false 778 : t == TYPES.a || 779 length === 0 || 780 (_type(length) == TYPES.n && length > 0 && length - 1 in obj); 781 } 782 783 function stripAndCollapse(value) { 784 var tokens = value.match(_rnothtmlwhite) || []; 785 return tokens.join(_strSpace); 786 } 787 788 function matches(elem, selector) { 789 var nodeList = 790 (elem.parentNode || document).querySelectorAll(selector) || []; 791 var i = nodeList[LEXICON.l]; 792 793 while (i--) if (nodeList[i] == elem) return true; 794 795 return false; 796 } 797 798 function insertAdjacentElement(el, strategy, child) { 799 if (COMPATIBILITY.isA(child)) { 800 for (var i = 0; i < child[LEXICON.l]; i++) 801 insertAdjacentElement(el, strategy, child[i]); 802 } else if (_type(child) == TYPES.s) 803 el.insertAdjacentHTML(strategy, child); 804 else 805 el.insertAdjacentElement(strategy, child.nodeType ? child : child[0]); 806 } 807 808 function setCSSVal(el, prop, val) { 809 try { 810 if (el[LEXICON.s][prop] !== undefined) 811 el[LEXICON.s][prop] = parseCSSVal(prop, val); 812 } catch (e) {} 813 } 814 815 function parseCSSVal(prop, val) { 816 if (!_cssNumber[prop.toLowerCase()] && _type(val) == TYPES.n) 817 val += "px"; 818 return val; 819 } 820 821 function startNextAnimationInQ(animObj, removeFromQ) { 822 var index; 823 var nextAnim; 824 if (removeFromQ !== false) animObj.q.splice(0, 1); 825 if (animObj.q[LEXICON.l] > 0) { 826 nextAnim = animObj.q[0]; 827 animate( 828 animObj.el, 829 nextAnim.props, 830 nextAnim.duration, 831 nextAnim.easing, 832 nextAnim.complete, 833 true 834 ); 835 } else { 836 index = inArray(animObj, _animations); 837 if (index > -1) _animations.splice(index, 1); 838 } 839 } 840 841 function setAnimationValue(el, prop, value) { 842 if (prop === _strScrollLeft || prop === _strScrollTop) el[prop] = value; 843 else setCSSVal(el, prop, value); 844 } 845 846 function animate(el, props, options, easing, complete, guaranteedNext) { 847 var hasOptions = isPlainObject(options); 848 var from = {}; 849 var to = {}; 850 var i = 0; 851 var key; 852 var animObj; 853 var start; 854 var progress; 855 var step; 856 var specialEasing; 857 var duration; 858 if (hasOptions) { 859 easing = options.easing; 860 start = options.start; 861 progress = options.progress; 862 step = options.step; 863 specialEasing = options.specialEasing; 864 complete = options.complete; 865 duration = options.duration; 866 } else duration = options; 867 specialEasing = specialEasing || {}; 868 duration = duration || 400; 869 easing = easing || "swing"; 870 guaranteedNext = guaranteedNext || false; 871 872 for (; i < _animations[LEXICON.l]; i++) { 873 if (_animations[i].el === el) { 874 animObj = _animations[i]; 875 break; 876 } 877 } 878 879 if (!animObj) { 880 animObj = { 881 el: el, 882 q: [], 883 }; 884 _animations.push(animObj); 885 } 886 887 for (key in props) { 888 if (key === _strScrollLeft || key === _strScrollTop) 889 from[key] = el[key]; 890 else from[key] = FakejQuery(el).css(key); 891 } 892 893 for (key in from) { 894 if (from[key] !== props[key] && props[key] !== undefined) 895 to[key] = props[key]; 896 } 897 898 if (!isEmptyObject(to)) { 899 var timeNow; 900 var end; 901 var percent; 902 var fromVal; 903 var toVal; 904 var easedVal; 905 var timeStart; 906 var frame; 907 var elapsed; 908 var qPos = guaranteedNext ? 0 : inArray(qObj, animObj.q); 909 var qObj = { 910 props: to, 911 duration: hasOptions ? options : duration, 912 easing: easing, 913 complete: complete, 914 }; 915 if (qPos === -1) { 916 qPos = animObj.q[LEXICON.l]; 917 animObj.q.push(qObj); 918 } 919 920 if (qPos === 0) { 921 if (duration > 0) { 922 timeStart = COMPATIBILITY.now(); 923 frame = function () { 924 timeNow = COMPATIBILITY.now();
925 elapsed = timeNow - timeStart; 926 end = qObj.stop || elapsed >= duration; 927 percent = 928 1 - 929 (MATH.max(0, timeStart + duration - timeNow) / duration || 0); 930 931 for (key in to) { 932 fromVal = parseFloat(from[key]); 933 toVal = parseFloat(to[key]); 934 easedVal = 935 (toVal - fromVal) * 936 EASING[specialEasing[key] || easing]( 937 percent, 938 percent * duration, 939 0, 940 1, 941 duration 942 ) + 943 fromVal; 944 setAnimationValue(el, key, easedVal); 945 if (isFunction(step)) { 946 step(easedVal, { 947 elem: el, 948 prop: key, 949 start: fromVal, 950 now: easedVal, 951 end: toVal, 952 pos: percent, 953 options: { 954 easing: easing, 955 speacialEasing: specialEasing, 956 duration: duration, 957 complete: complete, 958 step: step, 959 }, 960 startTime: timeStart, 961 }); 962 } 963 } 964 965 if (isFunction(progress)) 966 progress({}, percent, MATH.max(0, duration - elapsed)); 967 968 if (end) { 969 startNextAnimationInQ(animObj); 970 if (isFunction(complete)) complete(); 971 } else qObj.frame = COMPATIBILITY.rAF()(frame); 972 }; 973 qObj.frame = COMPATIBILITY.rAF()(frame); 974 } else { 975 for (key in to) setAnimationValue(el, key, to[key]); 976 startNextAnimationInQ(animObj); 977 } 978 } 979 } else if (guaranteedNext) startNextAnimationInQ(animObj); 980 } 981 982 function stop(el, clearQ, jumpToEnd) { 983 var animObj; 984 var qObj; 985 var key; 986 var i = 0; 987 for (; i < _animations[LEXICON.l]; i++) { 988 animObj = _animations[i]; 989 if (animObj.el === el) { 990 if (animObj.q[LEXICON.l] > 0) { 991 qObj = animObj.q[0]; 992 qObj.stop = true; 993 COMPATIBILITY.cAF()(qObj.frame); 994 animObj.q.splice(0, 1); 995 996 if (jumpToEnd) 997 for (key in qObj.props) 998 setAnimationValue(el, key, qObj.props[key]); 999 1000 if (clearQ) animObj.q = []; 1001 else startNextAnimationInQ(animObj, false); 1002 } 1003 break; 1004 } 1005 } 1006 } 1007 1008 function elementIsVisible(el) { 1009 return !!( 1010 el[LEXICON.oW] || 1011 el[LEXICON.oH] || 1012 el.getClientRects()[LEXICON.l] 1013 ); 1014 } 1015 1016 function FakejQuery(selector) { 1017 if (arguments[LEXICON.l] === 0) return this; 1018 1019 var base = new FakejQuery(); 1020 var elements = selector; 1021 var i = 0; 1022 var elms; 1023 var el; 1024 1025 if (_type(selector) == TYPES.s) { 1026 elements = []; 1027 if (selector.charAt(0) === "<") { 1028 el = document.createElement("div"); 1029 el.innerHTML = selector; 1030 elms = el.children; 1031 } else { 1032 elms = document.querySelectorAll(selector); 1033 } 1034 1035 for (; i < elms[LEXICON.l]; i++) elements.push(elms[i]); 1036 } 1037 1038 if (elements) { 1039 if ( 1040 _type(elements) != TYPES.s && 1041 (!isArrayLike(elements) || 1042 elements === window || 1043 elements === elements.self) 1044 ) 1045 elements = [elements]; 1046 1047 for (i = 0; i < elements[LEXICON.l]; i++) base[i] = elements[i]; 1048 1049 base[LEXICON.l] = elements[LEXICON.l]; 1050 } 1051 1052 return base; 1053 } 1054 1055 FakejQuery[LEXICON.p] = { 1056 //EVENTS: 1057 1058 on: function (eventName, handler) { 1059 eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [ 1060 _strEmpty, 1061 ]; 1062 1063 var eventNameLength = eventName[LEXICON.l]; 1064 var i = 0; 1065 var el; 1066 return this.each(function () { 1067 el = this; 1068 try { 1069 if (el.addEventListener) { 1070 for (; i < eventNameLength; i++) 1071 el.addEventListener(eventName[i], handler); 1072 } else if (el.detachEvent) { 1073 for (; i < eventNameLength; i++) 1074 el.attachEvent("on" + eventName[i], handler); 1075 } 1076 } catch (e) {} 1077 }); 1078 }, 1079 1080 off: function (eventName, handler) { 1081 eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [ 1082 _strEmpty, 1083 ]; 1084 1085 var eventNameLength = eventName[LEXICON.l]; 1086 var i = 0; 1087 var el; 1088 return this.each(function () { 1089 el = this; 1090 try { 1091 if (el.removeEventListener) { 1092 for (; i < eventNameLength; i++) 1093 el.removeEventListener(eventName[i], handler); 1094 } else if (el.detachEvent) { 1095 for (; i < eventNameLength; i++) 1096 el.detachEvent("on" + eventName[i], handler); 1097 } 1098 } catch (e) {} 1099 }); 1100 }, 1101 1102 one: function (eventName, handler) { 1103 eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [ 1104 _strEmpty, 1105 ]; 1106 return this.each(function () { 1107 var el = FakejQuery(this); 1108 FakejQuery.each(eventName, function (i, oneEventName) { 1109 var oneHandler = function (e) { 1110 handler.call(this, e); 1111 el.off(oneEventName, oneHandler); 1112 }; 1113 el.on(oneEventName, oneHandler); 1114 }); 1115 }); 1116 }, 1117 1118 trigger: function (eventName) { 1119 var el; 1120 var event; 1121 return this.each(function () { 1122 el = this; 1123 if (document.createEvent) { 1124 event = document.createEvent("HTMLEvents"); 1125 event.initEvent(eventName, true, false); 1126 el.dispatchEvent(event); 1127 } else { 1128 el.fireEvent("on" + eventName); 1129 } 1130 }); 1131 }, 1132 1133 //DOM NODE INSERTING / REMOVING: 1134 1135 append: function (child) { 1136 return this.each(function () { 1137 insertAdjacentElement(this, "beforeend", child); 1138 }); 1139 }, 1140 1141 prepend: function (child) { 1142 return this.each(function () { 1143 insertAdjacentElement(this, "afterbegin", child); 1144 }); 1145 }, 1146 1147 before: function (child) { 1148 return this.each(function () { 1149 insertAdjacentElement(this, "beforebegin", child); 1150 }); 1151 }, 1152 1153 after: function (child) { 1154 return this.each(function () { 1155 insertAdjacentElement(this, "afterend", child); 1156 }); 1157 }, 1158 1159 remove: function () { 1160 return this.each(function () { 1161 var el = this; 1162 var parentNode = el.parentNode; 1163 if (parentNode != null) parentNode.removeChild(el); 1164 }); 1165 }, 1166 1167 unwrap: function () { 1168 var parents = []; 1169 var i; 1170 var el; 1171 var parent; 1172 1173 this.each(function () { 1174 parent = this.parentNode; 1175 if (inArray(parent, parents) === -1) parents.push(parent); 1176 }); 1177 1178 for (i = 0; i < parents[LEXICON.l]; i++) { 1179 el = parents[i]; 1180 parent = el.parentNode; 1181 while (el.firstChild) parent.insertBefore(el.firstChild, el); 1182 parent.removeChild(el); 1183 } 1184 1185 return this; 1186 }, 1187 1188 wrapAll: function (wrapperHTML) { 1189 var i; 1190 var nodes = this; 1191 var wrapper = FakejQuery(wrapperHTML)[0]; 1192 var deepest = wrapper; 1193 var parent = nodes[0].parentNode; 1194 var previousSibling = nodes[0].previousSibling; 1195 while (deepest.childNodes[LEXICON.l] > 0) 1196 deepest = deepest.childNodes[0]; 1197 1198 for ( 1199 i = 0; 1200 nodes[LEXICON.l] - i;
1201 deepest.firstChild === nodes[0] && i++ 1202 ) 1203 deepest.appendChild(nodes[i]); 1204 1205 var nextSibling = previousSibling 1206 ? previousSibling.nextSibling 1207 : parent.firstChild; 1208 parent.insertBefore(wrapper, nextSibling); 1209 1210 return this; 1211 }, 1212 1213 wrapInner: function (wrapperHTML) { 1214 return this.each(function () { 1215 var el = FakejQuery(this); 1216 var contents = el.contents(); 1217 1218 if (contents[LEXICON.l]) contents.wrapAll(wrapperHTML); 1219 else el.append(wrapperHTML); 1220 }); 1221 }, 1222 1223 wrap: function (wrapperHTML) { 1224 return this.each(function () { 1225 FakejQuery(this).wrapAll(wrapperHTML); 1226 }); 1227 }, 1228 1229 //DOM NODE MANIPULATION / INFORMATION: 1230 1231 css: function (styles, val) { 1232 var el; 1233 var key; 1234 var cptStyle; 1235 var getCptStyle = window.getComputedStyle; 1236 if (_type(styles) == TYPES.s) { 1237 if (val === undefined) { 1238 el = this[0]; 1239 cptStyle = getCptStyle 1240 ? getCptStyle(el, null) 1241 : el.currentStyle[styles]; 1242 1243 //https://bugzilla.mozilla.org/show_bug.cgi?id=548397 can be null sometimes if iframe with display: none (firefox only!) 1244 return getCptStyle 1245 ? cptStyle != null 1246 ? cptStyle.getPropertyValue(styles) 1247 : el[LEXICON.s][styles] 1248 : cptStyle; 1249 } else { 1250 return this.each(function () { 1251 setCSSVal(this, styles, val); 1252 }); 1253 } 1254 } else { 1255 return this.each(function () { 1256 for (key in styles) setCSSVal(this, key, styles[key]); 1257 }); 1258 } 1259 }, 1260 1261 hasClass: function (className) { 1262 var elem, 1263 i = 0; 1264 var classNamePrepared = _strSpace + className + _strSpace; 1265 var classList; 1266 1267 while ((elem = this[i++])) { 1268 classList = elem.classList; 1269 if (classList && classList.contains(className)) return true; 1270 else if ( 1271 elem.nodeType === 1 && 1272 ( 1273 _strSpace + 1274 stripAndCollapse(elem.className + _strEmpty) + 1275 _strSpace 1276 ).indexOf(classNamePrepared) > -1 1277 ) 1278 return true; 1279 } 1280 1281 return false; 1282 }, 1283 1284 addClass: function (className) { 1285 var classes; 1286 var elem; 1287 var cur; 1288 var curValue; 1289 var clazz; 1290 var finalValue; 1291 var supportClassList; 1292 var elmClassList; 1293 var i = 0; 1294 var v = 0; 1295 1296 if (className) { 1297 classes = className.match(_rnothtmlwhite) || []; 1298 1299 while ((elem = this[i++])) { 1300 elmClassList = elem.classList; 1301 if (supportClassList === undefined) 1302 supportClassList = elmClassList !== undefined; 1303 1304 if (supportClassList) { 1305 while ((clazz = classes[v++])) elmClassList.add(clazz); 1306 } else { 1307 curValue = elem.className + _strEmpty; 1308 cur = 1309 elem.nodeType === 1 && 1310 _strSpace + stripAndCollapse(curValue) + _strSpace; 1311 1312 if (cur) { 1313 while ((clazz = classes[v++])) 1314 if (cur.indexOf(_strSpace + clazz + _strSpace) < 0) 1315 cur += clazz + _strSpace; 1316 1317 finalValue = stripAndCollapse(cur); 1318 if (curValue !== finalValue) elem.className = finalValue; 1319 } 1320 } 1321 } 1322 } 1323 1324 return this; 1325 }, 1326 1327 removeClass: function (className) { 1328 var classes; 1329 var elem; 1330 var cur; 1331 var curValue; 1332 var clazz; 1333 var finalValue; 1334 var supportClassList; 1335 var elmClassList; 1336 var i = 0; 1337 var v = 0; 1338 1339 if (className) { 1340 classes = className.match(_rnothtmlwhite) || []; 1341 1342 while ((elem = this[i++])) { 1343 elmClassList = elem.classList; 1344 if (supportClassList === undefined) 1345 supportClassList = elmClassList !== undefined; 1346 1347 if (supportClassList) { 1348 while ((clazz = classes[v++])) elmClassList.remove(clazz); 1349 } else { 1350 curValue = elem.className + _strEmpty; 1351 cur = 1352 elem.nodeType === 1 && 1353 _strSpace + stripAndCollapse(curValue) + _strSpace; 1354 1355 if (cur) { 1356 while ((clazz = classes[v++])) 1357 while (cur.indexOf(_strSpace + clazz + _strSpace) > -1) 1358 cur = cur.replace( 1359 _strSpace + clazz + _strSpace, 1360 _strSpace 1361 ); 1362 1363 finalValue = stripAndCollapse(cur); 1364 if (curValue !== finalValue) elem.className = finalValue; 1365 } 1366 } 1367 } 1368 } 1369 1370 return this; 1371 }, 1372 1373 hide: function () { 1374 return this.each(function () { 1375 this[LEXICON.s].display = "none"; 1376 }); 1377 }, 1378 1379 show: function () { 1380 return this.each(function () { 1381 this[LEXICON.s].display = "block"; 1382 }); 1383 }, 1384 1385 attr: function (attrName, value) { 1386 var i = 0; 1387 var el; 1388 while ((el = this[i++])) { 1389 if (value === undefined) return el.getAttribute(attrName); 1390 el.setAttribute(attrName, value); 1391 } 1392 return this; 1393 }, 1394 1395 removeAttr: function (attrName) { 1396 return this.each(function () { 1397 this.removeAttribute(attrName); 1398 }); 1399 }, 1400 1401 offset: function () { 1402 var el = this[0]; 1403 var rect = el[LEXICON.bCR](); 1404 var scrollLeft = 1405 window.pageXOffset || document.documentElement[_strScrollLeft]; 1406 var scrollTop = 1407 window.pageYOffset || document.documentElement[_strScrollTop]; 1408 return { 1409 top: rect.top + scrollTop, 1410 left: rect.left + scrollLeft, 1411 }; 1412 }, 1413 1414 position: function () { 1415 var el = this[0]; 1416 return { 1417 top: el.offsetTop, 1418 left: el.offsetLeft, 1419 }; 1420 }, 1421 1422 scrollLeft: function (value) { 1423 var i = 0; 1424 var el; 1425 while ((el = this[i++])) { 1426 if (value === undefined) return el[_strScrollLeft]; 1427 el[_strScrollLeft] = value; 1428 } 1429 return this; 1430 }, 1431 1432 scrollTop: function (value) { 1433 var i = 0; 1434 var el; 1435 while ((el = this[i++])) { 1436 if (value === undefined) return el[_strScrollTop]; 1437 el[_strScrollTop] = value; 1438 } 1439 return this; 1440 }, 1441 1442 val: function (value) { 1443 var el = this[0]; 1444 if (!value) return el.value; 1445 el.value = value; 1446 return this; 1447 }, 1448 1449 //DOM TRAVERSAL / FILTERING: 1450 1451 first: function () { 1452 return this.eq(0); 1453 }, 1454 1455 last: function () { 1456 return this.eq(-1); 1457 }, 1458 1459 eq: function (index) { 1460 return FakejQuery(this[index >= 0 ? index : this[LEXICON.l] + index]); 1461 }, 1462 1463 find: function (selector) { 1464 var children = []; 1465 var i; 1466 this.each(function () { 1467 var el = this; 1468 var ch = el.querySelectorAll(selector); 1469 for (i = 0; i < ch[LEXICON.l]; i++) children.push(ch[i]); 1470 }); 1471 return FakejQuery(children); 1472 }, 1473 1474 children: function (selector) { 1475 var children = []; 1476 var el; 1477 var ch; 1478 var i; 1479 1480 this.each(function () { 1481 ch = this.children; 1482 for (i = 0; i < ch[LEXICON.l]; i++) { 1483 el = ch[i]; 1484 if (selector) { 1485 if ( 1486 (el.matches && el.matches(selector)) || 1487 matches(el, selector) 1488 ) 1489 children.push(el); 1490 } else children.push(el); 1491 } 1492 }); 1493 return FakejQuery(children); 1494 }, 1495 1496 parent: function (selector) { 1497 var parents = []; 1498 var parent; 1499 this.each(function () { 1500 parent = this.parentNode; 1501 if (selector ? FakejQuery(parent).is(selector) : true) 1502 parents.push(parent); 1503 }); 1504 return FakejQuery(parents); 1505 }, 1506 1507 is: function (selector) { 1508 var el; 1509 var i; 1510 for (i = 0; i < this[LEXICON.l]; i++) { 1511 el = this[i]; 1512 if (selector === ":visible") return elementIsVisible(el); 1513 if (selector === ":hidden") return !elementIsVisible(el); 1514 if ((el.matches && el.matches(selector)) || matches(el, selector)) 1515 return true; 1516 } 1517 return false;
1518 }, 1519 1520 contents: function () { 1521 var contents = []; 1522 var childs; 1523 var i; 1524 1525 this.each(function () { 1526 childs = this.childNodes; 1527 for (i = 0; i < childs[LEXICON.l]; i++) contents.push(childs[i]); 1528 }); 1529 1530 return FakejQuery(contents); 1531 }, 1532 1533 each: function (callback) { 1534 return each(this, callback); 1535 }, 1536 1537 //ANIMATION: 1538 1539 animate: function (props, duration, easing, complete) { 1540 return this.each(function () { 1541 animate(this, props, duration, easing, complete); 1542 }); 1543 }, 1544 1545 stop: function (clearQ, jump) { 1546 return this.each(function () { 1547 stop(this, clearQ, jump); 1548 }); 1549 }, 1550 }; 1551 1552 extend(FakejQuery, { 1553 extend: extend, 1554 inArray: inArray, 1555 isEmptyObject: isEmptyObject, 1556 isPlainObject: isPlainObject, 1557 each: each, 1558 }); 1559 1560 return FakejQuery; 1561 })(); 1562 var INSTANCES = (function () { 1563 var _targets = []; 1564 var _instancePropertyString = "__overlayScrollbars__"; 1565 1566 /** 1567 * Register, unregister or get a certain (or all) instances. 1568 * Register: Pass the target and the instance. 1569 * Unregister: Pass the target and null. 1570 * Get Instance: Pass the target from which the instance shall be got. 1571 * Get Targets: Pass no arguments. 1572 * @param target The target to which the instance shall be registered / from which the instance shall be unregistered / the instance shall be got 1573 * @param instance The instance. 1574 * @returns {*|void} Returns the instance from the given target. 1575 */ 1576 return function (target, instance) { 1577 var argLen = arguments[LEXICON.l]; 1578 if (argLen < 1) { 1579 //return all targets 1580 return _targets; 1581 } else { 1582 if (instance) { 1583 //register instance 1584 target[_instancePropertyString] = instance; 1585 _targets.push(target); 1586 } else { 1587 var index = COMPATIBILITY.inA(target, _targets); 1588 if (index > -1) { 1589 if (argLen > 1) { 1590 //unregister instance 1591 delete target[_instancePropertyString]; 1592 _targets.splice(index, 1); 1593 } else { 1594 //get instance from target 1595 return _targets[index][_instancePropertyString]; 1596 } 1597 } 1598 } 1599 } 1600 }; 1601 })(); 1602 var PLUGIN = (function () { 1603 var _plugin; 1604 var _pluginsGlobals; 1605 var _pluginsAutoUpdateLoop; 1606 var _pluginsExtensions = []; 1607 var _pluginsOptions = (function () { 1608 var type = COMPATIBILITY.type; 1609 var possibleTemplateTypes = [ 1610 TYPES.b, //boolean 1611 TYPES.n, //number 1612 TYPES.s, //string 1613 TYPES.a, //array 1614 TYPES.o, //object 1615 TYPES.f, //function 1616 TYPES.z, //null 1617 ]; 1618 var restrictedStringsSplit = " "; 1619 var restrictedStringsPossibilitiesSplit = ":"; 1620 var classNameAllowedValues = [TYPES.z, TYPES.s]; 1621 var numberAllowedValues = TYPES.n; 1622 var booleanNullAllowedValues = [TYPES.z, TYPES.b]; 1623 var booleanTrueTemplate = [true, TYPES.b]; 1624 var booleanFalseTemplate = [false, TYPES.b]; 1625 var callbackTemplate = [null, [TYPES.z, TYPES.f]]; 1626 var updateOnLoadTemplate = [["img"], [TYPES.s, TYPES.a, TYPES.z]]; 1627 var inheritedAttrsTemplate = [ 1628 ["style", "class"], 1629 [TYPES.s, TYPES.a, TYPES.z], 1630 ]; 1631 var resizeAllowedValues = "n:none b:both h:horizontal v:vertical"; 1632 var overflowBehaviorAllowedValues = 1633 "v-h:visible-hidden v-s:visible-scroll s:scroll h:hidden"; 1634 var scrollbarsVisibilityAllowedValues = "v:visible h:hidden a:auto"; 1635 var scrollbarsAutoHideAllowedValues = "n:never s:scroll l:leave m:move"; 1636 var optionsDefaultsAndTemplate = { 1637 className: ["os-theme-dark", classNameAllowedValues], //null || string 1638 resize: ["none", resizeAllowedValues], //none || both || horizontal || vertical || n || b || h || v 1639 sizeAutoCapable: booleanTrueTemplate, //true || false 1640 clipAlways: booleanTrueTemplate, //true || false
1641 normalizeRTL: booleanTrueTemplate, //true || false 1642 paddingAbsolute: booleanFalseTemplate, //true || false 1643 autoUpdate: [null, booleanNullAllowedValues], //true || false || null 1644 autoUpdateInterval: [33, numberAllowedValues], //number 1645 updateOnLoad: updateOnLoadTemplate, //string || array || null 1646 nativeScrollbarsOverlaid: { 1647 showNativeScrollbars: booleanFalseTemplate, //true || false 1648 initialize: booleanTrueTemplate, //true || false 1649 }, 1650 overflowBehavior: { 1651 x: ["scroll", overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s 1652 y: ["scroll", overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s 1653 }, 1654 scrollbars: { 1655 visibility: ["auto", scrollbarsVisibilityAllowedValues], //visible || hidden || auto || v || h || a 1656 autoHide: ["never", scrollbarsAutoHideAllowedValues], //never || scroll || leave || move || n || s || l || m 1657 autoHideDelay: [800, numberAllowedValues], //number 1658 dragScrolling: booleanTrueTemplate, //true || false 1659 clickScrolling: booleanFalseTemplate, //true || false 1660 touchSupport: booleanTrueTemplate, //true || false 1661 snapHandle: booleanFalseTemplate, //true || false 1662 }, 1663 textarea: { 1664 dynWidth: booleanFalseTemplate, //true || false 1665 dynHeight: booleanFalseTemplate, //true || false 1666 inheritedAttrs: inheritedAttrsTemplate, //string || array || null 1667 }, 1668 callbacks: { 1669 onInitialized: callbackTemplate, //null || function 1670 onInitializationWithdrawn: callbackTemplate, //null || function 1671 onDestroyed: callbackTemplate, //null || function 1672 onScrollStart: callbackTemplate, //null || function 1673 onScroll: callbackTemplate, //null || function 1674 onScrollStop: callbackTemplate, //null || function 1675 onOverflowChanged: callbackTemplate, //null || function 1676 onOverflowAmountChanged: callbackTemplate, //null || function 1677 onDirectionChanged: callbackTemplate, //null || function 1678 onContentSizeChanged: callbackTemplate, //null || function 1679 onHostSizeChanged: callbackTemplate, //null || function 1680 onUpdated: callbackTemplate, //null || function 1681 }, 1682 }; 1683 var convert = function (template) { 1684 var recursive = function (obj) { 1685 var key; 1686 var val; 1687 var valType; 1688 for (key in obj) { 1689 if (!obj[LEXICON.hOP](key)) continue; 1690 val = obj[key]; 1691 valType = type(val); 1692 if (valType == TYPES.a) obj[key] = val[template ? 1 : 0]; 1693 else if (valType == TYPES.o) obj[key] = recursive(val); 1694 } 1695 return obj; 1696 }; 1697 return recursive( 1698 FRAMEWORK.extend(true, {}, optionsDefaultsAndTemplate) 1699 ); 1700 }; 1701 1702 return { 1703 _defaults: convert(), 1704 1705 _template: convert(true), 1706 1707 /** 1708 * Validates the passed object by the passed template. 1709 * @param obj The object which shall be validated. 1710 * @param template The template which defines the allowed values and types. 1711 * @param writeErrors True if errors shall be logged to the console. 1712 * @param diffObj If a object is passed then only valid differences to this object will be returned. 1713 * @returns {{}} A object which contains two objects called "default" and "prepared" which contains only the valid properties of the passed original object and discards not different values compared to the passed diffObj. 1714 */ 1715 _validate: function (obj, template, writeErrors, diffObj) { 1716 var validatedOptions = {}; 1717 var validatedOptionsPrepared = {}; 1718 var objectCopy = FRAMEWORK.extend(true, {}, obj); 1719 var inArray = FRAMEWORK.inArray; 1720 var isEmptyObj = FRAMEWORK.isEmptyObject; 1721 var checkObjectProps = function ( 1722 data, 1723 template, 1724 diffData, 1725 validatedOptions, 1726 validatedOptionsPrepared, 1727 prevPropName 1728 ) { 1729 for (var prop in template) { 1730 if (template[LEXICON.hOP](prop) && data[LEXICON.hOP](prop)) { 1731 var isValid = false;
vendor: 7,474 bytes, lines 1732-1899
1732 var isDiff = false; 1733 var templateValue = template[prop]; 1734 var templateValueType = type(templateValue); 1735 var templateIsComplex = templateValueType == TYPES.o; 1736 var templateTypes = !COMPATIBILITY.isA(templateValue) 1737 ? [templateValue] 1738 : templateValue; 1739 var dataDiffValue = diffData[prop]; 1740 var dataValue = data[prop]; 1741 var dataValueType = type(dataValue); 1742 var propPrefix = prevPropName ? prevPropName + "." : ""; 1743 var error = 1744 'The option "' + 1745 propPrefix + 1746 prop + 1747 "\" wasn't set, because"; 1748 var errorPossibleTypes = []; 1749 var errorRestrictedStrings = []; 1750 var restrictedStringValuesSplit; 1751 var restrictedStringValuesPossibilitiesSplit; 1752 var isRestrictedValue; 1753 var mainPossibility; 1754 var currType; 1755 var i; 1756 var v; 1757 var j; 1758 1759 dataDiffValue = 1760 dataDiffValue === undefined ? {} : dataDiffValue; 1761 1762 //if the template has a object as value, it means that the options are complex (verschachtelt) 1763 if (templateIsComplex && dataValueType == TYPES.o) { 1764 validatedOptions[prop] = {}; 1765 validatedOptionsPrepared[prop] = {}; 1766 checkObjectProps( 1767 dataValue, 1768 templateValue, 1769 dataDiffValue, 1770 validatedOptions[prop], 1771 validatedOptionsPrepared[prop], 1772 propPrefix + prop 1773 ); 1774 FRAMEWORK.each( 1775 [data, validatedOptions, validatedOptionsPrepared], 1776 function (index, value) { 1777 if (isEmptyObj(value[prop])) { 1778 delete value[prop]; 1779 } 1780 } 1781 ); 1782 } else if (!templateIsComplex) { 1783 for (i = 0; i < templateTypes[LEXICON.l]; i++) { 1784 currType = templateTypes[i]; 1785 templateValueType = type(currType); 1786 //if currtype is string and starts with restrictedStringPrefix and end with restrictedStringSuffix 1787 isRestrictedValue = 1788 templateValueType == TYPES.s && 1789 inArray(currType, possibleTemplateTypes) === -1; 1790 if (isRestrictedValue) { 1791 errorPossibleTypes.push(TYPES.s); 1792 1793 //split it into a array which contains all possible values for example: ["y:yes", "n:no", "m:maybe"] 1794 restrictedStringValuesSplit = currType.split( 1795 restrictedStringsSplit 1796 ); 1797 errorRestrictedStrings = errorRestrictedStrings.concat( 1798 restrictedStringValuesSplit 1799 ); 1800 for ( 1801 v = 0; 1802 v < restrictedStringValuesSplit[LEXICON.l]; 1803 v++ 1804 ) { 1805 //split the possible values into their possibiliteis for example: ["y", "yes"] -> the first is always the mainPossibility 1806 restrictedStringValuesPossibilitiesSplit = 1807 restrictedStringValuesSplit[v].split( 1808 restrictedStringsPossibilitiesSplit 1809 ); 1810 mainPossibility = 1811 restrictedStringValuesPossibilitiesSplit[0]; 1812 for ( 1813 j = 0; 1814 j < 1815 restrictedStringValuesPossibilitiesSplit[LEXICON.l]; 1816 j++ 1817 ) { 1818 //if any possibility matches with the dataValue, its valid 1819 if ( 1820 dataValue === 1821 restrictedStringValuesPossibilitiesSplit[j] 1822 ) { 1823 isValid = true; 1824 break; 1825 } 1826 } 1827 if (isValid) break; 1828 } 1829 } else { 1830 errorPossibleTypes.push(currType); 1831 1832 if (dataValueType === currType) { 1833 isValid = true; 1834 break; 1835 } 1836 } 1837 } 1838 1839 if (isValid) { 1840 isDiff = dataValue !== dataDiffValue; 1841 1842 if (isDiff) validatedOptions[prop] = dataValue; 1843 1844 if ( 1845 isRestrictedValue 1846 ? inArray( 1847 dataDiffValue, 1848 restrictedStringValuesPossibilitiesSplit 1849 ) < 0 1850 : isDiff 1851 ) 1852 validatedOptionsPrepared[prop] = isRestrictedValue 1853 ? mainPossibility 1854 : dataValue; 1855 } else if (writeErrors) { 1856 console.warn( 1857 error + 1858 " it doesn't accept the type [ " + 1859 dataValueType.toUpperCase() + 1860 ' ] with the value of "' + 1861 dataValue + 1862 '".\r\n' + 1863 "Accepted types are: [ " + 1864 errorPossibleTypes.join(", ").toUpperCase() + 1865 " ]." + 1866 (errorRestrictedStrings[length] > 0 1867 ? "\r\nValid strings are: [ " + 1868 errorRestrictedStrings 1869 .join(", ") 1870 .split(restrictedStringsPossibilitiesSplit) 1871 .join(", ") + 1872 " ]." 1873 : "") 1874 ); 1875 } 1876 delete data[prop]; 1877 } 1878 } 1879 } 1880 }; 1881 checkObjectProps( 1882 objectCopy, 1883 template, 1884 diffObj || {}, 1885 validatedOptions, 1886 validatedOptionsPrepared 1887 ); 1888 1889 //add values which aren't specified in the template to the finished validated object to prevent them from being discarded 1890 /* 1891 if(keepForeignProps) { 1892 FRAMEWORK.extend(true, validatedOptions, objectCopy); 1893 FRAMEWORK.extend(true, validatedOptionsPrepared, objectCopy); 1894 } 1895 */ 1896 1897 if (!isEmptyObj(objectCopy) && writeErrors) 1898 console.warn( 1899 "The following options are discarded due to invali
1899dity:\r\n" + 1900 window.JSON.stringify(objectCopy, null, 2) 1901 ); 1902 1903 return { 1904 _default: validatedOptions, 1905 _prepared: validatedOptionsPrepared, 1906 }; 1907 }, 1908 }; 1909 })(); 1910 1911 /** 1912 * Initializes the object which contains global information about the plugin and each instance of it. 1913 */ 1914 function initOverlayScrollbarsStatics() { 1915 if (!_pluginsGlobals) 1916 _pluginsGlobals = new OverlayScrollbarsGlobals( 1917 _pluginsOptions._defaults 1918 ); 1919 if (!_pluginsAutoUpdateLoop) 1920 _pluginsAutoUpdateLoop = new OverlayScrollbarsAutoUpdateLoop( 1921 _pluginsGlobals 1922 ); 1923 } 1924 1925 /** 1926 * The global object for the OverlayScrollbars objects. It contains resources which every OverlayScrollbars object needs. This object is initialized only once: if the first OverlayScrollbars object gets initialized. 1927 * @param defaultOptions 1928 * @constructor 1929 */ 1930 function OverlayScrollbarsGlobals(defaultOptions) { 1931 var _base = this; 1932 var strOverflow = "overflow"; 1933 var strHidden = "hidden"; 1934 var strScroll = "scroll"; 1935 var bodyElement = FRAMEWORK("body"); 1936 var scrollbarDummyElement = FRAMEWORK( 1937 '<div id="os-dummy-scrollbar-size"><div></div></div>' 1938 ); 1939 var scrollbarDummyElement0 = scrollbarDummyElement[0]; 1940 var dummyContainerChild = FRAMEWORK( 1941 scrollbarDummyElement.children("div").eq(0) 1942 ); 1943 1944 bodyElement.append(scrollbarDummyElement); 1945 scrollbarDummyElement.hide().show(); //fix IE8 bug (incorrect measuring) 1946 1947 var nativeScrollbarSize = calcNativeScrollbarSize( 1948 scrollbarDummyElement0 1949 ); 1950 var nativeScrollbarIsOverlaid = { 1951 x: nativeScrollbarSize.x === 0, 1952 y: nativeScrollbarSize.y === 0, 1953 }; 1954 var msie = (function () { 1955 var ua = window.navigator.userAgent; 1956 var strIndexOf = "indexOf"; 1957 var strSubString = "substring"; 1958 var msie = ua[strIndexOf]("MSIE "); 1959 var trident = ua[strIndexOf]("Trident/"); 1960 var edge = ua[strIndexOf]("Edge/"); 1961 var rv = ua[strIndexOf]("rv:"); 1962 var result; 1963 var parseIntFunc = parseInt; 1964 1965 // IE 10 or older => return version number 1966 if (msie > 0) 1967 result = parseIntFunc( 1968 ua[strSubString](msie + 5, ua[strIndexOf](".", msie)), 1969 10 1970 ); 1971 // IE 11 => return version number 1972 else if (trident > 0) 1973 result = parseIntFunc( 1974 ua[strSubString](rv + 3, ua[strIndexOf](".", rv)), 1975 10 1976 ); 1977 // Edge (IE 12+) => return version number 1978 else if (edge > 0) 1979 result = parseIntFunc( 1980 ua[strSubString](edge + 5, ua[strIndexOf](".", edge)), 1981 10 1982 ); 1983 1984 // other browser 1985 return result; 1986 })(); 1987 1988 FRAMEWORK.extend(_base, { 1989 defaultOptions: defaultOptions, 1990 msie: msie, 1991 autoUpdateLoop: false, 1992 autoUpdateRecommended: !COMPATIBILITY.mO(), 1993 nativeScrollbarSize: nativeScrollbarSize, 1994 nativeScrollbarIsOverlaid: nativeScrollbarIsOverlaid, 1995 nativeScrollbarStyling: (function () { 1996 var result = false;
1997 scrollbarDummyElement.addClass( 1998 "os-viewport-native-scrollbars-invisible" 1999 ); 2000 try { 2001 result = 2002 (scrollbarDummyElement.css("scrollbar-width") === "none" && 2003 (msie > 9 || !msie)) || 2004 window 2005 .getComputedStyle( 2006 scrollbarDummyElement0, 2007 "::-webkit-scrollbar" 2008 ) 2009 .getPropertyValue("display") === "none"; 2010 } catch (ex) {} 2011 2012 //fix opera bug: scrollbar styles will only appear if overflow value is scroll or auto during the activation of the style. 2013 //and set overflow to scroll 2014 //scrollbarDummyElement.css(strOverflow, strHidden).hide().css(strOverflow, strScroll).show(); 2015 //return (scrollbarDummyElement0[LEXICON.oH] - scrollbarDummyElement0[LEXICON.cH]) === 0 && (scrollbarDummyElement0[LEXICON.oW] - scrollbarDummyElement0[LEXICON.cW]) === 0; 2016 2017 return result; 2018 })(), 2019 overlayScrollbarDummySize: { x: 30, y: 30 }, 2020 cssCalc: VENDORS._cssPropertyValue("width", "calc", "(1px)") || null, 2021 restrictedMeasuring: (function () { 2022 //https://bugzilla.mozilla.org/show_bug.cgi?id=1439305 2023 //since 1.11.0 always false -> fixed via CSS (hopefully) 2024 scrollbarDummyElement.css(strOverflow, strHidden); 2025 var scrollSize = { 2026 w: scrollbarDummyElement0[LEXICON.sW], 2027 h: scrollbarDummyElement0[LEXICON.sH], 2028 }; 2029 scrollbarDummyElement.css(strOverflow, "visible"); 2030 var scrollSize2 = { 2031 w: scrollbarDummyElement0[LEXICON.sW], 2032 h: scrollbarDummyElement0[LEXICON.sH], 2033 }; 2034 return ( 2035 scrollSize.w - scrollSize2.w !== 0 || 2036 scrollSize.h - scrollSize2.h !== 0 2037 ); 2038 })(), 2039 rtlScrollBehavior: (function () { 2040 scrollbarDummyElement 2041 .css({ 2042 "overflow-y": strHidden, 2043 "overflow-x": strScroll, 2044 direction: "rtl", 2045 }) 2046 .scrollLeft(0); 2047 var dummyContainerOffset = scrollbarDummyElement.offset(); 2048 var dummyContainerChildOffset = dummyContainerChild.offset(); 2049 //https://github.com/KingSora/OverlayScrollbars/issues/187 2050 scrollbarDummyElement.scrollLeft(-999); 2051 var dummyContainerChildOffsetAfterScroll = 2052 dummyContainerChild.offset(); 2053 return { 2054 //origin direction = determines if the zero scroll position is on the left or right side 2055 //'i' means 'invert' (i === true means that the axis must be inverted to be correct) 2056 //true = on the left side 2057 //false = on the right side 2058 i: dummyContainerOffset.left === dummyContainerChildOffset.left, 2059 //negative = determines if the maximum scroll is positive or negative 2060 //'n' means 'negate' (n === true means that the axis must be negated to be correct) 2061 //true = negative 2062 //false = positive 2063 n: 2064 dummyContainerChildOffset.left !== 2065 dummyContainerChildOffsetAfterScroll.left, 2066 }; 2067 })(), 2068 supportTransform: !!VENDORS._cssProperty("transform"), 2069 supportTransition: !!VENDORS._cssProperty("transition"), 2070 supportPassiveEvents: (function () { 2071 var supportsPassive = false; 2072 try { 2073 window.addEventListener( 2074 "test", 2075 null, 2076 Object.defineProperty({}, "passive", { 2077 get: function () { 2078 supportsPassive = true; 2079 }, 2080 }) 2081 ); 2082 } catch (e) {} 2083 return supportsPassive; 2084 })(), 2085 supportResizeObserver: !!COMPATIBILITY.rO(), 2086 supportMutationObserver: !!COMPATIBILITY.mO(), 2087 }); 2088 2089 scrollbarDummyElement.removeAttr(LEXICON.s).remove(); 2090 2091 //Catch zoom event: 2092 (function () { 2093 if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) 2094 return; 2095 2096 var abs = MATH.abs;
vendor: 17,173 bytes, lines 2097-2528
2097 var windowWidth = COMPATIBILITY.wW(); 2098 var windowHeight = COMPATIBILITY.wH(); 2099 var windowDpr = getWindowDPR(); 2100 var onResize = function () { 2101 if (INSTANCES().length > 0) { 2102 var newW = COMPATIBILITY.wW(); 2103 var newH = COMPATIBILITY.wH(); 2104 var deltaW = newW - windowWidth; 2105 var deltaH = newH - windowHeight; 2106 2107 if (deltaW === 0 && deltaH === 0) return; 2108 2109 var deltaWRatio = MATH.round(newW / (windowWidth / 100.0)); 2110 var deltaHRatio = MATH.round(newH / (windowHeight / 100.0)); 2111 var absDeltaW = abs(deltaW); 2112 var absDeltaH = abs(deltaH); 2113 var absDeltaWRatio = abs(deltaWRatio); 2114 var absDeltaHRatio = abs(deltaHRatio); 2115 var newDPR = getWindowDPR(); 2116 2117 var deltaIsBigger = absDeltaW > 2 && absDeltaH > 2; 2118 var difference = !differenceIsBiggerThanOne( 2119 absDeltaWRatio, 2120 absDeltaHRatio 2121 ); 2122 var dprChanged = newDPR !== windowDpr && windowDpr > 0; 2123 var isZoom = deltaIsBigger && difference && dprChanged; 2124 var oldScrollbarSize = _base.nativeScrollbarSize; 2125 var newScrollbarSize; 2126 2127 if (isZoom) { 2128 bodyElement.append(scrollbarDummyElement); 2129 newScrollbarSize = _base.nativeScrollbarSize = 2130 calcNativeScrollbarSize(scrollbarDummyElement[0]); 2131 scrollbarDummyElement.remove(); 2132 if ( 2133 oldScrollbarSize.x !== newScrollbarSize.x || 2134 oldScrollbarSize.y !== newScrollbarSize.y 2135 ) { 2136 FRAMEWORK.each(INSTANCES(), function () { 2137 if (INSTANCES(this)) INSTANCES(this).update("zoom"); 2138 }); 2139 } 2140 } 2141 2142 windowWidth = newW; 2143 windowHeight = newH; 2144 windowDpr = newDPR; 2145 } 2146 }; 2147 2148 function differenceIsBiggerThanOne(valOne, valTwo) { 2149 var absValOne = abs(valOne); 2150 var absValTwo = abs(valTwo); 2151 return !( 2152 absValOne === absValTwo || 2153 absValOne + 1 === absValTwo || 2154 absValOne - 1 === absValTwo 2155 ); 2156 } 2157 2158 function getWindowDPR() { 2159 var dDPI = window.screen.deviceXDPI || 0; 2160 var sDPI = window.screen.logicalXDPI || 1; 2161 return window.devicePixelRatio || dDPI / sDPI; 2162 } 2163 2164 FRAMEWORK(window).on("resize", onResize); 2165 })(); 2166 2167 function calcNativeScrollbarSize(measureElement) { 2168 return { 2169 x: measureElement[LEXICON.oH] - measureElement[LEXICON.cH], 2170 y: measureElement[LEXICON.oW] - measureElement[LEXICON.cW], 2171 }; 2172 } 2173 } 2174 2175 /** 2176 * The object which manages the auto update loop for all OverlayScrollbars objects. This object is initialized only once: if the first OverlayScrollbars object gets initialized. 2177 * @constructor 2178 */ 2179 function OverlayScrollbarsAutoUpdateLoop(globals) { 2180 var _base = this; 2181 var _inArray = FRAMEWORK.inArray; 2182 var _getNow = COMPATIBILITY.now; 2183 var _strAutoUpdate = "autoUpdate"; 2184 var _strAutoUpdateInterval = _strAutoUpdate + "Interval"; 2185 var _strLength = LEXICON.l; 2186 var _loopingInstances = []; 2187 var _loopingInstancesIntervalCache = []; 2188 var _loopIsActive = false; 2189 var _loopIntervalDefault = 33; 2190 var _loopInterval = _loopIntervalDefault; 2191 var _loopTimeOld = _getNow(); 2192 var _loopID; 2193 2194 /** 2195 * The auto update loop which will run every 50 milliseconds or less if the update interval of a instance is lower than 50 milliseconds. 2196 */ 2197 var loop = function () { 2198 if (_loopingInstances[_strLength] > 0 && _loopIsActive) { 2199 _loopID = COMPATIBILITY.rAF()(function () { 2200 loop(); 2201 }); 2202 var timeNew = _getNow(); 2203 var timeDelta = timeNew - _loopTimeOld; 2204 var lowestInterval; 2205 var instance; 2206 var instanceOptions; 2207 var instanceAutoUpdateAllowed; 2208 var instanceAutoUpdateInterval; 2209 var now; 2210 2211 if (timeDelta > _loopInterval) { 2212 _loopTimeOld = timeNew - (timeDelta % _loopInterval); 2213 lowestInterval = _loopIntervalDefault; 2214 for (var i = 0; i < _loopingInstances[_strLength]; i++) { 2215 instance = _loopingInstances[i]; 2216 if (instance !== undefined) { 2217 instanceOptions = instance.options(); 2218 instanceAutoUpdateAllowed = instanceOptions[_strAutoUpdate]; 2219 instanceAutoUpdateInterval = MATH.max( 2220 1, 2221 instanceOptions[_strAutoUpdateInterval] 2222 ); 2223 now = _getNow(); 2224 2225 if ( 2226 (instanceAutoUpdateAllowed === true || 2227 instanceAutoUpdateAllowed === null) && 2228 now - _loopingInstancesIntervalCache[i] > 2229 instanceAutoUpdateInterval 2230 ) { 2231 instance.update("auto"); 2232 _loopingInstancesIntervalCache[i] = new Date( 2233 (now += instanceAutoUpdateInterval) 2234 ); 2235 } 2236 2237 lowestInterval = MATH.max( 2238 1, 2239 MATH.min(lowestInterval, instanceAutoUpdateInterval) 2240 ); 2241 } 2242 } 2243 _loopInterval = lowestInterval; 2244 } 2245 } else { 2246 _loopInterval = _loopIntervalDefault; 2247 } 2248 }; 2249 2250 /** 2251 * Add OverlayScrollbars instance to the auto update loop. Only successful if the instance isn't already added. 2252 * @param instance The instance which shall be updated in a loop automatically. 2253 */ 2254 _base.add = function (instance) { 2255 if (_inArray(instance, _loopingInstances) === -1) { 2256 _loopingInstances.push(instance); 2257 _loopingInstancesIntervalCache.push(_getNow()); 2258 if (_loopingInstances[_strLength] > 0 && !_loopIsActive) { 2259 _loopIsActive = true; 2260 globals.autoUpdateLoop = _loopIsActive; 2261 loop(); 2262 } 2263 } 2264 }; 2265 2266 /** 2267 * Remove OverlayScrollbars instance from the auto update loop. Only successful if the instance was added before. 2268 * @param instance The instance which shall be updated in a loop automatically. 2269 */ 2270 _base.remove = function (instance) { 2271 var index = _inArray(instance, _loopingInstances); 2272 if (index > -1) { 2273 //remove from loopingInstances list 2274 _loopingInstancesIntervalCache.splice(index, 1); 2275 _loopingInstances.splice(index, 1); 2276 2277 //correct update loop behavior 2278 if (_loopingInstances[_strLength] === 0 && _loopIsActive) { 2279 _loopIsActive = false; 2280 globals.autoUpdateLoop = _loopIsActive; 2281 if (_loopID !== undefined) { 2282 COMPATIBILITY.cAF()(_loopID); 2283 _loopID = -1; 2284 } 2285 } 2286 } 2287 }; 2288 } 2289 2290 /** 2291 * A object which manages the scrollbars visibility of the target element. 2292 * @param pluginTargetElement The element from which the scrollbars shall be hidden. 2293 * @param options The custom options. 2294 * @param extensions The custom extensions. 2295 * @param globals 2296 * @param autoUpdateLoop 2297 * @returns {*} 2298 * @constructor 2299 */ 2300 function OverlayScrollbarsInstance( 2301 pluginTargetElement, 2302 options, 2303 extensions, 2304 globals, 2305 autoUpdateLoop 2306 ) { 2307 //shortcuts 2308 var type = COMPATIBILITY.type; 2309 var inArray = FRAMEWORK.inArray; 2310 var each = FRAMEWORK.each; 2311 2312 //make correct instanceof 2313 var _base = new _plugin(); 2314 var _frameworkProto = FRAMEWORK[LEXICON.p]; 2315 2316 //if passed element is no HTML element: skip and return 2317 if (!isHTMLElement(pluginTargetElement)) return; 2318 2319 //if passed element is already initialized: set passed options if there are any and return its instance 2320 if (INSTANCES(pluginTargetElement)) { 2321 var inst = INSTANCES(pluginTargetElement); 2322 inst.options(options); 2323 return inst; 2324 } 2325 2326 //globals: 2327 var _nativeScrollbarIsOverlaid; 2328 var _overlayScrollbarDummySize; 2329 var _rtlScrollBehavior; 2330 var _autoUpdateRecommended; 2331 var _msieVersion; 2332 var _nativeScrollbarStyling; 2333 var _cssCalc; 2334 var _nativeScrollbarSize; 2335 var _supportTransition; 2336 var _supportTransform; 2337 var _supportPassiveEvents; 2338 var _supportResizeObserver; 2339 var _supportMutationObserver; 2340 var _restrictedMeasuring; 2341 2342 //general readonly: 2343 var _initialized; 2344 var _destroyed; 2345 var _isTextarea; 2346 var _isBody; 2347 var _documentMixed; 2348 var _domExists; 2349 2350 //general: 2351 var _isBorderBox; 2352 var _sizeAutoObserverAdded; 2353 var _paddingX; 2354 var _paddingY; 2355 var _borderX; 2356 var _borderY; 2357 var _marginX; 2358 var _marginY; 2359 var _isRTL; 2360 var _sleeping; 2361 var _contentBorderSize = {}; 2362 var _scrollHorizontalInfo = {}; 2363 var _scrollVerticalInfo = {}; 2364 var _viewportSize = {}; 2365 var _nativeScrollbarMinSize = {}; 2366 2367 //naming: 2368 var _strMinusHidden = "-hidden"; 2369 var _strMarginMinus = "margin-"; 2370 var _strPaddingMinus = "padding-"; 2371 var _strBorderMinus = "border-"; 2372 var _strTop = "top"; 2373 var _strRight = "right"; 2374 var _strBottom = "bottom"; 2375 var _strLeft = "left"; 2376 var _strMinMinus = "min-"; 2377 var _strMaxMinus = "max-"; 2378 var _strWidth = "width"; 2379 var _strHeight = "height"; 2380 var _strFloat = "float"; 2381 var _strEmpty = ""; 2382 var _strAuto = "auto"; 2383 var _strSync = "sync"; 2384 var _strScroll = "scroll"; 2385 var _strHundredPercent = "100%"; 2386 var _strX = "x"; 2387 var _strY = "y"; 2388 var _strDot = "."; 2389 var _strSpace = " "; 2390 var _strScrollbar = "scrollbar"; 2391 var _strMinusHorizontal = "-horizontal"; 2392 var _strMinusVertical = "-vertical"; 2393 var _strScrollLeft = _strScroll + "Left"; 2394 var _strScrollTop = _strScroll + "Top"; 2395 var _strMouseTouchDownEvent = "mousedown touchstart"; 2396 var _strMouseTouchUpEvent = "mouseup touchend touchcancel"; 2397 var _strMouseTouchMoveEvent = "mousemove touchmove"; 2398 var _strMouseEnter = "mouseenter"; 2399 var _strMouseLeave = "mouseleave"; 2400 var _strKeyDownEvent = "keydown"; 2401 var _strKeyUpEvent = "keyup"; 2402 var _strSelectStartEvent = "selectstart"; 2403 var _strTransitionEndEvent = 2404 "transitionend webkitTransitionEnd oTransitionEnd"; 2405 var _strResizeObserverProperty = "__overlayScrollbarsRO__"; 2406 2407 //class names: 2408 var _cassNamesPrefix = "os-"; 2409 var _classNameHTMLElement = _cassNamesPrefix + "html"; 2410 var _classNameHostElement = _cassNamesPrefix + "host"; 2411 var _classNameHostElementForeign = _classNameHostElement + "-foreign"; 2412 var _classNameHostTextareaElement = _classNameHostElement + "-textarea"; 2413 var _classNameHostScrollbarHorizontalHidden = 2414 _classNameHostElement + 2415 "-" + 2416 _strScrollbar + 2417 _strMinusHorizontal + 2418 _strMinusHidden; 2419 var _classNameHostScrollbarVerticalHidden = 2420 _classNameHostElement + 2421 "-" + 2422 _strScrollbar + 2423 _strMinusVertical + 2424 _strMinusHidden; 2425 var _classNameHostTransition = _classNameHostElement + "-transition"; 2426 var _classNameHostRTL = _classNameHostElement + "-rtl"; 2427 var _classNameHostResizeDisabled = 2428 _classNameHostElement + "-resize-disabled"; 2429 var _classNameHostScrolling = _classNameHostElement + "-scrolling"; 2430 var _classNameHostOverflow = _classNameHostElement + "-overflow"; 2431 var _classNameHostOverflow = _classNameHostElement + "-overflow"; 2432 var _classNameHostOverflowX = _classNameHostOverflow + "-x"; 2433 var _classNameHostOverflowY = _classNameHostOverflow + "-y"; 2434 var _classNameTextareaElement = _cassNamesPrefix + "textarea"; 2435 var _classNameTextareaCoverElement = 2436 _classNameTextareaElement + "-cover"; 2437 var _classNamePaddingElement = _cassNamesPrefix + "padding"; 2438 var _classNameViewportElement = _cassNamesPrefix + "viewport"; 2439 var _classNameViewportNativeScrollbarsInvisible = 2440 _classNameViewportElement + "-native-scrollbars-invisible"; 2441 var _classNameViewportNativeScrollbarsOverlaid = 2442 _classNameViewportElement + "-native-scrollbars-overlaid"; 2443 var _classNameContentElement = _cassNamesPrefix + "content"; 2444 var _classNameContentArrangeElement = 2445 _cassNamesPrefix + "content-arrange"; 2446 var _classNameContentGlueElement = _cassNamesPrefix + "content-glue"; 2447 var _classNameSizeAutoObserverElement = 2448 _cassNamesPrefix + "size-auto-observer"; 2449 var _classNameResizeObserverElement = 2450 _cassNamesPrefix + "resize-observer"; 2451 var _classNameResizeObserverItemElement = 2452 _cassNamesPrefix + "resize-observer-item"; 2453 var _classNameResizeObserverItemFinalElement = 2454 _classNameResizeObserverItemElement + "-final"; 2455 var _classNameTextInherit = _cassNamesPrefix + "text-inherit"; 2456 var _classNameScrollbar = _cassNamesPrefix + _strScrollbar; 2457 var _classNameScrollbarTrack = _classNameScrollbar + "-track"; 2458 var _classNameScrollbarTrackOff = _classNameScrollbarTrack + "-off"; 2459 var _classNameScrollbarHandle = _classNameScrollbar + "-handle"; 2460 var _classNameScrollbarHandleOff = _classNameScrollbarHandle + "-off"; 2461 var _classNameScrollbarUnusable = _classNameScrollbar + "-unusable"; 2462 var _classNameScrollbarAutoHidden = 2463 _classNameScrollbar + "-" + _strAuto + _strMinusHidden; 2464 var _classNameScrollbarCorner = _classNameScrollbar + "-corner"; 2465 var _classNameScrollbarCornerResize = 2466 _classNameScrollbarCorner + "-resize"; 2467 var _classNameScrollbarCornerResizeB = 2468 _classNameScrollbarCornerResize + "-both"; 2469 var _classNameScrollbarCornerResizeH = 2470 _classNameScrollbarCornerResize + _strMinusHorizontal; 2471 var _classNameScrollbarCornerResizeV = 2472 _classNameScrollbarCornerResize + _strMinusVertical; 2473 var _classNameScrollbarHorizontal = 2474 _classNameScrollbar + _strMinusHorizontal; 2475 var _classNameScrollbarVertical = 2476 _classNameScrollbar + _strMinusVertical; 2477 var _classNameDragging = _cassNamesPrefix + "dragging"; 2478 var _classNameThemeNone = _cassNamesPrefix + "theme-none"; 2479 var _classNamesDynamicDestroy = [ 2480 _classNameViewportNativeScrollbarsInvisible, 2481 _classNameViewportNativeScrollbarsOverlaid, 2482 _classNameScrollbarTrackOff, 2483 _classNameScrollbarHandleOff, 2484 _classNameScrollbarUnusable, 2485 _classNameScrollbarAutoHidden, 2486 _classNameScrollbarCornerResize, 2487 _classNameScrollbarCornerResizeB, 2488 _classNameScrollbarCornerResizeH, 2489 _classNameScrollbarCornerResizeV, 2490 _classNameDragging, 2491 ].join(_strSpace); 2492 2493 //callbacks: 2494 var _callbacksInitQeueue = []; 2495 2496 //attrs viewport shall inherit from target 2497 var _viewportAttrsFromTarget = [LEXICON.ti]; 2498 2499 //options: 2500 var _defaultOptions; 2501 var _currentOptions; 2502 var _currentPreparedOptions; 2503 2504 //extensions: 2505 var _extensions = {}; 2506 var _extensionsPrivateMethods = "added removed on contract"; 2507 2508 //update 2509 var _lastUpdateTime; 2510 var _swallowedUpdateHints = {}; 2511 var _swallowedUpdateTimeout; 2512 var _swallowUpdateLag = 42; 2513 var _updateOnLoadEventName = "load"; 2514 var _updateOnLoadElms = []; 2515 2516 //DOM elements: 2517 var _windowElement; 2518 var _documentElement; 2519 var _htmlElement; 2520 var _bodyElement; 2521 var _targetElement; //the target element of this OverlayScrollbars object 2522 var _hostElement; //the host element of this OverlayScrollbars object -> may be the same as targetElement 2523 var _sizeAutoObserverElement; //observes size auto changes 2524 var _sizeObserverElement; //observes size and padding changes 2525 var _paddingElement; //manages the padding 2526 var _viewportElement; //is the viewport of our scrollbar model 2527 var _contentElement; //the element which holds the content 2528 var _contentArrangeElement;
2528 //is needed for correct sizing of the content element (only if native scrollbars are overlays) 2529 var _contentGlueElement; //has always the size of the content element 2530 var _textareaCoverElement; //only applied if target is a textarea element. Used for correct size calculation and for prevention of uncontrolled scrolling 2531 var _scrollbarCornerElement; 2532 var _scrollbarHorizontalElement; 2533 var _scrollbarHorizontalTrackElement; 2534 var _scrollbarHorizontalHandleElement; 2535 var _scrollbarVerticalElement; 2536 var _scrollbarVerticalTrackElement; 2537 var _scrollbarVerticalHandleElement; 2538 var _windowElementNative; 2539 var _documentElementNative; 2540 var _targetElementNative; 2541 var _hostElementNative; 2542 var _sizeAutoObserverElementNative; 2543 var _sizeObserverElementNative; 2544 var _paddingElementNative; 2545 var _viewportElementNative; 2546 var _contentElementNative; 2547 2548 //Cache: 2549 var _hostSizeCache; 2550 var _contentScrollSizeCache; 2551 var _arrangeContentSizeCache; 2552 var _hasOverflowCache; 2553 var _hideOverflowCache; 2554 var _widthAutoCache; 2555 var _heightAutoCache; 2556 var _cssBoxSizingCache; 2557 var _cssPaddingCache; 2558 var _cssBorderCache; 2559 var _cssMarginCache; 2560 var _cssDirectionCache; 2561 var _cssDirectionDetectedCache; 2562 var _paddingAbsoluteCache; 2563 var _clipAlwaysCache; 2564 var _contentGlueSizeCache; 2565 var _overflowBehaviorCache; 2566 var _overflowAmountCache; 2567 var _ignoreOverlayScrollbarHidingCache; 2568 var _autoUpdateCache; 2569 var _sizeAutoCapableCache; 2570 var _contentElementScrollSizeChangeDetectedCache; 2571 var _hostElementSizeChangeDetectedCache; 2572 var _scrollbarsVisibilityCache; 2573 var _scrollbarsAutoHideCache; 2574 var _scrollbarsClickScrollingCache; 2575 var _scrollbarsDragScrollingCache; 2576 var _resizeCache; 2577 var _normalizeRTLCache; 2578 var _classNameCache; 2579 var _oldClassName; 2580 var _textareaAutoWrappingCache; 2581 var _textareaInfoCache; 2582 var _textareaSizeCache; 2583 var _textareaDynHeightCache; 2584 var _textareaDynWidthCache; 2585 var _bodyMinSizeCache; 2586 var _updateAutoCache = {}; 2587 2588 //MutationObserver: 2589 var _mutationObserverHost; 2590 var _mutationObserverContent; 2591 var _mutationObserverHostCallback; 2592 var _mutationObserverContentCallback; 2593 var _mutationObserversConnected; 2594 var _mutationObserverAttrsTextarea = ["wrap", "cols", "rows"]; 2595 var _mutationObserverAttrsHost = [ 2596 LEXICON.i, 2597 LEXICON.c, 2598 LEXICON.s, 2599 "open", 2600 ].concat(_viewportAttrsFromTarget); 2601 2602 //events: 2603 var _destroyEvents = []; 2604 2605 //textarea: 2606 var _textareaHasFocus; 2607 2608 //scrollbars: 2609 var _scrollbarsAutoHideTimeoutId; 2610 var _scrollbarsAutoHideMoveTimeoutId; 2611 var _scrollbarsAutoHideDelay; 2612 var _scrollbarsAutoHideNever; 2613 var _scrollbarsAutoHideScroll; 2614 var _scrollbarsAutoHideMove; 2615 var _scrollbarsAutoHideLeave; 2616 var _scrollbarsHandleHovered; 2617 var _scrollbarsHandlesDefineScrollPos; 2618 2619 //resize 2620 var _resizeNone; 2621 var _resizeBoth; 2622 var _resizeHorizontal; 2623 var _resizeVertical; 2624 2625 //==== Event Listener ====// 2626 2627 /** 2628 * Adds or removes a event listener from the given element. 2629 * @param element The element to which the event listener shall be applied or removed. 2630 * @param eventNames The name(s) of the events. 2631 * @param listener The method which shall be called. 2632 * @param remove True if the handler shall be removed, false or undefined if the handler shall be added. 2633 * @param passiveOrOptions The options for the event. 2634 */ 2635 function setupResponsiveEventListener( 2636 element, 2637 eventNames, 2638 listener, 2639 remove, 2640 passiveOrOptions 2641 ) { 2642 var collected = 2643 COMPATIBILITY.isA(eventNames) && COMPATIBILITY.isA(listener); 2644 var method = remove ? "removeEventListener" : "addEventListener"; 2645 var onOff = remove ? "off" : "on"; 2646 var events = collected ? false : eventNames.split(_strSpace); 2647 var i = 0; 2648 2649 var passiveOrOptionsIsObj = FRAMEWORK.isPlainObject(passiveOrOptions); 2650 var passive = 2651 (_supportPassiveEvents && 2652 (passiveOrOptionsIsObj 2653 ? passiveOrOptions._passive 2654 : passiveOrOptions)) || 2655 false; 2656 var capture = 2657 passiveOrOptionsIsObj && (passiveOrOptions._capture || false); 2658 var nativeParam = _supportPassiveEvents 2659 ? { 2660 passive: passive, 2661 capture: capture, 2662 } 2663 : capture; 2664 2665 if (collected) { 2666 for (; i < eventNames[LEXICON.l]; i++) 2667 setupResponsiveEventListener( 2668 element, 2669 eventNames[i], 2670 listener[i], 2671 remove, 2672 passiveOrOptions 2673 ); 2674 } else { 2675 for (; i < events[LEXICON.l]; i++) { 2676 if (_supportPassiveEvents) { 2677 element[0][method](events[i], listener, nativeParam); 2678 } else { 2679 element[onOff](events[i], listener); 2680 } 2681 } 2682 } 2683 } 2684 2685 function addDestroyEventListener( 2686 element, 2687 eventNames, 2688 listener, 2689 passive 2690 ) { 2691 setupResponsiveEventListener( 2692 element, 2693 eventNames, 2694 listener, 2695 false, 2696 passive 2697 ); 2698 _destroyEvents.push( 2699 COMPATIBILITY.bind( 2700 setupResponsiveEventListener, 2701 0, 2702 element, 2703 eventNames, 2704 listener, 2705 true, 2706 passive 2707 ) 2708 ); 2709 } 2710 2711 //==== Resize Observer ====// 2712 2713 /** 2714 * Adds or removes a resize observer from the given element. 2715 * @param targetElement The element to which the resize observer shall be added or removed. 2716 * @param onElementResizedCallback The callback which is fired every time the resize observer registers a size change or false / undefined if the resizeObserver shall be removed. 2717 */ 2718 function setupResizeObserver(targetElement, onElementResizedCallback) { 2719 if (targetElement) { 2720 var resizeObserver = COMPATIBILITY.rO(); 2721 var strAnimationStartEvent = 2722 "animationstart mozAnimationStart webkitAnimationStart MSAnimationStart"; 2723 var strChildNodes = "childNodes"; 2724 var constScroll = 3333333; 2725 var callback = function () { 2726 targetElement[_strScrollTop](constScroll)[_strScrollLeft]( 2727 _isRTL 2728 ? _rtlScrollBehavior.n 2729 ? -constScroll 2730 : _rtlScrollBehavior.i 2731 ? 0 2732 : constScroll 2733 : constScroll 2734 ); 2735 onElementResizedCallback(); 2736 }; 2737 //add resize observer: 2738 if (onElementResizedCallback) { 2739 if (_supportResizeObserver) { 2740 var element = targetElement 2741 .addClass("observed") 2742 .append(generateDiv(_classNameResizeObserverElement)) 2743 .contents()[0]; 2744 var observer = (element[_strResizeObserverProperty] = 2745 new resizeObserver(callback)); 2746 observer.observe(element); 2747 } else { 2748 if (_msieVersion > 9 || !_autoUpdateRecommended) {
2749 targetElement.prepend( 2750 generateDiv( 2751 _classNameResizeObserverElement, 2752 generateDiv( 2753 { c: _classNameResizeObserverItemElement, dir: "ltr" }, 2754 generateDiv( 2755 _classNameResizeObserverItemElement, 2756 generateDiv(_classNameResizeObserverItemFinalElement) 2757 ) + 2758 generateDiv( 2759 _classNameResizeObserverItemElement, 2760 generateDiv({ 2761 c: _classNameResizeObserverItemFinalElement, 2762 style: "width: 200%; height: 200%", 2763 }) 2764 ) 2765 ) 2766 ) 2767 ); 2768 2769 var observerElement = 2770 targetElement[0][strChildNodes][0][strChildNodes][0]; 2771 var shrinkElement = FRAMEWORK( 2772 observerElement[strChildNodes][1] 2773 ); 2774 var expandElement = FRAMEWORK( 2775 observerElement[strChildNodes][0] 2776 ); 2777 var expandElementChild = FRAMEWORK( 2778 expandElement[0][strChildNodes][0] 2779 ); 2780 var widthCache = observerElement[LEXICON.oW]; 2781 var heightCache = observerElement[LEXICON.oH]; 2782 var isDirty; 2783 var rAFId; 2784 var currWidth; 2785 var currHeight; 2786 var factor = 2; 2787 var nativeScrollbarSize = globals.nativeScrollbarSize; //care don't make changes to this object!!! 2788 var reset = function () { 2789 /* 2790 var sizeResetWidth = observerElement[LEXICON.oW] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; 2791 var sizeResetHeight = observerElement[LEXICON.oH] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; 2792 var expandChildCSS = {}; 2793 expandChildCSS[_strWidth] = sizeResetWidth; 2794 expandChildCSS[_strHeight] = sizeResetHeight; 2795 expandElementChild.css(expandChildCSS); 2796 2797 2798 expandElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); 2799 shrinkElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); 2800 */ 2801 expandElement[_strScrollLeft](constScroll)[_strScrollTop]( 2802 constScroll 2803 ); 2804 shrinkElement[_strScrollLeft](constScroll)[_strScrollTop]( 2805 constScroll 2806 ); 2807 }; 2808 var onResized = function () { 2809 rAFId = 0; 2810 if (!isDirty) return; 2811 2812 widthCache = currWidth; 2813 heightCache = currHeight; 2814 callback(); 2815 }; 2816 var onScroll = function (event) { 2817 currWidth = observerElement[LEXICON.oW]; 2818 currHeight = observerElement[LEXICON.oH]; 2819 isDirty = 2820 currWidth != widthCache || currHeight != heightCache; 2821 2822 if (event && isDirty && !rAFId) { 2823 COMPATIBILITY.cAF()(rAFId); 2824 rAFId = COMPATIBILITY.rAF()(onResized); 2825 } else if (!event) onResized(); 2826 2827 reset(); 2828 if (event) { 2829 COMPATIBILITY.prvD(event); 2830 COMPATIBILITY.stpP(event); 2831 } 2832 return false;
2833 }; 2834 var expandChildCSS = {}; 2835 var observerElementCSS = {}; 2836 2837 setTopRightBottomLeft(observerElementCSS, _strEmpty, [ 2838 -((nativeScrollbarSize.y + 1) * factor), 2839 nativeScrollbarSize.x * -factor, 2840 nativeScrollbarSize.y * -factor, 2841 -((nativeScrollbarSize.x + 1) * factor), 2842 ]); 2843 2844 FRAMEWORK(observerElement).css(observerElementCSS); 2845 expandElement.on(_strScroll, onScroll); 2846 shrinkElement.on(_strScroll, onScroll); 2847 targetElement.on(strAnimationStartEvent, function () { 2848 onScroll(false); 2849 }); 2850 //lets assume that the divs will never be that large and a constant value is enough 2851 expandChildCSS[_strWidth] = constScroll; 2852 expandChildCSS[_strHeight] = constScroll; 2853 expandElementChild.css(expandChildCSS); 2854 2855 reset(); 2856 } else { 2857 var attachEvent = _documentElementNative.attachEvent; 2858 var isIE = _msieVersion !== undefined; 2859 if (attachEvent) { 2860 targetElement.prepend( 2861 generateDiv(_classNameResizeObserverElement) 2862 ); 2863 findFirst( 2864 targetElement, 2865 _strDot + _classNameResizeObserverElement 2866 )[0].attachEvent("onresize", callback); 2867 } else { 2868 var obj = _documentElementNative.createElement(TYPES.o); 2869 obj.setAttribute(LEXICON.ti, "-1"); 2870 obj.setAttribute( 2871 LEXICON.c, 2872 _classNameResizeObserverElement 2873 ); 2874 obj.onload = function () { 2875 var wnd = this.contentDocument.defaultView; 2876 wnd.addEventListener("resize", callback); 2877 wnd.document.documentElement.style.display = "none"; 2878 }; 2879 obj.type = "text/html"; 2880 if (isIE) targetElement.prepend(obj); 2881 obj.data = "about:blank"; 2882 if (!isIE) targetElement.prepend(obj); 2883 targetElement.on(strAnimationStartEvent, callback); 2884 } 2885 } 2886 } 2887 2888 if (targetElement[0] === _sizeObserverElementNative) { 2889 var directionChanged = function () { 2890 var dir = _hostElement.css("direction"); 2891 var css = {}; 2892 var scrollLeftValue = 0; 2893 var result = false;
vendor: 9,470 bytes, lines 2894-3131
2894 if (dir !== _cssDirectionDetectedCache) { 2895 if (dir === "ltr") { 2896 css[_strLeft] = 0; 2897 css[_strRight] = _strAuto; 2898 scrollLeftValue = constScroll; 2899 } else { 2900 css[_strLeft] = _strAuto; 2901 css[_strRight] = 0; 2902 scrollLeftValue = _rtlScrollBehavior.n 2903 ? -constScroll 2904 : _rtlScrollBehavior.i 2905 ? 0 2906 : constScroll; 2907 } 2908 //execution order is important for IE!!! 2909 _sizeObserverElement.children().eq(0).css(css); 2910 _sizeObserverElement[_strScrollLeft](scrollLeftValue)[ 2911 _strScrollTop 2912 ](constScroll); 2913 _cssDirectionDetectedCache = dir; 2914 result = true; 2915 } 2916 return result; 2917 }; 2918 directionChanged(); 2919 addDestroyEventListener( 2920 targetElement, 2921 _strScroll, 2922 function (event) { 2923 if (directionChanged()) update(); 2924 COMPATIBILITY.prvD(event); 2925 COMPATIBILITY.stpP(event); 2926 return false; 2927 } 2928 ); 2929 } 2930 } 2931 //remove resize observer: 2932 else { 2933 if (_supportResizeObserver) { 2934 var element = targetElement.contents()[0]; 2935 var resizeObserverObj = element[_strResizeObserverProperty]; 2936 if (resizeObserverObj) { 2937 resizeObserverObj.disconnect(); 2938 delete element[_strResizeObserverProperty]; 2939 } 2940 } else { 2941 remove( 2942 targetElement 2943 .children(_strDot + _classNameResizeObserverElement) 2944 .eq(0) 2945 ); 2946 } 2947 } 2948 } 2949 } 2950 2951 /** 2952 * Freezes or unfreezes the given resize observer. 2953 * @param targetElement The element to which the target resize observer is applied. 2954 * @param freeze True if the resize observer shall be frozen, false otherwise. 2955 2956 function freezeResizeObserver(targetElement, freeze) { 2957 if (targetElement !== undefined) { 2958 if(freeze) { 2959 if (_supportResizeObserver) { 2960 var element = targetElement.contents()[0]; 2961 element[_strResizeObserverProperty].unobserve(element); 2962 } 2963 else { 2964 targetElement = targetElement.children(_strDot + _classNameResizeObserverElement).eq(0); 2965 var w = targetElement.css(_strWidth); 2966 var h = targetElement.css(_strHeight); 2967 var css = {}; 2968 css[_strWidth] = w; 2969 css[_strHeight] = h; 2970 targetElement.css(css); 2971 } 2972 } 2973 else { 2974 if (_supportResizeObserver) { 2975 var element = targetElement.contents()[0]; 2976 element[_strResizeObserverProperty].observe(element); 2977 } 2978 else { 2979 var css = { }; 2980 css[_strHeight] = _strEmpty; 2981 css[_strWidth] = _strEmpty; 2982 targetElement.children(_strDot + _classNameResizeObserverElement).eq(0).css(css); 2983 } 2984 } 2985 } 2986 } 2987 */ 2988 2989 //==== Mutation Observers ====// 2990 2991 /** 2992 * Creates MutationObservers for the host and content Element if they are supported. 2993 */ 2994 function createMutationObservers() { 2995 if (_supportMutationObserver) { 2996 var mutationObserverContentLag = 11; 2997 var mutationObserver = COMPATIBILITY.mO(); 2998 var contentLastUpdate = COMPATIBILITY.now(); 2999 var mutationTarget; 3000 var mutationAttrName; 3001 var mutationIsClass; 3002 var oldMutationVal; 3003 var newClassVal; 3004 var hostClassNameRegex; 3005 var contentTimeout; 3006 var now; 3007 var sizeAuto; 3008 var action; 3009 3010 _mutationObserverHostCallback = function (mutations) { 3011 var doUpdate = false; 3012 var doUpdateForce = false; 3013 var mutation; 3014 var mutatedAttrs = []; 3015 3016 if (_initialized && !_sleeping) { 3017 each(mutations, function () { 3018 mutation = this; 3019 mutationTarget = mutation.target; 3020 mutationAttrName = mutation.attributeName; 3021 mutationIsClass = mutationAttrName === LEXICON.c; 3022 oldMutationVal = mutation.oldValue; 3023 newClassVal = mutationTarget.className; 3024 3025 if (_domExists && mutationIsClass && !doUpdateForce) { 3026 // if old class value contains _classNameHostElementForeign and new class value doesn't 3027 if ( 3028 oldMutationVal.indexOf(_classNameHostElementForeign) > 3029 -1 && 3030 newClassVal.indexOf(_classNameHostElementForeign) < 0 3031 ) { 3032 hostClassNameRegex = createHostClassNameRegExp(true); 3033 _hostElementNative.className = newClassVal 3034 .split(_strSpace) 3035 .concat( 3036 oldMutationVal 3037 .split(_strSpace) 3038 .filter(function (name) { 3039 return name.match(hostClassNameRegex); 3040 }) 3041 ) 3042 .join(_strSpace); 3043 doUpdate = doUpdateForce = true; 3044 } 3045 } 3046 3047 if (!doUpdate) { 3048 doUpdate = mutationIsClass 3049 ? hostClassNamesChanged(oldMutationVal, newClassVal) 3050 : mutationAttrName === LEXICON.s 3051 ? oldMutationVal !== mutationTarget[LEXICON.s].cssText 3052 : true; 3053 } 3054 3055 mutatedAttrs.push(mutationAttrName); 3056 }); 3057 3058 updateViewportAttrsFromTarget(mutatedAttrs); 3059 3060 if (doUpdate) _base.update(doUpdateForce || _strAuto); 3061 } 3062 return doUpdate; 3063 }; 3064 _mutationObserverContentCallback = function (mutations) { 3065 var doUpdate = false; 3066 var mutation; 3067 3068 if (_initialized && !_sleeping) { 3069 each(mutations, function () { 3070 mutation = this; 3071 doUpdate = isUnknownMutation(mutation); 3072 return !doUpdate; 3073 }); 3074 3075 if (doUpdate) { 3076 now = COMPATIBILITY.now(); 3077 sizeAuto = _heightAutoCache || _widthAutoCache; 3078 action = function () { 3079 if (!_destroyed) { 3080 contentLastUpdate = now; 3081 3082 //if cols, rows or wrap attr was changed 3083 if (_isTextarea) textareaUpdate(); 3084 3085 if (sizeAuto) update(); 3086 else _base.update(_strAuto); 3087 } 3088 }; 3089 clearTimeout(contentTimeout); 3090 if ( 3091 mutationObserverContentLag <= 0 || 3092 now - contentLastUpdate > mutationObserverContentLag || 3093 !sizeAuto 3094 ) 3095 action(); 3096 else 3097 contentTimeout = setTimeout( 3098 action, 3099 mutationObserverContentLag 3100 ); 3101 } 3102 } 3103 return doUpdate; 3104 }; 3105 3106 _mutationObserverHost = new mutationObserver( 3107 _mutationObserverHostCallback 3108 ); 3109 _mutationObserverContent = new mutationObserver( 3110 _mutationObserverContentCallback 3111 ); 3112 } 3113 } 3114 3115 /** 3116 * Connects the MutationObservers if they are supported. 3117 */ 3118 function connectMutationObservers() { 3119 if (_supportMutationObserver && !_mutationObserversConnected) { 3120 _mutationObserverHost.observe(_hostElementNative, { 3121 attributes: true, 3122 attributeOldValue: true, 3123 attributeFilter: _mutationObserverAttrsHost, 3124 }); 3125 3126 _mutationObserverContent.observe( 3127 _isTextarea ? _targetElementNative : _contentElementNative, 3128 { 3129 attributes: true, 3130 attributeOldValue: true, 3131 subtree: !_isTextarea,
3132 childList: !_isTextarea, 3133 characterData: !_isTextarea, 3134 attributeFilter: _isTextarea 3135 ? _mutationObserverAttrsTextarea 3136 : _mutationObserverAttrsHost, 3137 } 3138 ); 3139 3140 _mutationObserversConnected = true; 3141 } 3142 } 3143 3144 /** 3145 * Disconnects the MutationObservers if they are supported. 3146 */ 3147 function disconnectMutationObservers() { 3148 if (_supportMutationObserver && _mutationObserversConnected) { 3149 _mutationObserverHost.disconnect(); 3150 _mutationObserverContent.disconnect(); 3151 3152 _mutationObserversConnected = false; 3153 } 3154 } 3155 3156 //==== Events of elements ====// 3157 3158 /** 3159 * This method gets called every time the host element gets resized. IMPORTANT: Padding changes are detected too!! 3160 * It refreshes the hostResizedEventArgs and the hostSizeResizeCache. 3161 * If there are any size changes, the update method gets called. 3162 */ 3163 function hostOnResized() { 3164 if (!_sleeping) { 3165 var changed; 3166 var hostSize = { 3167 w: _sizeObserverElementNative[LEXICON.sW], 3168 h: _sizeObserverElementNative[LEXICON.sH], 3169 }; 3170 3171 changed = checkCache(hostSize, _hostElementSizeChangeDetectedCache); 3172 _hostElementSizeChangeDetectedCache = hostSize; 3173 if (changed) update({ _hostSizeChanged: true }); 3174 } 3175 } 3176 3177 /** 3178 * The mouse enter event of the host element. This event is only needed for the autoHide feature. 3179 */ 3180 function hostOnMouseEnter() { 3181 if (_scrollbarsAutoHideLeave) refreshScrollbarsAutoHide(true); 3182 } 3183 3184 /** 3185 * The mouse leave event of the host element. This event is only needed for the autoHide feature. 3186 */ 3187 function hostOnMouseLeave() { 3188 if ( 3189 _scrollbarsAutoHideLeave && 3190 !_bodyElement.hasClass(_classNameDragging) 3191 ) 3192 refreshScrollbarsAutoHide(false); 3193 } 3194 3195 /** 3196 * The mouse move event of the host element. This event is only needed for the autoHide "move" feature. 3197 */ 3198 function hostOnMouseMove() { 3199 if (_scrollbarsAutoHideMove) { 3200 refreshScrollbarsAutoHide(true); 3201 clearTimeout(_scrollbarsAutoHideMoveTimeoutId); 3202 _scrollbarsAutoHideMoveTimeoutId = setTimeout(function () { 3203 if (_scrollbarsAutoHideMove && !_destroyed) 3204 refreshScrollbarsAutoHide(false); 3205 }, 100); 3206 } 3207 } 3208 3209 /** 3210 * Prevents text from deselection if attached to the document element on the mousedown event of a DOM element. 3211 * @param event The select start event. 3212 */ 3213 function documentOnSelectStart(event) { 3214 COMPATIBILITY.prvD(event); 3215 return false; 3216 } 3217 3218 /** 3219 * A callback which will be called after a element has loaded. 3220 */ 3221 function updateOnLoadCallback(event) { 3222 if (!_destroyed) { 3223 var target = event.target; 3224 var elm = FRAMEWORK(event.target); 3225 var index = FRAMEWORK.inArray(target, _updateOnLoadElms); 3226 if (index > -1) { 3227 _updateOnLoadElms.splice(index, 1); 3228 } 3229 3230 eachUpdateOnLoad(function (i, updateOnLoadSelector) { 3231 if (elm.is(updateOnLoadSelector)) { 3232 update({ _contentSizeChanged: true }); 3233 } 3234 }); 3235 } 3236 } 3237 3238 /** 3239 * Adds or removes mouse & touch events of the host element. (for handling auto-hiding of the scrollbars) 3240 * @param destroy Indicates whether the events shall be added or removed. 3241 */ 3242 function setupHostMouseTouchEvents(destroy) { 3243 if (!destroy) setupHostMouseTouchEvents(true); 3244 3245 setupResponsiveEventListener( 3246 _hostElement, 3247 _strMouseTouchMoveEvent.split(_strSpace)[0], 3248 hostOnMouseMove, 3249 !_scrollbarsAutoHideMove || destroy, 3250 true 3251 ); 3252 setupResponsiveEventListener( 3253 _hostElement, 3254 [_strMouseEnter, _strMouseLeave], 3255 [hostOnMouseEnter, hostOnMouseLeave], 3256 !_scrollbarsAutoHideLeave || destroy, 3257 true 3258 ); 3259 3260 //if the plugin is initialized and the mouse is over the host element, make the scrollbars visible 3261 if (!_initialized && !destroy) 3262 _hostElement.one("mouseover", hostOnMouseEnter); 3263 } 3264 3265 //==== Update Detection ====// 3266 3267 /** 3268 * Measures the min width and min height of the body element and refreshes the related cache. 3269 * @returns {boolean} True if the min width or min height has changed, false otherwise. 3270 */ 3271 function bodyMinSizeChanged() { 3272 var bodyMinSize = {}; 3273 if (_isBody && _contentArrangeElement) {
3274 bodyMinSize.w = parseToZeroOrNumber( 3275 _contentArrangeElement.css(_strMinMinus + _strWidth) 3276 ); 3277 bodyMinSize.h = parseToZeroOrNumber( 3278 _contentArrangeElement.css(_strMinMinus + _strHeight) 3279 ); 3280 bodyMinSize.c = checkCache(bodyMinSize, _bodyMinSizeCache); 3281 bodyMinSize.f = true; //flag for "measured at least once" 3282 } 3283 _bodyMinSizeCache = bodyMinSize; 3284 return !!bodyMinSize.c; 3285 } 3286 3287 /** 3288 * Returns true if the class names really changed (new class without plugin host prefix) 3289 * @param oldClassNames The old ClassName string or array. 3290 * @param newClassNames The new ClassName string or array. 3291 * @returns {boolean} True if the class names has really changed, false otherwise. 3292 */ 3293 function hostClassNamesChanged(oldClassNames, newClassNames) { 3294 var currClasses = 3295 typeof newClassNames == TYPES.s 3296 ? newClassNames.split(_strSpace) 3297 : []; 3298 var oldClasses = 3299 typeof oldClassNames == TYPES.s 3300 ? oldClassNames.split(_strSpace) 3301 : []; 3302 var diff = getArrayDifferences(oldClasses, currClasses); 3303 3304 // remove none theme from diff list to prevent update 3305 var idx = inArray(_classNameThemeNone, diff); 3306 var i; 3307 var regex; 3308 3309 if (idx > -1) diff.splice(idx, 1); 3310 3311 if (diff[LEXICON.l] > 0) { 3312 regex = createHostClassNameRegExp(true, true); 3313 for (i = 0; i < diff.length; i++) { 3314 if (!diff[i].match(regex)) { 3315 return true; 3316 } 3317 } 3318 } 3319 return false; 3320 } 3321 3322 /** 3323 * Returns true if the given mutation is not from a from the plugin generated element. If the target element is a textarea the mutation is always unknown. 3324 * @param mutation The mutation which shall be checked. 3325 * @returns {boolean} True if the mutation is from a unknown element, false otherwise. 3326 */ 3327 function isUnknownMutation(mutation) { 3328 var attributeName = mutation.attributeName; 3329 var mutationTarget = mutation.target; 3330 var mutationType = mutation.type; 3331 var strClosest = "closest"; 3332 3333 if (mutationTarget === _contentElementNative) 3334 return attributeName === null; 3335 if ( 3336 mutationType === "attributes" && 3337 (attributeName === LEXICON.c || attributeName === LEXICON.s) && 3338 !_isTextarea 3339 ) { 3340 //ignore className changes by the plugin 3341 if ( 3342 attributeName === LEXICON.c && 3343 FRAMEWORK(mutationTarget).hasClass(_classNameHostElement) 3344 ) 3345 return hostClassNamesChanged( 3346 mutation.oldValue, 3347 mutationTarget.className 3348 ); 3349 3350 //only do it of browser support it natively 3351 if (typeof mutationTarget[strClosest] != TYPES.f) return true; 3352 if ( 3353 mutationTarget[strClosest]( 3354 _strDot + _classNameResizeObserverElement 3355 ) !== null || 3356 mutationTarget[strClosest](_strDot + _classNameScrollbar) !== 3357 null || 3358 mutationTarget[strClosest]( 3359 _strDot + _classNameScrollbarCorner 3360 ) !== null 3361 ) 3362 return false; 3363 } 3364 return true; 3365 } 3366 3367 /** 3368 * Returns true if the content size was changed since the last time this method was called. 3369 * @returns {boolean} True if the content size was changed, false otherwise. 3370 */ 3371 function updateAutoContentSizeChanged() { 3372 if (_sleeping) return false; 3373 3374 var contentMeasureElement = getContentMeasureElement(); 3375 var textareaValueLength = 3376 _isTextarea && _widthAutoCache && !_textareaAutoWrappingCache 3377 ? _targetElement.val().length 3378 : 0;
3379 var setCSS = 3380 !_mutationObserversConnected && _widthAutoCache && !_isTextarea; 3381 var css = {}; 3382 var float; 3383 var bodyMinSizeC; 3384 var changed; 3385 var contentElementScrollSize; 3386 3387 if (setCSS) { 3388 float = _contentElement.css(_strFloat); 3389 css[_strFloat] = _isRTL ? _strRight : _strLeft; 3390 css[_strWidth] = _strAuto; 3391 _contentElement.css(css); 3392 } 3393 contentElementScrollSize = { 3394 w: contentMeasureElement[LEXICON.sW] + textareaValueLength, 3395 h: contentMeasureElement[LEXICON.sH] + textareaValueLength, 3396 }; 3397 if (setCSS) { 3398 css[_strFloat] = float; 3399 css[_strWidth] = _strHundredPercent; 3400 _contentElement.css(css); 3401 } 3402 3403 bodyMinSizeC = bodyMinSizeChanged(); 3404 changed = checkCache( 3405 contentElementScrollSize, 3406 _contentElementScrollSizeChangeDetectedCache 3407 ); 3408 3409 _contentElementScrollSizeChangeDetectedCache = 3410 contentElementScrollSize; 3411 3412 return changed || bodyMinSizeC; 3413 } 3414 3415 /** 3416 * Returns true when a attribute which the MutationObserver would observe has changed. 3417 * @returns {boolean} True if one of the attributes which a MutationObserver would observe has changed, false or undefined otherwise. 3418 */ 3419 function meaningfulAttrsChanged() { 3420 if (_sleeping || _mutationObserversConnected) return; 3421 3422 var elem; 3423 var curr; 3424 var cache; 3425 var changedAttrs = []; 3426 var checks = [ 3427 { 3428 _elem: _hostElement, 3429 _attrs: _mutationObserverAttrsHost.concat(":visible"), 3430 }, 3431 { 3432 _elem: _isTextarea ? _targetElement : undefined, 3433 _attrs: _mutationObserverAttrsTextarea, 3434 }, 3435 ]; 3436 3437 each(checks, function (index, check) { 3438 elem = check._elem; 3439 if (elem) { 3440 each(check._attrs, function (index, attr) { 3441 curr = attr.charAt(0) === ":" ? elem.is(attr) : elem.attr(attr); 3442 cache = _updateAutoCache[attr]; 3443 3444 if (checkCache(curr, cache)) { 3445 changedAttrs.push(attr); 3446 } 3447 3448 _updateAutoCache[attr] = curr; 3449 }); 3450 } 3451 }); 3452 3453 updateViewportAttrsFromTarget(changedAttrs); 3454 3455 return changedAttrs[LEXICON.l] > 0; 3456 } 3457 3458 /** 3459 * Checks is a CSS Property of a child element is affecting the scroll size of the content. 3460 * @param propertyName The CSS property name. 3461 * @returns {boolean} True if the property is affecting the content scroll size, false otherwise. 3462 */ 3463 function isSizeAffectingCSSProperty(propertyName) { 3464 if (!_initialized) return true; 3465 var flexGrow = "flex-grow"; 3466 var flexShrink = "flex-shrink"; 3467 var flexBasis = "flex-basis"; 3468 var affectingPropsX = [ 3469 _strWidth, 3470 _strMinMinus + _strWidth, 3471 _strMaxMinus + _strWidth, 3472 _strMarginMinus + _strLeft, 3473 _strMarginMinus + _strRight, 3474 _strLeft, 3475 _strRight, 3476 "font-weight", 3477 "word-spacing", 3478 flexGrow, 3479 flexShrink, 3480 flexBasis, 3481 ]; 3482 var affectingPropsXContentBox = [ 3483 _strPaddingMinus + _strLeft, 3484 _strPaddingMinus + _strRight, 3485 _strBorderMinus + _strLeft + _strWidth, 3486 _strBorderMinus + _strRight + _strWidth, 3487 ]; 3488 var affectingPropsY = [ 3489 _strHeight, 3490 _strMinMinus + _strHeight, 3491 _strMaxMinus + _strHeight, 3492 _strMarginMinus + _strTop, 3493 _strMarginMinus + _strBottom, 3494 _strTop, 3495 _strBottom, 3496 "line-height", 3497 flexGrow, 3498 flexShrink, 3499 flexBasis, 3500 ]; 3501 var affectingPropsYContentBox = [ 3502 _strPaddingMinus + _strTop, 3503 _strPaddingMinus + _strBottom, 3504 _strBorderMinus + _strTop + _strWidth, 3505 _strBorderMinus + _strBottom + _strWidth, 3506 ]; 3507 var _strS = "s"; 3508 var _strVS = "v-s"; 3509 var checkX = 3510 _overflowBehaviorCache.x === _strS || 3511 _overflowBehaviorCache.x === _strVS; 3512 var checkY = 3513 _overflowBehaviorCache.y === _strS || 3514 _overflowBehaviorCache.y === _strVS; 3515 var sizeIsAffected = false;
3516 var checkPropertyName = function (arr, name) { 3517 for (var i = 0; i < arr[LEXICON.l]; i++) { 3518 if (arr[i] === name) return true; 3519 } 3520 return false; 3521 }; 3522 3523 if (checkY) { 3524 sizeIsAffected = checkPropertyName(affectingPropsY, propertyName); 3525 if (!sizeIsAffected && !_isBorderBox) 3526 sizeIsAffected = checkPropertyName( 3527 affectingPropsYContentBox, 3528 propertyName 3529 ); 3530 } 3531 if (checkX && !sizeIsAffected) { 3532 sizeIsAffected = checkPropertyName(affectingPropsX, propertyName); 3533 if (!sizeIsAffected && !_isBorderBox) 3534 sizeIsAffected = checkPropertyName( 3535 affectingPropsXContentBox, 3536 propertyName 3537 ); 3538 } 3539 return sizeIsAffected; 3540 } 3541 3542 //==== Update ====// 3543 3544 /** 3545 * Sets the attribute values of the viewport element to the values from the target element. 3546 * The value of a attribute is only set if the attribute is whitelisted. 3547 * @attrs attrs The array of attributes which shall be set or undefined if all whitelisted shall be set. 3548 */ 3549 function updateViewportAttrsFromTarget(attrs) { 3550 attrs = attrs || _viewportAttrsFromTarget; 3551 each(attrs, function (index, attr) { 3552 if (COMPATIBILITY.inA(attr, _viewportAttrsFromTarget) > -1) { 3553 var targetAttr = _targetElement.attr(attr); 3554 if (type(targetAttr) == TYPES.s) { 3555 _viewportElement.attr(attr, targetAttr); 3556 } else { 3557 _viewportElement.removeAttr(attr); 3558 } 3559 } 3560 }); 3561 } 3562 3563 /** 3564 * Updates the variables and size of the textarea element, and manages the scroll on new line or new character. 3565 */ 3566 function textareaUpdate() { 3567 if (!_sleeping) { 3568 var wrapAttrOff = !_textareaAutoWrappingCache; 3569 var minWidth = _viewportSize.w; 3570 var minHeight = _viewportSize.h; 3571 var css = {}; 3572 var doMeasure = _widthAutoCache || wrapAttrOff; 3573 var origWidth; 3574 var width; 3575 var origHeight; 3576 var height; 3577 3578 //reset min size 3579 css[_strMinMinus + _strWidth] = _strEmpty; 3580 css[_strMinMinus + _strHeight] = _strEmpty; 3581 3582 //set width auto 3583 css[_strWidth] = _strAuto; 3584 _targetElement.css(css); 3585 3586 //measure width 3587 origWidth = _targetElementNative[LEXICON.oW]; 3588 width = doMeasure 3589 ? MATH.max(origWidth, _targetElementNative[LEXICON.sW] - 1) 3590 : 1; 3591 /*width += (_widthAutoCache ? _marginX + (!_isBorderBox ? wrapAttrOff ? 0 : _paddingX + _borderX : 0) : 0);*/ 3592 3593 //set measured width 3594 css[_strWidth] = _widthAutoCache 3595 ? _strAuto /*width*/ 3596 : _strHundredPercent; 3597 css[_strMinMinus + _strWidth] = _strHundredPercent; 3598 3599 //set height auto 3600 css[_strHeight] = _strAuto; 3601 _targetElement.css(css); 3602 3603 //measure height 3604 origHeight = _targetElementNative[LEXICON.oH]; 3605 height = MATH.max(origHeight, _targetElementNative[LEXICON.sH] - 1); 3606 3607 //append correct size values 3608 css[_strWidth] = width; 3609 css[_strHeight] = height; 3610 _textareaCoverElement.css(css); 3611 3612 //apply min width / min height to prevent textarea collapsing 3613 css[_strMinMinus + _strWidth] = 3614 minWidth /*+ (!_isBorderBox && _widthAutoCache ? _paddingX + _borderX : 0)*/; 3615 css[_strMinMinus + _strHeight] = 3616 minHeight /*+ (!_isBorderBox && _heightAutoCache ? _paddingY + _borderY : 0)*/; 3617 _targetElement.css(css); 3618 3619 return { 3620 _originalWidth: origWidth, 3621 _originalHeight: origHeight, 3622 _dynamicWidth: width, 3623 _dynamicHeight: height, 3624 }; 3625 } 3626 } 3627 3628 /** 3629 * Updates the plugin and DOM to the current options. 3630 * This method should only be called if a update is 100% required. 3631 * @param updateHints A objects which contains hints for this update: 3632 * { 3633 * _hostSizeChanged : boolean, 3634 * _contentSizeChanged : boolean, 3635 * _force : boolean, == preventSwallowing 3636 * _changedOptions : { }, == preventSwallowing && preventSleep 3637 * } 3638 */ 3639 function update(updateHints) { 3640 clearTimeout(_swallowedUpdateTimeout); 3641 updateHints = updateHints || {}; 3642 _swallowedUpdateHints._hostSizeChanged |= 3643 updateHints._hostSizeChanged; 3644 _swallowedUpdateHints._contentSizeChanged |= 3645 updateHints._contentSizeChanged; 3646 _swallowedUpdateHints._force |= updateHints._force; 3647 3648 var now = COMPATIBILITY.now(); 3649 var hostSizeChanged = !!_swallowedUpdateHints._hostSizeChanged; 3650 var contentSizeChanged = !!_swallowedUpdateHints._contentSizeChanged; 3651 var force = !!_swallowedUpdateHints._force; 3652 var changedOptions = updateHints._changedOptions; 3653 var swallow = 3654 _swallowUpdateLag > 0 && 3655 _initialized && 3656 !_destroyed && 3657 !force && 3658 !changedOptions && 3659 now - _lastUpdateTime < _swallowUpdateLag && 3660 !_heightAutoCache && 3661 !_widthAutoCache; 3662 var displayIsHidden; 3663 3664 if (swallow) 3665 _swallowedUpdateTimeout = setTimeout(update, _swallowUpdateLag); 3666 3667 //abort update due to: 3668 //destroyed 3669 //swallowing 3670 //sleeping 3671 //host is hidden or has false display 3672 if ( 3673 _destroyed || 3674 swallow || 3675 (_sleeping && !changedOptions) || 3676 (_initialized && 3677 !force && 3678 (displayIsHidden = _hostElement.is(":hidden"))) || 3679 _hostElement.css("display") === "inline" 3680 ) 3681 return; 3682
3683 _lastUpdateTime = now; 3684 _swallowedUpdateHints = {}; 3685 3686 //if scrollbar styling is possible and native scrollbars aren't overlaid the scrollbar styling will be applied which hides the native scrollbars completely. 3687 if ( 3688 _nativeScrollbarStyling && 3689 !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y) 3690 ) { 3691 //native scrollbars are hidden, so change the values to zero 3692 _nativeScrollbarSize.x = 0; 3693 _nativeScrollbarSize.y = 0; 3694 } else { 3695 //refresh native scrollbar size (in case of zoom) 3696 _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); 3697 } 3698 3699 // Scrollbar padding is needed for firefox, because firefox hides scrollbar automatically if the size of the div is too small. 3700 // The calculation: [scrollbar size +3 *3] 3701 // (+3 because of possible decoration e.g. borders, margins etc., but only if native scrollbar is NOT a overlaid scrollbar) 3702 // (*3 because (1)increase / (2)decrease -button and (3)resize handle) 3703 _nativeScrollbarMinSize = { 3704 x: 3705 (_nativeScrollbarSize.x + 3706 (_nativeScrollbarIsOverlaid.x ? 0 : 3)) * 3707 3, 3708 y: 3709 (_nativeScrollbarSize.y + 3710 (_nativeScrollbarIsOverlaid.y ? 0 : 3)) * 3711 3, 3712 }; 3713 3714 changedOptions = changedOptions || {}; 3715 //freezeResizeObserver(_sizeObserverElement, true); 3716 //freezeResizeObserver(_sizeAutoObserverElement, true); 3717 3718 var checkCacheAutoForce = function () { 3719 return checkCache.apply( 3720 this, 3721 [].slice.call(arguments).concat([force]) 3722 ); 3723 }; 3724 3725 //save current scroll offset 3726 var currScroll = { 3727 x: _viewportElement[_strScrollLeft](), 3728 y: _viewportElement[_strScrollTop](), 3729 }; 3730 3731 var currentPreparedOptionsScrollbars = 3732 _currentPreparedOptions.scrollbars; 3733 var currentPreparedOptionsTextarea = _currentPreparedOptions.textarea; 3734 3735 //scrollbars visibility: 3736 var scrollbarsVisibility = 3737 currentPreparedOptionsScrollbars.visibility; 3738 var scrollbarsVisibilityChanged = checkCacheAutoForce( 3739 scrollbarsVisibility, 3740 _scrollbarsVisibilityCache 3741 ); 3742 3743 //scrollbars autoHide: 3744 var scrollbarsAutoHide = currentPreparedOptionsScrollbars.autoHide; 3745 var scrollbarsAutoHideChanged = checkCacheAutoForce( 3746 scrollbarsAutoHide, 3747 _scrollbarsAutoHideCache 3748 ); 3749 3750 //scrollbars click scrolling 3751 var scrollbarsClickScrolling = 3752 currentPreparedOptionsScrollbars.clickScrolling; 3753 var scrollbarsClickScrollingChanged = checkCacheAutoForce( 3754 scrollbarsClickScrolling, 3755 _scrollbarsClickScrollingCache 3756 ); 3757 3758 //scrollbars drag scrolling 3759 var scrollbarsDragScrolling = 3760 currentPreparedOptionsScrollbars.dragScrolling; 3761 var scrollbarsDragScrollingChanged = checkCacheAutoForce( 3762 scrollbarsDragScrolling, 3763 _scrollbarsDragScrollingCache 3764 ); 3765 3766 //className 3767 var className = _currentPreparedOptions.className; 3768 var classNameChanged = checkCacheAutoForce( 3769 className, 3770 _classNameCache 3771 ); 3772 3773 //resize 3774 var resize = _currentPreparedOptions.resize; 3775 var resizeChanged = 3776 checkCacheAutoForce(resize, _resizeCache) && !_isBody; //body can't be resized since the window itself acts as resize possibility. 3777 3778 //paddingAbsolute 3779 var paddingAbsolute = _currentPreparedOptions.paddingAbsolute; 3780 var paddingAbsoluteChanged = checkCacheAutoForce( 3781 paddingAbsolute, 3782 _paddingAbsoluteCache 3783 ); 3784 3785 //clipAlways 3786 var clipAlways = _currentPreparedOptions.clipAlways; 3787 var clipAlwaysChanged = checkCacheAutoForce( 3788 clipAlways, 3789 _clipAlwaysCache 3790 ); 3791 3792 //sizeAutoCapable 3793 var sizeAutoCapable = 3794 _currentPreparedOptions.sizeAutoCapable && !_isBody; //body can never be size auto, because it shall be always as big as the viewport. 3795 var sizeAutoCapableChanged = checkCacheAutoForce( 3796 sizeAutoCapable, 3797 _sizeAutoCapableCache 3798 ); 3799 3800 //showNativeScrollbars 3801 var ignoreOverlayScrollbarHiding = 3802 _currentPreparedOptions.nativeScrollbarsOverlaid 3803 .showNativeScrollbars; 3804 var ignoreOverlayScrollbarHidingChanged = checkCacheAutoForce( 3805 ignoreOverlayScrollbarHiding, 3806 _ignoreOverlayScrollbarHidingCache 3807 ); 3808 3809 //autoUpdate 3810 var autoUpdate = _currentPreparedOptions.autoUpdate; 3811 var autoUpdateChanged = checkCacheAutoForce( 3812 autoUpdate, 3813 _autoUpdateCache 3814 ); 3815 3816 //overflowBehavior 3817 var overflowBehavior = _currentPreparedOptions.overflowBehavior; 3818 var overflowBehaviorChanged = checkCacheAutoForce( 3819 overflowBehavior, 3820 _overflowBehaviorCache, 3821 force 3822 ); 3823 3824 //dynWidth: 3825 var textareaDynWidth = currentPreparedOptionsTextarea.dynWidth; 3826 var textareaDynWidthChanged = checkCacheAutoForce( 3827 _textareaDynWidthCache, 3828 textareaDynWidth 3829 ); 3830 3831 //dynHeight: 3832 var textareaDynHeight = currentPreparedOptionsTextarea.dynHeight; 3833 var textareaDynHeightChanged = checkCacheAutoForce( 3834 _textareaDynHeightCache, 3835 textareaDynHeight 3836 ); 3837 3838 //scrollbars visibility 3839 _scrollbarsAutoHideNever = scrollbarsAutoHide === "n"; 3840 _scrollbarsAutoHideScroll = scrollbarsAutoHide === "s"; 3841 _scrollbarsAutoHideMove = scrollbarsAutoHide === "m"; 3842 _scrollbarsAutoHideLeave = scrollbarsAutoHide === "l"; 3843 3844 //scrollbars autoHideDelay 3845 _scrollbarsAutoHideDelay = 3846 currentPreparedOptionsScrollbars.autoHideDelay; 3847 3848 //old className
3849 _oldClassName = _classNameCache; 3850 3851 //resize 3852 _resizeNone = resize === "n"; 3853 _resizeBoth = resize === "b"; 3854 _resizeHorizontal = resize === "h"; 3855 _resizeVertical = resize === "v"; 3856 3857 //normalizeRTL 3858 _normalizeRTLCache = _currentPreparedOptions.normalizeRTL; 3859 3860 //ignore overlay scrollbar hiding 3861 ignoreOverlayScrollbarHiding = 3862 ignoreOverlayScrollbarHiding && 3863 _nativeScrollbarIsOverlaid.x && 3864 _nativeScrollbarIsOverlaid.y; 3865 3866 //refresh options cache 3867 _scrollbarsVisibilityCache = scrollbarsVisibility; 3868 _scrollbarsAutoHideCache = scrollbarsAutoHide; 3869 _scrollbarsClickScrollingCache = scrollbarsClickScrolling; 3870 _scrollbarsDragScrollingCache = scrollbarsDragScrolling; 3871 _classNameCache = className; 3872 _resizeCache = resize; 3873 _paddingAbsoluteCache = paddingAbsolute; 3874 _clipAlwaysCache = clipAlways; 3875 _sizeAutoCapableCache = sizeAutoCapable; 3876 _ignoreOverlayScrollbarHidingCache = ignoreOverlayScrollbarHiding; 3877 _autoUpdateCache = autoUpdate; 3878 _overflowBehaviorCache = extendDeep({}, overflowBehavior); 3879 _textareaDynWidthCache = textareaDynWidth; 3880 _textareaDynHeightCache = textareaDynHeight; 3881 _hasOverflowCache = _hasOverflowCache || { x: false, y: false }; 3882 3883 //set correct class name to the host element 3884 if (classNameChanged) { 3885 removeClass( 3886 _hostElement, 3887 _oldClassName + _strSpace + _classNameThemeNone 3888 ); 3889 addClass( 3890 _hostElement, 3891 className !== undefined && 3892 className !== null && 3893 className.length > 0 3894 ? className 3895 : _classNameThemeNone 3896 ); 3897 } 3898 3899 //set correct auto Update 3900 if (autoUpdateChanged) { 3901 if ( 3902 autoUpdate === true || 3903 (autoUpdate === null && _autoUpdateRecommended) 3904 ) { 3905 disconnectMutationObservers(); 3906 autoUpdateLoop.add(_base); 3907 } else { 3908 autoUpdateLoop.remove(_base); 3909 connectMutationObservers(); 3910 } 3911 } 3912 3913 //activate or deactivate size auto capability 3914 if (sizeAutoCapableChanged) { 3915 if (sizeAutoCapable) { 3916 if (_contentGlueElement) { 3917 _contentGlueElement.show(); 3918 } else { 3919 _contentGlueElement = FRAMEWORK( 3920 generateDiv(_classNameContentGlueElement) 3921 ); 3922 _paddingElement.before(_contentGlueElement); 3923 } 3924 if (_sizeAutoObserverAdded) { 3925 _sizeAutoObserverElement.show(); 3926 } else { 3927 _sizeAutoObserverElement = FRAMEWORK( 3928 generateDiv(_classNameSizeAutoObserverElement) 3929 ); 3930 _sizeAutoObserverElementNative = _sizeAutoObserverElement[0]; 3931 3932 _contentGlueElement.before(_sizeAutoObserverElement); 3933 var oldSize = { w: -1, h: -1 }; 3934 setupResizeObserver(_sizeAutoObserverElement, function () { 3935 var newSize = { 3936 w: _sizeAutoObserverElementNative[LEXICON.oW], 3937 h: _sizeAutoObserverElementNative[LEXICON.oH], 3938 }; 3939 if (checkCache(newSize, oldSize)) { 3940 if ( 3941 (_initialized && _heightAutoCache && newSize.h > 0) || 3942 (_widthAutoCache && newSize.w > 0) 3943 ) { 3944 update(); 3945 } else if ( 3946 (_initialized && !_heightAutoCache && newSize.h === 0) || 3947 (!_widthAutoCache && newSize.w === 0) 3948 ) { 3949 update(); 3950 } 3951 } 3952 oldSize = newSize; 3953 }); 3954 _sizeAutoObserverAdded = true; 3955 //fix heightAuto detector bug if height is fixed but contentHeight is 0. 3956 //the probability this bug will ever happen is very very low, thats why its ok if we use calc which isn't supported in IE8. 3957 if (_cssCalc !== null) 3958 _sizeAutoObserverElement.css( 3959 _strHeight, 3960 _cssCalc + "(100% + 1px)" 3961 ); 3962 } 3963 } else { 3964 if (_sizeAutoObserverAdded) _sizeAutoObserverElement.hide(); 3965 if (_contentGlueElement) _contentGlueElement.hide(); 3966 } 3967 } 3968 3969 //if force, update all resizeObservers too 3970 if (force) { 3971 _sizeObserverElement.find("*").trigger(_strScroll); 3972 if (_sizeAutoObserverAdded) 3973 _sizeAutoObserverElement.find("*").trigger(_strScroll); 3974 } 3975 3976 //display hidden: 3977 displayIsHidden = 3978 displayIsHidden === undefined 3979 ? _hostElement.is(":hidden") 3980 : displayIsHidden; 3981 3982 //textarea AutoWrapping: 3983 var textareaAutoWrapping = _isTextarea 3984 ? _targetElement.attr("wrap") !== "off" 3985 : false;
3986 var textareaAutoWrappingChanged = checkCacheAutoForce( 3987 textareaAutoWrapping, 3988 _textareaAutoWrappingCache 3989 ); 3990 3991 //detect direction: 3992 var cssDirection = _hostElement.css("direction"); 3993 var cssDirectionChanged = checkCacheAutoForce( 3994 cssDirection, 3995 _cssDirectionCache 3996 ); 3997 3998 //detect box-sizing: 3999 var boxSizing = _hostElement.css("box-sizing"); 4000 var boxSizingChanged = checkCacheAutoForce( 4001 boxSizing, 4002 _cssBoxSizingCache 4003 ); 4004 4005 //detect padding: 4006 var padding = getTopRightBottomLeftHost(_strPaddingMinus); 4007 4008 //width + height auto detecting var: 4009 var sizeAutoObserverElementBCRect; 4010 //exception occurs in IE8 sometimes (unknown exception) 4011 try { 4012 sizeAutoObserverElementBCRect = _sizeAutoObserverAdded 4013 ? _sizeAutoObserverElementNative[LEXICON.bCR]() 4014 : null; 4015 } catch (ex) { 4016 return; 4017 } 4018 4019 _isRTL = cssDirection === "rtl"; 4020 _isBorderBox = boxSizing === "border-box"; 4021 var isRTLLeft = _isRTL ? _strLeft : _strRight; 4022 var isRTLRight = _isRTL ? _strRight : _strLeft; 4023 4024 //detect width auto: 4025 var widthAutoResizeDetection = false; 4026 var widthAutoObserverDetection = 4027 _sizeAutoObserverAdded && 4028 _hostElement.css(_strFloat) !== "none" /*|| _isTextarea */ 4029 ? MATH.round( 4030 sizeAutoObserverElementBCRect.right - 4031 sizeAutoObserverElementBCRect.left 4032 ) === 0 && 4033 (!paddingAbsolute 4034 ? _hostElementNative[LEXICON.cW] - _paddingX > 0 4035 : true) 4036 : false; 4037 if (sizeAutoCapable && !widthAutoObserverDetection) { 4038 var tmpCurrHostWidth = _hostElementNative[LEXICON.oW]; 4039 var tmpCurrContentGlueWidth = _contentGlueElement.css(_strWidth); 4040 _contentGlueElement.css(_strWidth, _strAuto); 4041 4042 var tmpNewHostWidth = _hostElementNative[LEXICON.oW]; 4043 _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); 4044 widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; 4045 if (!widthAutoResizeDetection) { 4046 _contentGlueElement.css(_strWidth, tmpCurrHostWidth + 1); 4047 tmpNewHostWidth = _hostElementNative[LEXICON.oW]; 4048 _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); 4049 widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; 4050 } 4051 } 4052 var widthAuto = 4053 (widthAutoObserverDetection || widthAutoResizeDetection) && 4054 sizeAutoCapable && 4055 !displayIsHidden; 4056 var widthAutoChanged = checkCacheAutoForce( 4057 widthAuto, 4058 _widthAutoCache 4059 ); 4060 var wasWidthAuto = !widthAuto && _widthAutoCache; 4061 4062 //detect height auto: 4063 var heightAuto = 4064 _sizeAutoObserverAdded && sizeAutoCapable && !displayIsHidden 4065 ? MATH.round( 4066 sizeAutoObserverElementBCRect.bottom - 4067 sizeAutoObserverElementBCRect.top 4068 ) === 4069 0 /* && (!paddingAbsolute && (_msieVersion > 9 || !_msieVersion) ? true : true) */ 4070 : false; 4071 var heightAutoChanged = checkCacheAutoForce( 4072 heightAuto, 4073 _heightAutoCache 4074 ); 4075 var wasHeightAuto = !heightAuto && _heightAutoCache; 4076 4077 //detect border: 4078 //we need the border only if border box and auto size 4079 var updateBorderX = (widthAuto && _isBorderBox) || !_isBorderBox; 4080 var updateBorderY = (heightAuto && _isBorderBox) || !_isBorderBox; 4081 var border = getTopRightBottomLeftHost( 4082 _strBorderMinus, 4083 "-" + _strWidth, 4084 !updateBorderX, 4085 !updateBorderY 4086 ); 4087 4088 //detect margin: 4089 var margin = getTopRightBottomLeftHost(_strMarginMinus); 4090 4091 //vars to apply correct css 4092 var contentElementCSS = {}; 4093 var contentGlueElementCSS = {}; 4094 4095 //funcs 4096 var getHostSize = function () { 4097 //has to be clientSize because offsetSize respect borders 4098 return { 4099 w: _hostElementNative[LEXICON.cW], 4100 h: _hostElementNative[LEXICON.cH], 4101 }; 4102 }; 4103 var getViewportSize = function () { 4104 //viewport size is padding container because it never has padding, margin and a border 4105 //determine zoom rounding error -> sometimes scrollWidth/Height is smaller than clientWidth/Height 4106 //if this happens add the difference to the viewportSize to compensate the rounding error 4107 return { 4108 w: 4109 _paddingElementNative[LEXICON.oW] + 4110 MATH.max( 4111 0, 4112 _contentElementNative[LEXICON.cW] - 4113 _contentElementNative[LEXICON.sW] 4114 ), 4115 h: 4116 _paddingElementNative[LEXICON.oH] + 4117 MATH.max( 4118 0, 4119 _contentElementNative[LEXICON.cH] - 4120 _contentElementNative[LEXICON.sH] 4121 ), 4122 }; 4123 }; 4124 4125 //set info for padding 4126 var paddingAbsoluteX = (_paddingX = padding.l + padding.r); 4127 var paddingAbsoluteY = (_paddingY = padding.t + padding.b); 4128 paddingAbsoluteX *= paddingAbsolute ? 1 : 0; 4129 paddingAbsoluteY *= paddingAbsolute ? 1 : 0; 4130 padding.c = checkCacheAutoForce(padding, _cssPaddingCache); 4131 4132 //set info for border 4133 _borderX = border.l + border.r; 4134 _borderY = border.t + border.b; 4135 border.c = checkCacheAutoForce(border, _cssBorderCache); 4136 4137 //set info for margin 4138 _marginX = margin.l + margin.r; 4139 _marginY = margin.t + margin.b; 4140 margin.c = checkCacheAutoForce(margin, _cssMarginCache); 4141 4142 //refresh cache 4143 _textareaAutoWrappingCache = textareaAutoWrapping; 4144 _cssDirectionCache = cssDirection; 4145 _cssBoxSizingCache = boxSizing; 4146 _widthAutoCache = widthAuto;
vendor: 8,459 bytes, lines 4147-4360
4147 _heightAutoCache = heightAuto; 4148 _cssPaddingCache = padding; 4149 _cssBorderCache = border; 4150 _cssMarginCache = margin; 4151 4152 //IEFix direction changed 4153 if (cssDirectionChanged && _sizeAutoObserverAdded) 4154 _sizeAutoObserverElement.css(_strFloat, isRTLRight); 4155 4156 //apply padding: 4157 if ( 4158 padding.c || 4159 cssDirectionChanged || 4160 paddingAbsoluteChanged || 4161 widthAutoChanged || 4162 heightAutoChanged || 4163 boxSizingChanged || 4164 sizeAutoCapableChanged 4165 ) { 4166 var paddingElementCSS = {}; 4167 var textareaCSS = {}; 4168 var paddingValues = [padding.t, padding.r, padding.b, padding.l]; 4169 4170 setTopRightBottomLeft(contentGlueElementCSS, _strMarginMinus, [ 4171 -padding.t, 4172 -padding.r, 4173 -padding.b, 4174 -padding.l, 4175 ]); 4176 if (paddingAbsolute) { 4177 setTopRightBottomLeft( 4178 paddingElementCSS, 4179 _strEmpty, 4180 paddingValues 4181 ); 4182 setTopRightBottomLeft( 4183 _isTextarea ? textareaCSS : contentElementCSS, 4184 _strPaddingMinus 4185 ); 4186 } else { 4187 setTopRightBottomLeft(paddingElementCSS, _strEmpty); 4188 setTopRightBottomLeft( 4189 _isTextarea ? textareaCSS : contentElementCSS, 4190 _strPaddingMinus, 4191 paddingValues 4192 ); 4193 } 4194 4195 _paddingElement.css(paddingElementCSS); 4196 _targetElement.css(textareaCSS); 4197 } 4198 4199 //viewport size is padding container because it never has padding, margin and a border. 4200 _viewportSize = getViewportSize(); 4201 4202 //update Textarea 4203 var textareaSize = _isTextarea ? textareaUpdate() : false; 4204 var textareaSizeChanged = 4205 _isTextarea && 4206 checkCacheAutoForce(textareaSize, _textareaSizeCache); 4207 var textareaDynOrigSize = 4208 _isTextarea && textareaSize 4209 ? { 4210 w: textareaDynWidth 4211 ? textareaSize._dynamicWidth 4212 : textareaSize._originalWidth, 4213 h: textareaDynHeight 4214 ? textareaSize._dynamicHeight 4215 : textareaSize._originalHeight, 4216 } 4217 : {}; 4218 _textareaSizeCache = textareaSize; 4219 4220 //fix height auto / width auto in cooperation with current padding & boxSizing behavior: 4221 if ( 4222 heightAuto && 4223 (heightAutoChanged || 4224 paddingAbsoluteChanged || 4225 boxSizingChanged || 4226 padding.c || 4227 border.c) 4228 ) { 4229 contentElementCSS[_strHeight] = _strAuto; 4230 } else if (heightAutoChanged || paddingAbsoluteChanged) { 4231 contentElementCSS[_strHeight] = _strHundredPercent; 4232 } 4233 if ( 4234 widthAuto && 4235 (widthAutoChanged || 4236 paddingAbsoluteChanged || 4237 boxSizingChanged || 4238 padding.c || 4239 border.c || 4240 cssDirectionChanged) 4241 ) { 4242 contentElementCSS[_strWidth] = _strAuto; 4243 contentGlueElementCSS[_strMaxMinus + _strWidth] = 4244 _strHundredPercent; //IE Fix 4245 } else if (widthAutoChanged || paddingAbsoluteChanged) { 4246 contentElementCSS[_strWidth] = _strHundredPercent; 4247 contentElementCSS[_strFloat] = _strEmpty; 4248 contentGlueElementCSS[_strMaxMinus + _strWidth] = _strEmpty; //IE Fix 4249 } 4250 if (widthAuto) { 4251 //textareaDynOrigSize.w || _strAuto :: doesnt works because applied margin will shift width 4252 contentGlueElementCSS[_strWidth] = _strAuto; 4253 4254 contentElementCSS[_strWidth] = 4255 VENDORS._cssPropertyValue(_strWidth, "max-content intrinsic") || 4256 _strAuto; 4257 contentElementCSS[_strFloat] = isRTLRight; 4258 } else { 4259 contentGlueElementCSS[_strWidth] = _strEmpty; 4260 } 4261 if (heightAuto) { 4262 //textareaDynOrigSize.h || _contentElementNative[LEXICON.cH] :: use for anti scroll jumping 4263 contentGlueElementCSS[_strHeight] = 4264 textareaDynOrigSize.h || _contentElementNative[LEXICON.cH]; 4265 } else { 4266 contentGlueElementCSS[_strHeight] = _strEmpty; 4267 } 4268 if (sizeAutoCapable) _contentGlueElement.css(contentGlueElementCSS); 4269 _contentElement.css(contentElementCSS); 4270 4271 //CHECKPOINT HERE ~ 4272 contentElementCSS = {}; 4273 contentGlueElementCSS = {}; 4274 4275 //if [content(host) client / scroll size, or target element direction, or content(host) max-sizes] changed, or force is true 4276 if ( 4277 hostSizeChanged || 4278 contentSizeChanged || 4279 textareaSizeChanged || 4280 cssDirectionChanged || 4281 boxSizingChanged || 4282 paddingAbsoluteChanged || 4283 widthAutoChanged || 4284 widthAuto || 4285 heightAutoChanged || 4286 heightAuto || 4287 ignoreOverlayScrollbarHidingChanged || 4288 overflowBehaviorChanged || 4289 clipAlwaysChanged || 4290 resizeChanged || 4291 scrollbarsVisibilityChanged || 4292 scrollbarsAutoHideChanged || 4293 scrollbarsDragScrollingChanged || 4294 scrollbarsClickScrollingChanged || 4295 textareaDynWidthChanged || 4296 textareaDynHeightChanged || 4297 textareaAutoWrappingChanged 4298 ) { 4299 var strOverflow = "overflow"; 4300 var strOverflowX = strOverflow + "-x"; 4301 var strOverflowY = strOverflow + "-y"; 4302 var strHidden = "hidden"; 4303 var strVisible = "visible"; 4304 4305 //Reset the viewport (very important for natively overlaid scrollbars and zoom change 4306 //don't change the overflow prop as it is very expensive and affects performance !A LOT! 4307 if (!_nativeScrollbarStyling) { 4308 var viewportElementResetCSS = {}; 4309 var resetXTmp = 4310 _hasOverflowCache.y && 4311 _hideOverflowCache.ys && 4312 !ignoreOverlayScrollbarHiding 4313 ? _nativeScrollbarIsOverlaid.y 4314 ? _viewportElement.css(isRTLLeft) 4315 : -_nativeScrollbarSize.y 4316 : 0; 4317 var resetBottomTmp = 4318 _hasOverflowCache.x && 4319 _hideOverflowCache.xs && 4320 !ignoreOverlayScrollbarHiding 4321 ? _nativeScrollbarIsOverlaid.x 4322 ? _viewportElement.css(_strBottom) 4323 : -_nativeScrollbarSize.x 4324 : 0; 4325 setTopRightBottomLeft(viewportElementResetCSS, _strEmpty); 4326 _viewportElement.css(viewportElementResetCSS); 4327 } 4328 4329 //measure several sizes: 4330 var contentMeasureElement = getContentMeasureElement(); 4331 //in Firefox content element has to have overflow hidden, else element margins aren't calculated properly, this element prevents this bug, but only if scrollbars aren't overlaid 4332 var contentSize = { 4333 //use clientSize because natively overlaidScrollbars add borders 4334 w: textareaDynOrigSize.w || contentMeasureElement[LEXICON.cW], 4335 h: textareaDynOrigSize.h || contentMeasureElement[LEXICON.cH], 4336 }; 4337 var scrollSize = { 4338 w: contentMeasureElement[LEXICON.sW], 4339 h: contentMeasureElement[LEXICON.sH], 4340 }; 4341 4342 //apply the correct viewport style and measure viewport size 4343 if (!_nativeScrollbarStyling) { 4344 viewportElementResetCSS[_strBottom] = wasHeightAuto 4345 ? _strEmpty 4346 : resetBottomTmp; 4347 viewportElementResetCSS[isRTLLeft] = wasWidthAuto 4348 ? _strEmpty 4349 : resetXTmp; 4350 _viewportElement.css(viewportElementResetCSS); 4351 } 4352 _viewportSize = getViewportSize(); 4353 4354 //measure and correct several sizes 4355 var hostSize = getHostSize(); 4356 var hostAbsoluteRectSize = { 4357 w: 4358 hostSize.w - 4359 _marginX - 4360 _borderX -
4361 (_isBorderBox ? 0 : _paddingX), 4362 h: 4363 hostSize.h - 4364 _marginY - 4365 _borderY - 4366 (_isBorderBox ? 0 : _paddingY), 4367 }; 4368 var contentGlueSize = { 4369 //client/scrollSize + AbsolutePadding -> because padding is only applied to the paddingElement if its absolute, so you have to add it manually 4370 //hostSize is clientSize -> so padding should be added manually, right? FALSE! Because content glue is inside hostElement, so we don't have to worry about padding 4371 w: MATH.max( 4372 (widthAuto ? contentSize.w : scrollSize.w) + paddingAbsoluteX, 4373 hostAbsoluteRectSize.w 4374 ), 4375 h: MATH.max( 4376 (heightAuto ? contentSize.h : scrollSize.h) + paddingAbsoluteY, 4377 hostAbsoluteRectSize.h 4378 ), 4379 }; 4380 contentGlueSize.c = checkCacheAutoForce( 4381 contentGlueSize, 4382 _contentGlueSizeCache 4383 ); 4384 _contentGlueSizeCache = contentGlueSize; 4385 4386 //apply correct contentGlue size 4387 if (sizeAutoCapable) { 4388 //size contentGlue correctly to make sure the element has correct size if the sizing switches to auto 4389 if (contentGlueSize.c || heightAuto || widthAuto) { 4390 contentGlueElementCSS[_strWidth] = contentGlueSize.w; 4391 contentGlueElementCSS[_strHeight] = contentGlueSize.h; 4392 4393 //textarea-sizes are already calculated correctly at this point 4394 if (!_isTextarea) { 4395 contentSize = { 4396 //use clientSize because natively overlaidScrollbars add borders 4397 w: contentMeasureElement[LEXICON.cW], 4398 h: contentMeasureElement[LEXICON.cH], 4399 }; 4400 } 4401 } 4402 var textareaCoverCSS = {}; 4403 var setContentGlueElementCSSfunction = function (horizontal) { 4404 var scrollbarVars = getScrollbarVars(horizontal); 4405 var wh = scrollbarVars._w_h; 4406 var strWH = scrollbarVars._width_height; 4407 var autoSize = horizontal ? widthAuto : heightAuto; 4408 var borderSize = horizontal ? _borderX : _borderY; 4409 var paddingSize = horizontal ? _paddingX : _paddingY; 4410 var marginSize = horizontal ? _marginX : _marginY; 4411 var viewportSize = 4412 _viewportSize[wh] - 4413 borderSize - 4414 marginSize - 4415 (_isBorderBox ? 0 : paddingSize); 4416 4417 //make contentGlue size -1 if element is not auto sized, to make sure that a resize event happens when the element shrinks 4418 if (!autoSize || (!autoSize && border.c)) 4419 contentGlueElementCSS[strWH] = hostAbsoluteRectSize[wh] - 1; 4420 4421 //if size is auto and host is smaller than size as min size, make content glue size -1 to make sure size changes will be detected (this is only needed if padding is 0) 4422 if ( 4423 autoSize && 4424 contentSize[wh] < viewportSize && 4425 (horizontal && _isTextarea ? !textareaAutoWrapping : true) 4426 ) { 4427 if (_isTextarea) 4428 textareaCoverCSS[strWH] = 4429 parseToZeroOrNumber(_textareaCoverElement.css(strWH)) - 1; 4430 contentGlueElementCSS[strWH] -= 1; 4431 } 4432 4433 //make sure content glue size is at least 1 4434 if (contentSize[wh] > 0) 4435 contentGlueElementCSS[strWH] = MATH.max( 4436 1, 4437 contentGlueElementCSS[strWH] 4438 ); 4439 }; 4440 setContentGlueElementCSSfunction(true); 4441 setContentGlueElementCSSfunction(false); 4442 4443 if (_isTextarea) _textareaCoverElement.css(textareaCoverCSS); 4444 _contentGlueElement.css(contentGlueElementCSS); 4445 } 4446 if (widthAuto) contentElementCSS[_strWidth] = _strHundredPercent; 4447 if (widthAuto && !_isBorderBox && !_mutationObserversConnected) 4448 contentElementCSS[_strFloat] = "none"; 4449 4450 //apply and reset content style 4451 _contentElement.css(contentElementCSS); 4452 contentElementCSS = {}; 4453
vendor: 8,629 bytes, lines 4454-4650
4454 //measure again, but this time all correct sizes: 4455 var contentScrollSize = { 4456 w: contentMeasureElement[LEXICON.sW], 4457 h: contentMeasureElement[LEXICON.sH], 4458 }; 4459 contentScrollSize.c = contentSizeChanged = checkCacheAutoForce( 4460 contentScrollSize, 4461 _contentScrollSizeCache 4462 ); 4463 _contentScrollSizeCache = contentScrollSize; 4464 4465 //refresh viewport size after correct measuring 4466 _viewportSize = getViewportSize(); 4467 4468 hostSize = getHostSize(); 4469 hostSizeChanged = checkCacheAutoForce(hostSize, _hostSizeCache); 4470 _hostSizeCache = hostSize; 4471 4472 var hideOverflowForceTextarea = 4473 _isTextarea && (_viewportSize.w === 0 || _viewportSize.h === 0); 4474 var previousOverflowAmount = _overflowAmountCache; 4475 var overflowBehaviorIsVS = {}; 4476 var overflowBehaviorIsVH = {}; 4477 var overflowBehaviorIsS = {}; 4478 var overflowAmount = {}; 4479 var hasOverflow = {}; 4480 var hideOverflow = {}; 4481 var canScroll = {}; 4482 var viewportRect = _paddingElementNative[LEXICON.bCR](); 4483 var setOverflowVariables = function (horizontal) { 4484 var scrollbarVars = getScrollbarVars(horizontal); 4485 var scrollbarVarsInverted = getScrollbarVars(!horizontal); 4486 var xyI = scrollbarVarsInverted._x_y; 4487 var xy = scrollbarVars._x_y; 4488 var wh = scrollbarVars._w_h; 4489 var widthHeight = scrollbarVars._width_height; 4490 var scrollMax = _strScroll + scrollbarVars._Left_Top + "Max"; 4491 var fractionalOverflowAmount = viewportRect[widthHeight] 4492 ? MATH.abs(viewportRect[widthHeight] - _viewportSize[wh]) 4493 : 0; 4494 var checkFractionalOverflowAmount = 4495 previousOverflowAmount && 4496 previousOverflowAmount[xy] > 0 && 4497 _viewportElementNative[scrollMax] === 0; 4498 overflowBehaviorIsVS[xy] = overflowBehavior[xy] === "v-s"; 4499 overflowBehaviorIsVH[xy] = overflowBehavior[xy] === "v-h"; 4500 overflowBehaviorIsS[xy] = overflowBehavior[xy] === "s"; 4501 overflowAmount[xy] = MATH.max( 4502 0, 4503 MATH.round((contentScrollSize[wh] - _viewportSize[wh]) * 100) / 4504 100 4505 ); 4506 overflowAmount[xy] *= 4507 hideOverflowForceTextarea || 4508 (checkFractionalOverflowAmount && 4509 fractionalOverflowAmount > 0 && 4510 fractionalOverflowAmount < 1) 4511 ? 0 4512 : 1; 4513 hasOverflow[xy] = overflowAmount[xy] > 0; 4514 4515 //hideOverflow: 4516 //x || y : true === overflow is hidden by "overflow: scroll" OR "overflow: hidden" 4517 //xs || ys : true === overflow is hidden by "overflow: scroll" 4518 hideOverflow[xy] = 4519 overflowBehaviorIsVS[xy] || overflowBehaviorIsVH[xy] 4520 ? hasOverflow[xyI] && 4521 !overflowBehaviorIsVS[xyI] && 4522 !overflowBehaviorIsVH[xyI] 4523 : hasOverflow[xy]; 4524 hideOverflow[xy + "s"] = hideOverflow[xy] 4525 ? overflowBehaviorIsS[xy] || overflowBehaviorIsVS[xy] 4526 : false; 4527 4528 canScroll[xy] = hasOverflow[xy] && hideOverflow[xy + "s"]; 4529 }; 4530 setOverflowVariables(true); 4531 setOverflowVariables(false); 4532 4533 overflowAmount.c = checkCacheAutoForce( 4534 overflowAmount, 4535 _overflowAmountCache 4536 ); 4537 _overflowAmountCache = overflowAmount; 4538 hasOverflow.c = checkCacheAutoForce(hasOverflow, _hasOverflowCache); 4539 _hasOverflowCache = hasOverflow; 4540 hideOverflow.c = checkCacheAutoForce( 4541 hideOverflow, 4542 _hideOverflowCache 4543 ); 4544 _hideOverflowCache = hideOverflow; 4545 4546 //if native scrollbar is overlay at x OR y axis, prepare DOM 4547 if (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y) { 4548 var borderDesign = "px solid transparent"; 4549 var contentArrangeElementCSS = {}; 4550 var arrangeContent = {}; 4551 var arrangeChanged = force; 4552 var setContentElementCSS; 4553 4554 if (hasOverflow.x || hasOverflow.y) { 4555 arrangeContent.w = 4556 _nativeScrollbarIsOverlaid.y && hasOverflow.y 4557 ? contentScrollSize.w + _overlayScrollbarDummySize.y 4558 : _strEmpty; 4559 arrangeContent.h = 4560 _nativeScrollbarIsOverlaid.x && hasOverflow.x 4561 ? contentScrollSize.h + _overlayScrollbarDummySize.x 4562 : _strEmpty; 4563 arrangeChanged = checkCacheAutoForce( 4564 arrangeContent, 4565 _arrangeContentSizeCache 4566 ); 4567 _arrangeContentSizeCache = arrangeContent; 4568 } 4569 4570 if ( 4571 hasOverflow.c || 4572 hideOverflow.c || 4573 contentScrollSize.c || 4574 cssDirectionChanged || 4575 widthAutoChanged || 4576 heightAutoChanged || 4577 widthAuto || 4578 heightAuto || 4579 ignoreOverlayScrollbarHidingChanged 4580 ) { 4581 contentElementCSS[_strMarginMinus + isRTLRight] = 4582 contentElementCSS[_strBorderMinus + isRTLRight] = _strEmpty; 4583 setContentElementCSS = function (horizontal) { 4584 var scrollbarVars = getScrollbarVars(horizontal); 4585 var scrollbarVarsInverted = getScrollbarVars(!horizontal); 4586 var xy = scrollbarVars._x_y; 4587 var strDirection = horizontal ? _strBottom : isRTLLeft; 4588 var invertedAutoSize = horizontal ? heightAuto : widthAuto; 4589 4590 if ( 4591 _nativeScrollbarIsOverlaid[xy] && 4592 hasOverflow[xy] && 4593 hideOverflow[xy + "s"] 4594 ) { 4595 contentElementCSS[_strMarginMinus + strDirection] = 4596 invertedAutoSize 4597 ? ignoreOverlayScrollbarHiding 4598 ? _strEmpty 4599 : _overlayScrollbarDummySize[xy] 4600 : _strEmpty; 4601 contentElementCSS[_strBorderMinus + strDirection] = 4602 (horizontal ? !invertedAutoSize : true) && 4603 !ignoreOverlayScrollbarHiding 4604 ? _overlayScrollbarDummySize[xy] + borderDesign 4605 : _strEmpty; 4606 } else { 4607 arrangeContent[scrollbarVarsInverted._w_h] = 4608 contentElementCSS[_strMarginMinus + strDirection] = 4609 contentElementCSS[_strBorderMinus + strDirection] = 4610 _strEmpty; 4611 arrangeChanged = true; 4612 } 4613 }; 4614 4615 if (_nativeScrollbarStyling) { 4616 addRemoveClass( 4617 _viewportElement, 4618 _classNameViewportNativeScrollbarsInvisible, 4619 !ignoreOverlayScrollbarHiding 4620 ); 4621 } else { 4622 setContentElementCSS(true); 4623 setContentElementCSS(false); 4624 } 4625 } 4626 if (ignoreOverlayScrollbarHiding) { 4627 arrangeContent.w = arrangeContent.h = _strEmpty; 4628 arrangeChanged = true; 4629 } 4630 if (arrangeChanged && !_nativeScrollbarStyling) { 4631 contentArrangeElementCSS[_strWidth] = hideOverflow.y 4632 ? arrangeContent.w 4633 : _strEmpty; 4634 contentArrangeElementCSS[_strHeight] = hideOverflow.x 4635 ? arrangeContent.h 4636 : _strEmpty; 4637 4638 if (!_contentArrangeElement) { 4639 _contentArrangeElement = FRAMEWORK( 4640 generateDiv(_classNameContentArrangeElement) 4641 ); 4642 _viewportElement.prepend(_contentArrangeElement); 4643 } 4644 _contentArrangeElement.css(contentArrangeElementCSS); 4645 } 4646 _contentElement.css(contentElementCSS); 4647 } 4648 4649 var viewportElementCSS = {}; 4650 var paddingElementCSS = {};
4651 var setViewportCSS; 4652 if ( 4653 hostSizeChanged || 4654 hasOverflow.c || 4655 hideOverflow.c || 4656 contentScrollSize.c || 4657 overflowBehaviorChanged || 4658 boxSizingChanged || 4659 ignoreOverlayScrollbarHidingChanged || 4660 cssDirectionChanged || 4661 clipAlwaysChanged || 4662 heightAutoChanged 4663 ) { 4664 viewportElementCSS[isRTLRight] = _strEmpty; 4665 setViewportCSS = function (horizontal) { 4666 var scrollbarVars = getScrollbarVars(horizontal); 4667 var scrollbarVarsInverted = getScrollbarVars(!horizontal); 4668 var xy = scrollbarVars._x_y; 4669 var XY = scrollbarVars._X_Y; 4670 var strDirection = horizontal ? _strBottom : isRTLLeft; 4671 4672 var reset = function () { 4673 viewportElementCSS[strDirection] = _strEmpty; 4674 _contentBorderSize[scrollbarVarsInverted._w_h] = 0; 4675 }; 4676 if (hasOverflow[xy] && hideOverflow[xy + "s"]) { 4677 viewportElementCSS[strOverflow + XY] = _strScroll; 4678 if (ignoreOverlayScrollbarHiding || _nativeScrollbarStyling) { 4679 reset(); 4680 } else { 4681 viewportElementCSS[strDirection] = 4682 -(_nativeScrollbarIsOverlaid[xy] 4683 ? _overlayScrollbarDummySize[xy] 4684 : _nativeScrollbarSize[xy]); 4685 _contentBorderSize[scrollbarVarsInverted._w_h] = 4686 _nativeScrollbarIsOverlaid[xy] 4687 ? _overlayScrollbarDummySize[scrollbarVarsInverted._x_y] 4688 : 0; 4689 } 4690 } else { 4691 viewportElementCSS[strOverflow + XY] = _strEmpty; 4692 reset(); 4693 } 4694 }; 4695 setViewportCSS(true); 4696 setViewportCSS(false); 4697 4698 // if the scroll container is too small and if there is any overflow with no overlay scrollbar (and scrollbar styling isn't possible), 4699 // make viewport element greater in size (Firefox hide Scrollbars fix) 4700 // because firefox starts hiding scrollbars on too small elements 4701 // with this behavior the overflow calculation may be incorrect or the scrollbars would appear suddenly 4702 // https://bugzilla.mozilla.org/show_bug.cgi?id=292284 4703 if ( 4704 !_nativeScrollbarStyling && 4705 (_viewportSize.h < _nativeScrollbarMinSize.x || 4706 _viewportSize.w < _nativeScrollbarMinSize.y) && 4707 ((hasOverflow.x && 4708 hideOverflow.x && 4709 !_nativeScrollbarIsOverlaid.x) || 4710 (hasOverflow.y && 4711 hideOverflow.y && 4712 !_nativeScrollbarIsOverlaid.y)) 4713 ) { 4714 viewportElementCSS[_strPaddingMinus + _strTop] = 4715 _nativeScrollbarMinSize.x; 4716 viewportElementCSS[_strMarginMinus + _strTop] = 4717 -_nativeScrollbarMinSize.x; 4718 4719 viewportElementCSS[_strPaddingMinus + isRTLRight] = 4720 _nativeScrollbarMinSize.y; 4721 viewportElementCSS[_strMarginMinus + isRTLRight] = 4722 -_nativeScrollbarMinSize.y; 4723 } else { 4724 viewportElementCSS[_strPaddingMinus + _strTop] = 4725 viewportElementCSS[_strMarginMinus + _strTop] = 4726 viewportElementCSS[_strPaddingMinus + isRTLRight] = 4727 viewportElementCSS[_strMarginMinus + isRTLRight] = 4728 _strEmpty; 4729 } 4730 viewportElementCSS[_strPaddingMinus + isRTLLeft] = 4731 viewportElementCSS[_strMarginMinus + isRTLLeft] = _strEmpty; 4732 4733 //if there is any overflow (x OR y axis) and this overflow shall be hidden, make overflow hidden, else overflow visible 4734 if ( 4735 (hasOverflow.x && hideOverflow.x) || 4736 (hasOverflow.y && hideOverflow.y) || 4737 hideOverflowForceTextarea 4738 ) { 4739 //only hide if is Textarea 4740 if (_isTextarea && hideOverflowForceTextarea) { 4741 paddingElementCSS[strOverflowX] = paddingElementCSS[ 4742 strOverflowY 4743 ] = strHidden; 4744 } 4745 } else { 4746 if ( 4747 !clipAlways || 4748 overflowBehaviorIsVH.x || 4749 overflowBehaviorIsVS.x || 4750 overflowBehaviorIsVH.y || 4751 overflowBehaviorIsVS.y 4752 ) { 4753 //only un-hide if Textarea 4754 if (_isTextarea) { 4755 paddingElementCSS[strOverflowX] = paddingElementCSS[ 4756 strOverflowY 4757 ] = _strEmpty; 4758 } 4759 viewportElementCSS[strOverflowX] = viewportElementCSS[ 4760 strOverflowY 4761 ] = strVisible; 4762 } 4763 } 4764 4765 _paddingElement.css(paddingElementCSS); 4766 _viewportElement.css(viewportElementCSS); 4767 viewportElementCSS = {}; 4768 4769 //force soft redraw in webkit because without the scrollbars will may appear because DOM wont be redrawn under special conditions 4770 if ( 4771 (hasOverflow.c || 4772 boxSizingChanged || 4773 widthAutoChanged || 4774 heightAutoChanged) && 4775 !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y) 4776 ) { 4777 var elementStyle = _contentElementNative[LEXICON.s]; 4778 var dump; 4779 elementStyle.webkitTransform = "scale(1)"; 4780 elementStyle.display = "run-in"; 4781 dump = _contentElementNative[LEXICON.oH]; 4782 elementStyle.display = _strEmpty; //|| dump; //use dump to prevent it from deletion if minify 4783 elementStyle.webkitTransform = _strEmpty; 4784 } 4785 /* 4786 //force hard redraw in webkit if native overlaid scrollbars shall appear 4787 if (ignoreOverlayScrollbarHidingChanged && ignoreOverlayScrollbarHiding) { 4788 _hostElement.hide(); 4789 var dump = _hostElementNative[LEXICON.oH]; 4790 _hostElement.show(); 4791 } 4792 */ 4793 } 4794 4795 //change to direction RTL and width auto Bugfix in Webkit 4796 //without this fix, the DOM still thinks the scrollbar is LTR and thus the content is shifted to the left 4797 contentElementCSS = {}; 4798 if (cssDirectionChanged || widthAutoChanged || heightAutoChanged) { 4799 if (_isRTL && widthAuto) { 4800 var floatTmp = _contentElement.css(_strFloat); 4801 var posLeftWithoutFloat = MATH.round( 4802 _contentElement 4803 .css(_strFloat, _strEmpty) 4804 .css(_strLeft, _strEmpty) 4805 .position().left 4806 ); 4807 _contentElement.css(_strFloat, floatTmp); 4808 var posLeftWithFloat = MATH.round( 4809 _contentElement.position().left 4810 ); 4811 4812 if (posLeftWithoutFloat !== posLeftWithFloat) 4813 contentElementCSS[_strLeft] = posLeftWithoutFloat; 4814 } else { 4815 contentElementCSS[_strLeft] = _strEmpty; 4816 } 4817 } 4818 _contentElement.css(contentElementCSS); 4819 4820 //handle scroll position 4821 if (_isTextarea && contentSizeChanged) { 4822 var textareaInfo = getTextareaInfo(); 4823 if (textareaInfo) { 4824 var textareaRowsChanged = 4825 _textareaInfoCache === undefined 4826 ? true 4827 : textareaInfo._rows !== _textareaInfoCache._rows; 4828 var cursorRow = textareaInfo._cursorRow; 4829 var cursorCol = textareaInfo._cursorColumn; 4830 var widestRow = textareaInfo._widestRow; 4831 var lastRow = textareaInfo._rows; 4832 var lastCol = textareaInfo._columns;
4833 var cursorPos = textareaInfo._cursorPosition; 4834 var cursorMax = textareaInfo._cursorMax; 4835 var cursorIsLastPosition = 4836 cursorPos >= cursorMax && _textareaHasFocus; 4837 var textareaScrollAmount = { 4838 x: 4839 !textareaAutoWrapping && 4840 cursorCol === lastCol && 4841 cursorRow === widestRow 4842 ? _overflowAmountCache.x 4843 : -1, 4844 y: ( 4845 textareaAutoWrapping 4846 ? cursorIsLastPosition || 4847 (textareaRowsChanged && 4848 (previousOverflowAmount 4849 ? currScroll.y === previousOverflowAmount.y 4850 : false)) 4851 : (cursorIsLastPosition || textareaRowsChanged) && 4852 cursorRow === lastRow 4853 ) 4854 ? _overflowAmountCache.y 4855 : -1, 4856 }; 4857 currScroll.x = 4858 textareaScrollAmount.x > -1 4859 ? _isRTL && _normalizeRTLCache && _rtlScrollBehavior.i 4860 ? 0 4861 : textareaScrollAmount.x 4862 : currScroll.x; //if inverted, scroll to 0 -> normalized this means to max scroll offset. 4863 currScroll.y = 4864 textareaScrollAmount.y > -1 4865 ? textareaScrollAmount.y 4866 : currScroll.y; 4867 } 4868 _textareaInfoCache = textareaInfo; 4869 } 4870 if ( 4871 _isRTL && 4872 _rtlScrollBehavior.i && 4873 _nativeScrollbarIsOverlaid.y && 4874 hasOverflow.x && 4875 _normalizeRTLCache 4876 ) 4877 currScroll.x += _contentBorderSize.w || 0; 4878 if (widthAuto) _hostElement[_strScrollLeft](0); 4879 if (heightAuto) _hostElement[_strScrollTop](0); 4880 _viewportElement[_strScrollLeft](currScroll.x)[_strScrollTop]( 4881 currScroll.y 4882 ); 4883 4884 //scrollbars management: 4885 var scrollbarsVisibilityVisible = scrollbarsVisibility === "v"; 4886 var scrollbarsVisibilityHidden = scrollbarsVisibility === "h"; 4887 var scrollbarsVisibilityAuto = scrollbarsVisibility === "a"; 4888 var refreshScrollbarsVisibility = function (showX, showY) { 4889 showY = showY === undefined ? showX : showY; 4890 refreshScrollbarAppearance(true, showX, canScroll.x); 4891 refreshScrollbarAppearance(false, showY, canScroll.y); 4892 }; 4893 4894 //manage class name which indicates scrollable overflow 4895 addRemoveClass( 4896 _hostElement, 4897 _classNameHostOverflow, 4898 hideOverflow.x || hideOverflow.y 4899 ); 4900 addRemoveClass( 4901 _hostElement, 4902 _classNameHostOverflowX, 4903 hideOverflow.x 4904 ); 4905 addRemoveClass( 4906 _hostElement, 4907 _classNameHostOverflowY, 4908 hideOverflow.y 4909 ); 4910 4911 //add or remove rtl class name for styling purposes except when its body, then the scrollbar stays 4912 if (cssDirectionChanged && !_isBody) { 4913 addRemoveClass(_hostElement, _classNameHostRTL, _isRTL); 4914 } 4915 4916 //manage the resize feature (CSS3 resize "polyfill" for this plugin) 4917 if (_isBody) addClass(_hostElement, _classNameHostResizeDisabled); 4918 if (resizeChanged) { 4919 addRemoveClass( 4920 _hostElement, 4921 _classNameHostResizeDisabled, 4922 _resizeNone 4923 ); 4924 addRemoveClass( 4925 _scrollbarCornerElement, 4926 _classNameScrollbarCornerResize, 4927 !_resizeNone 4928 ); 4929 addRemoveClass( 4930 _scrollbarCornerElement, 4931 _classNameScrollbarCornerResizeB, 4932 _resizeBoth 4933 ); 4934 addRemoveClass( 4935 _scrollbarCornerElement, 4936 _classNameScrollbarCornerResizeH, 4937 _resizeHorizontal 4938 ); 4939 addRemoveClass( 4940 _scrollbarCornerElement, 4941 _classNameScrollbarCornerResizeV, 4942 _resizeVertical 4943 ); 4944 } 4945 4946 //manage the scrollbars general visibility + the scrollbar interactivity (unusable class name) 4947 if ( 4948 scrollbarsVisibilityChanged || 4949 overflowBehaviorChanged || 4950 hideOverflow.c || 4951 hasOverflow.c || 4952 ignoreOverlayScrollbarHidingChanged 4953 ) { 4954 if (ignoreOverlayScrollbarHiding) { 4955 if (ignoreOverlayScrollbarHidingChanged) { 4956 removeClass(_hostElement, _classNameHostScrolling); 4957 if (ignoreOverlayScrollbarHiding) { 4958 refreshScrollbarsVisibility(false); 4959 } 4960 } 4961 } else if (scrollbarsVisibilityAuto) { 4962 refreshScrollbarsVisibility(canScroll.x, canScroll.y); 4963 } else if (scrollbarsVisibilityVisible) { 4964 refreshScrollbarsVisibility(true); 4965 } else if (scrollbarsVisibilityHidden) { 4966 refreshScrollbarsVisibility(false); 4967 } 4968 } 4969 4970 //manage the scrollbars auto hide feature (auto hide them after specific actions) 4971 if ( 4972 scrollbarsAutoHideChanged || 4973 ignoreOverlayScrollbarHidingChanged 4974 ) { 4975 setupHostMouseTouchEvents( 4976 !_scrollbarsAutoHideLeave && !_scrollbarsAutoHideMove 4977 ); 4978 refreshScrollbarsAutoHide( 4979 _scrollbarsAutoHideNever, 4980 !_scrollbarsAutoHideNever 4981 ); 4982 } 4983 4984 //manage scrollbars handle length & offset - don't remove! 4985 if ( 4986 hostSizeChanged || 4987 overflowAmount.c || 4988 heightAutoChanged || 4989 widthAutoChanged || 4990 resizeChanged || 4991 boxSizingChanged || 4992 paddingAbsoluteChanged || 4993 ignoreOverlayScrollbarHidingChanged || 4994 cssDirectionChanged 4995 ) { 4996 refreshScrollbarHandleLength(true); 4997 refreshScrollbarHandleOffset(true); 4998 refreshScrollbarHandleLength(false); 4999 refreshScrollbarHandleOffset(false); 5000 } 5001 5002 //manage interactivity 5003 if (scrollbarsClickScrollingChanged) 5004 refreshScrollbarsInteractive(true, scrollbarsClickScrolling); 5005 if (scrollbarsDragScrollingChanged) 5006 refreshScrollbarsInteractive(false, scrollbarsDragScrolling); 5007 5008 //callbacks: 5009 dispatchCallback( 5010 "onDirectionChanged", 5011 { 5012 isRTL: _isRTL, 5013 dir: cssDirection, 5014 }, 5015 cssDirectionChanged 5016 ); 5017 dispatchCallback( 5018 "onHostSizeChanged", 5019 { 5020 width: _hostSizeCache.w, 5021 height: _hostSizeCache.h, 5022 }, 5023 hostSizeChanged 5024 ); 5025 dispatchCallback( 5026 "onContentSizeChanged", 5027 { 5028 width: _contentScrollSizeCache.w, 5029 height: _contentScrollSizeCache.h, 5030 }, 5031 contentSizeChanged 5032 ); 5033 dispatchCallback( 5034 "onOverflowChanged", 5035 { 5036 x: hasOverflow.x, 5037 y: hasOverflow.y, 5038 xScrollable: hideOverflow.xs, 5039 yScrollable: hideOverflow.ys, 5040 clipped: hideOverflow.x || hideOverflow.y, 5041 }, 5042 hasOverflow.c || hideOverflow.c 5043 ); 5044 dispatchCallback( 5045 "onOverflowAmountChanged", 5046 { 5047 x: overflowAmount.x, 5048 y: overflowAmount.y, 5049 }, 5050 overflowAmount.c 5051 ); 5052 } 5053 5054 //fix body min size 5055 if ( 5056 _isBody && 5057 _bodyMinSizeCache && 5058 (_hasOverflowCache.c || _bodyMinSizeCache.c) 5059 ) { 5060 //its possible that no min size was measured until now, because the content arrange element was just added now, in this case, measure now the min size. 5061 if (!_bodyMinSizeCache.f) bodyMinSizeChanged(); 5062 if (_nativeScrollbarIsOverlaid.y && _hasOverflowCache.x) 5063 _contentElement.css( 5064 _strMinMinus + _strWidth, 5065 _bodyMinSizeCache.w + _overlayScrollbarDummySize.y 5066 ); 5067 if (_nativeScrollbarIsOverlaid.x && _hasOverflowCache.y) 5068 _contentElement.css( 5069 _strMinMinus + _strHeight, 5070 _bodyMinSizeCache.h + _overlayScrollbarDummySize.x 5071 ); 5072 _bodyMinSizeCache.c = false;
vendor: 24,393 bytes, lines 5073-5735
5073 } 5074 5075 if (_initialized && changedOptions.updateOnLoad) { 5076 updateElementsOnLoad(); 5077 } 5078 5079 //freezeResizeObserver(_sizeObserverElement, false); 5080 //freezeResizeObserver(_sizeAutoObserverElement, false); 5081 5082 dispatchCallback("onUpdated", { forced: force }); 5083 } 5084 5085 /** 5086 * Updates the found elements of which the load event shall be handled. 5087 */ 5088 function updateElementsOnLoad() { 5089 if (!_isTextarea) { 5090 eachUpdateOnLoad(function (i, updateOnLoadSelector) { 5091 _contentElement.find(updateOnLoadSelector).each(function (i, el) { 5092 // if element doesn't have a updateOnLoadCallback applied 5093 if (COMPATIBILITY.inA(el, _updateOnLoadElms) < 0) { 5094 _updateOnLoadElms.push(el); 5095 FRAMEWORK(el) 5096 .off(_updateOnLoadEventName, updateOnLoadCallback) 5097 .on(_updateOnLoadEventName, updateOnLoadCallback); 5098 } 5099 }); 5100 }); 5101 } 5102 } 5103 5104 //==== Options ====// 5105 5106 /** 5107 * Sets new options but doesn't call the update method. 5108 * @param newOptions The object which contains the new options. 5109 * @returns {*} A object which contains the changed options. 5110 */ 5111 function setOptions(newOptions) { 5112 var validatedOpts = _pluginsOptions._validate( 5113 newOptions, 5114 _pluginsOptions._template, 5115 true, 5116 _currentOptions 5117 ); 5118 5119 _currentOptions = extendDeep( 5120 {}, 5121 _currentOptions, 5122 validatedOpts._default 5123 ); 5124 _currentPreparedOptions = extendDeep( 5125 {}, 5126 _currentPreparedOptions, 5127 validatedOpts._prepared 5128 ); 5129 5130 return validatedOpts._prepared; 5131 } 5132 5133 //==== Structure ====// 5134 5135 /** 5136 * Builds or destroys the wrapper and helper DOM elements. 5137 * @param destroy Indicates whether the DOM shall be build or destroyed. 5138 */ 5139 /** 5140 * Builds or destroys the wrapper and helper DOM elements. 5141 * @param destroy Indicates whether the DOM shall be build or destroyed. 5142 */ 5143 function setupStructureDOM(destroy) { 5144 var strParent = "parent"; 5145 var classNameResizeObserverHost = "os-resize-observer-host"; 5146 var classNameTextareaElementFull = 5147 _classNameTextareaElement + _strSpace + _classNameTextInherit; 5148 var textareaClass = _isTextarea 5149 ? _strSpace + _classNameTextInherit 5150 : _strEmpty; 5151 var adoptAttrs = _currentPreparedOptions.textarea.inheritedAttrs; 5152 var adoptAttrsMap = {}; 5153 var applyAdoptedAttrs = function () { 5154 var applyAdoptedAttrsElm = destroy ? _targetElement : _hostElement; 5155 each(adoptAttrsMap, function (key, value) { 5156 if (type(value) == TYPES.s) { 5157 if (key == LEXICON.c) applyAdoptedAttrsElm.addClass(value); 5158 else applyAdoptedAttrsElm.attr(key, value); 5159 } 5160 }); 5161 }; 5162 var hostElementClassNames = [ 5163 _classNameHostElement, 5164 _classNameHostElementForeign, 5165 _classNameHostTextareaElement, 5166 _classNameHostResizeDisabled, 5167 _classNameHostRTL, 5168 _classNameHostScrollbarHorizontalHidden, 5169 _classNameHostScrollbarVerticalHidden, 5170 _classNameHostTransition, 5171 _classNameHostScrolling, 5172 _classNameHostOverflow, 5173 _classNameHostOverflowX, 5174 _classNameHostOverflowY, 5175 _classNameThemeNone, 5176 _classNameTextareaElement, 5177 _classNameTextInherit, 5178 _classNameCache, 5179 ].join(_strSpace); 5180 var hostElementCSS = {}; 5181 5182 //get host element as first element, because that's the most upper element and required for the other elements 5183 _hostElement = 5184 _hostElement || 5185 (_isTextarea 5186 ? _domExists 5187 ? _targetElement[strParent]() 5188 [strParent]() 5189 [strParent]() 5190 [strParent]() 5191 : FRAMEWORK(generateDiv(_classNameHostTextareaElement)) 5192 : _targetElement); 5193 _contentElement = 5194 _contentElement || 5195 selectOrGenerateDivByClass( 5196 _classNameContentElement + textareaClass 5197 ); 5198 _viewportElement = 5199 _viewportElement || 5200 selectOrGenerateDivByClass( 5201 _classNameViewportElement + textareaClass 5202 ); 5203 _paddingElement = 5204 _paddingElement || 5205 selectOrGenerateDivByClass( 5206 _classNamePaddingElement + textareaClass 5207 ); 5208 _sizeObserverElement = 5209 _sizeObserverElement || 5210 selectOrGenerateDivByClass(classNameResizeObserverHost); 5211 _textareaCoverElement = 5212 _textareaCoverElement || 5213 (_isTextarea 5214 ? selectOrGenerateDivByClass(_classNameTextareaCoverElement) 5215 : undefined); 5216 5217 //add this class to workaround class changing issues with UI frameworks especially Vue 5218 if (_domExists) addClass(_hostElement, _classNameHostElementForeign); 5219 5220 //on destroy, remove all generated class names from the host element before collecting the adopted attributes 5221 //to prevent adopting generated class names 5222 if (destroy) removeClass(_hostElement, hostElementClassNames); 5223 5224 //collect all adopted attributes 5225 adoptAttrs = 5226 type(adoptAttrs) == TYPES.s 5227 ? adoptAttrs.split(_strSpace) 5228 : adoptAttrs; 5229 if (COMPATIBILITY.isA(adoptAttrs) && _isTextarea) { 5230 each(adoptAttrs, function (i, v) { 5231 if (type(v) == TYPES.s) { 5232 adoptAttrsMap[v] = destroy 5233 ? _hostElement.attr(v) 5234 : _targetElement.attr(v); 5235 } 5236 }); 5237 } 5238 5239 if (!destroy) { 5240 if (_isTextarea) { 5241 if (!_currentPreparedOptions.sizeAutoCapable) { 5242 hostElementCSS[_strWidth] = _targetElement.css(_strWidth); 5243 hostElementCSS[_strHeight] = _targetElement.css(_strHeight); 5244 } 5245 5246 if (!_domExists) 5247 _targetElement 5248 .addClass(_classNameTextInherit) 5249 .wrap(_hostElement); 5250 5251 //jQuery clones elements in wrap functions, so we have to select them again 5252 _hostElement = _targetElement[strParent]().css(hostElementCSS); 5253 } 5254 5255 if (!_domExists) { 5256 //add the correct class to the target element 5257 addClass( 5258 _targetElement, 5259 _isTextarea 5260 ? classNameTextareaElementFull 5261 : _classNameHostElement 5262 ); 5263 5264 //wrap the content into the generated elements to create the required DOM 5265 _hostElement 5266 .wrapInner(_contentElement) 5267 .wrapInner(_viewportElement) 5268 .wrapInner(_paddingElement) 5269 .prepend(_sizeObserverElement); 5270 5271 //jQuery clones elements in wrap functions, so we have to select them again 5272 _contentElement = findFirst( 5273 _hostElement, 5274 _strDot + _classNameContentElement 5275 ); 5276 _viewportElement = findFirst( 5277 _hostElement, 5278 _strDot + _classNameViewportElement 5279 ); 5280 _paddingElement = findFirst( 5281 _hostElement, 5282 _strDot + _classNamePaddingElement 5283 ); 5284 5285 if (_isTextarea) { 5286 _contentElement.prepend(_textareaCoverElement); 5287 applyAdoptedAttrs(); 5288 } 5289 } 5290 5291 if (_nativeScrollbarStyling) 5292 addClass( 5293 _viewportElement, 5294 _classNameViewportNativeScrollbarsInvisible 5295 ); 5296 if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y) 5297 addClass( 5298 _viewportElement, 5299 _classNameViewportNativeScrollbarsOverlaid 5300 ); 5301 if (_isBody) addClass(_htmlElement, _classNameHTMLElement); 5302 5303 _sizeObserverElementNative = _sizeObserverElement[0]; 5304 _hostElementNative = _hostElement[0]; 5305 _paddingElementNative = _paddingElement[0]; 5306 _viewportElementNative = _viewportElement[0]; 5307 _contentElementNative = _contentElement[0]; 5308 5309 updateViewportAttrsFromTarget(); 5310 } else { 5311 if (_domExists && _initialized) { 5312 //clear size observer 5313 _sizeObserverElement.children().remove(); 5314 5315 //remove the style property and classes from already generated elements 5316 each( 5317 [ 5318 _paddingElement, 5319 _viewportElement, 5320 _contentElement, 5321 _textareaCoverElement, 5322 ], 5323 function (i, elm) { 5324 if (elm) { 5325 removeClass( 5326 elm.removeAttr(LEXICON.s), 5327 _classNamesDynamicDestroy 5328 ); 5329 } 5330 } 5331 ); 5332 5333 //add classes to the host element which was removed previously to match the expected DOM 5334 addClass( 5335 _hostElement, 5336 _isTextarea 5337 ? _classNameHostTextareaElement 5338 : _classNameHostElement 5339 ); 5340 } else { 5341 //remove size observer 5342 remove(_sizeObserverElement); 5343 5344 //unwrap the content to restore DOM 5345 _contentElement.contents().unwrap().unwrap().unwrap(); 5346 5347 if (_isTextarea) { 5348 _targetElement.unwrap(); 5349 remove(_hostElement); 5350 remove(_textareaCoverElement); 5351 applyAdoptedAttrs(); 5352 } 5353 } 5354 5355 if (_isTextarea) _targetElement.removeAttr(LEXICON.s); 5356 5357 if (_isBody) removeClass(_htmlElement, _classNameHTMLElement); 5358 } 5359 } 5360 5361 /** 5362 * Adds or removes all wrapper elements interactivity events. 5363 * @param destroy Indicates whether the Events shall be added or removed. 5364 */ 5365 function setupStructureEvents() { 5366 var textareaKeyDownRestrictedKeyCodes = [ 5367 112, 5368 113, 5369 114, 5370 115, 5371 116, 5372 117, 5373 118, 5374 119, 5375 120, 5376 121, 5377 123, //F1 to F12 5378 33, 5379 34, //page up, page down 5380 37, 5381 38, 5382 39, 5383 40, //left, up, right, down arrows 5384 16, 5385 17, 5386 18, 5387 19, 5388 20, 5389 144, //Shift, Ctrl, Alt, Pause, CapsLock, NumLock 5390 ]; 5391 var textareaKeyDownKeyCodesList = []; 5392 var textareaUpdateIntervalID; 5393 var scrollStopTimeoutId; 5394 var scrollStopDelay = 175; 5395 var strFocus = "focus"; 5396 5397 function updateTextarea(doClearInterval) { 5398 textareaUpdate(); 5399 _base.update(_strAuto); 5400 if (doClearInterval && _autoUpdateRecommended) 5401 clearInterval(textareaUpdateIntervalID); 5402 } 5403 function textareaOnScroll(event) { 5404 _targetElement[_strScrollLeft]( 5405 _rtlScrollBehavior.i && _normalizeRTLCache ? 9999999 : 0 5406 ); 5407 _targetElement[_strScrollTop](0); 5408 COMPATIBILITY.prvD(event); 5409 COMPATIBILITY.stpP(event); 5410 return false; 5411 } 5412 function textareaOnDrop(event) { 5413 setTimeout(function () { 5414 if (!_destroyed) updateTextarea(); 5415 }, 50); 5416 } 5417 function textareaOnFocus() { 5418 _textareaHasFocus = true; 5419 addClass(_hostElement, strFocus); 5420 } 5421 function textareaOnFocusout() { 5422 _textareaHasFocus = false; 5423 textareaKeyDownKeyCodesList = []; 5424 removeClass(_hostElement, strFocus); 5425 updateTextarea(true); 5426 } 5427 function textareaOnKeyDown(event) { 5428 var keyCode = event.keyCode; 5429 5430 if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { 5431 if (!textareaKeyDownKeyCodesList[LEXICON.l]) { 5432 updateTextarea(); 5433 textareaUpdateIntervalID = setInterval( 5434 updateTextarea, 5435 1000 / 60 5436 ); 5437 } 5438 if (inArray(keyCode, textareaKeyDownKeyCodesList) < 0) 5439 textareaKeyDownKeyCodesList.push(keyCode); 5440 } 5441 } 5442 function textareaOnKeyUp(event) { 5443 var keyCode = event.keyCode; 5444 var index = inArray(keyCode, textareaKeyDownKeyCodesList); 5445 5446 if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { 5447 if (index > -1) textareaKeyDownKeyCodesList.splice(index, 1); 5448 if (!textareaKeyDownKeyCodesList[LEXICON.l]) updateTextarea(true); 5449 } 5450 } 5451 function contentOnTransitionEnd(event) { 5452 if (_autoUpdateCache === true) return; 5453 event = event.originalEvent || event; 5454 if (isSizeAffectingCSSProperty(event.propertyName)) 5455 _base.update(_strAuto); 5456 } 5457 function viewportOnScroll(event) { 5458 if (!_sleeping) { 5459 if (scrollStopTimeoutId !== undefined) 5460 clearTimeout(scrollStopTimeoutId); 5461 else { 5462 if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) 5463 refreshScrollbarsAutoHide(true); 5464 5465 if (!nativeOverlayScrollbarsAreActive()) 5466 addClass(_hostElement, _classNameHostScrolling); 5467 5468 dispatchCallback("onScrollStart", event); 5469 } 5470 5471 //if a scrollbars handle gets dragged, the mousemove event is responsible for refreshing the handle offset 5472 //because if CSS scroll-snap is used, the handle offset gets only refreshed on every snap point 5473 //this looks laggy & clunky, it looks much better if the offset refreshes with the mousemove 5474 if (!_scrollbarsHandlesDefineScrollPos) { 5475 refreshScrollbarHandleOffset(true); 5476 refreshScrollbarHandleOffset(false); 5477 } 5478 dispatchCallback("onScroll", event); 5479 5480 scrollStopTimeoutId = setTimeout(function () { 5481 if (!_destroyed) { 5482 //OnScrollStop: 5483 clearTimeout(scrollStopTimeoutId); 5484 scrollStopTimeoutId = undefined; 5485 5486 if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) 5487 refreshScrollbarsAutoHide(false); 5488 5489 if (!nativeOverlayScrollbarsAreActive()) 5490 removeClass(_hostElement, _classNameHostScrolling); 5491 5492 dispatchCallback("onScrollStop", event); 5493 } 5494 }, scrollStopDelay); 5495 } 5496 } 5497 5498 if (_isTextarea) { 5499 if (_msieVersion > 9 || !_autoUpdateRecommended) { 5500 addDestroyEventListener(_targetElement, "input", updateTextarea); 5501 } else { 5502 addDestroyEventListener( 5503 _targetElement, 5504 [_strKeyDownEvent, _strKeyUpEvent], 5505 [textareaOnKeyDown, textareaOnKeyUp] 5506 ); 5507 } 5508 5509 addDestroyEventListener( 5510 _targetElement, 5511 [_strScroll, "drop", strFocus, strFocus + "out"], 5512 [ 5513 textareaOnScroll, 5514 textareaOnDrop, 5515 textareaOnFocus, 5516 textareaOnFocusout, 5517 ] 5518 ); 5519 } else { 5520 addDestroyEventListener( 5521 _contentElement, 5522 _strTransitionEndEvent, 5523 contentOnTransitionEnd 5524 ); 5525 } 5526 addDestroyEventListener( 5527 _viewportElement, 5528 _strScroll, 5529 viewportOnScroll, 5530 true 5531 ); 5532 } 5533 5534 //==== Scrollbars ====// 5535 5536 /** 5537 * Builds or destroys all scrollbar DOM elements (scrollbar, track, handle) 5538 * @param destroy Indicates whether the DOM shall be build or destroyed. 5539 */ 5540 function setupScrollbarsDOM(destroy) { 5541 var selectOrGenerateScrollbarDOM = function (isHorizontal) { 5542 var scrollbarClassName = isHorizontal 5543 ? _classNameScrollbarHorizontal 5544 : _classNameScrollbarVertical; 5545 var scrollbar = selectOrGenerateDivByClass( 5546 _classNameScrollbar + _strSpace + scrollbarClassName, 5547 true 5548 ); 5549 var track = selectOrGenerateDivByClass( 5550 _classNameScrollbarTrack, 5551 scrollbar 5552 ); 5553 var handle = selectOrGenerateDivByClass( 5554 _classNameScrollbarHandle, 5555 scrollbar 5556 ); 5557 5558 if (!_domExists && !destroy) { 5559 scrollbar.append(track); 5560 track.append(handle); 5561 } 5562 5563 return { 5564 _scrollbar: scrollbar, 5565 _track: track, 5566 _handle: handle, 5567 }; 5568 }; 5569 function resetScrollbarDOM(isHorizontal) { 5570 var scrollbarVars = getScrollbarVars(isHorizontal); 5571 var scrollbar = scrollbarVars._scrollbar; 5572 var track = scrollbarVars._track; 5573 var handle = scrollbarVars._handle; 5574 5575 if (_domExists && _initialized) { 5576 each([scrollbar, track, handle], function (i, elm) { 5577 removeClass( 5578 elm.removeAttr(LEXICON.s), 5579 _classNamesDynamicDestroy 5580 ); 5581 }); 5582 } else { 5583 remove( 5584 scrollbar || 5585 selectOrGenerateScrollbarDOM(isHorizontal)._scrollbar 5586 ); 5587 } 5588 } 5589 var horizontalElements; 5590 var verticalElements; 5591 5592 if (!destroy) { 5593 horizontalElements = selectOrGenerateScrollbarDOM(true); 5594 verticalElements = selectOrGenerateScrollbarDOM(); 5595 5596 _scrollbarHorizontalElement = horizontalElements._scrollbar; 5597 _scrollbarHorizontalTrackElement = horizontalElements._track; 5598 _scrollbarHorizontalHandleElement = horizontalElements._handle; 5599 _scrollbarVerticalElement = verticalElements._scrollbar; 5600 _scrollbarVerticalTrackElement = verticalElements._track; 5601 _scrollbarVerticalHandleElement = verticalElements._handle; 5602 5603 if (!_domExists) { 5604 _paddingElement.after(_scrollbarVerticalElement); 5605 _paddingElement.after(_scrollbarHorizontalElement); 5606 } 5607 } else { 5608 resetScrollbarDOM(true); 5609 resetScrollbarDOM(); 5610 } 5611 } 5612 5613 /** 5614 * Initializes all scrollbar interactivity events. (track and handle dragging, clicking, scrolling) 5615 * @param isHorizontal True if the target scrollbar is the horizontal scrollbar, false if the target scrollbar is the vertical scrollbar. 5616 */ 5617 function setupScrollbarEvents(isHorizontal) { 5618 var scrollbarVars = getScrollbarVars(isHorizontal); 5619 var scrollbarVarsInfo = scrollbarVars._info; 5620 var insideIFrame = _windowElementNative.top !== _windowElementNative; 5621 var xy = scrollbarVars._x_y; 5622 var XY = scrollbarVars._X_Y; 5623 var scroll = _strScroll + scrollbarVars._Left_Top; 5624 var strActive = "active"; 5625 var strSnapHandle = "snapHandle"; 5626 var strClickEvent = "click"; 5627 var scrollDurationFactor = 1; 5628 var increaseDecreaseScrollAmountKeyCodes = [16, 17]; //shift, ctrl 5629 var trackTimeout; 5630 var mouseDownScroll; 5631 var mouseDownOffset; 5632 var mouseDownInvertedScale; 5633 5634 function getPointerPosition(event) { 5635 return _msieVersion && insideIFrame 5636 ? event["screen" + XY] 5637 : COMPATIBILITY.page(event)[xy]; //use screen coordinates in EDGE & IE because the page values are incorrect in frames. 5638 } 5639 function getPreparedScrollbarsOption(name) { 5640 return _currentPreparedOptions.scrollbars[name]; 5641 } 5642 function increaseTrackScrollAmount() { 5643 scrollDurationFactor = 0.5; 5644 } 5645 function decreaseTrackScrollAmount() { 5646 scrollDurationFactor = 1; 5647 } 5648 function stopClickEventPropagation(event) { 5649 COMPATIBILITY.stpP(event); 5650 } 5651 function documentKeyDown(event) { 5652 if ( 5653 inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1 5654 ) 5655 increaseTrackScrollAmount(); 5656 } 5657 function documentKeyUp(event) { 5658 if ( 5659 inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1 5660 ) 5661 decreaseTrackScrollAmount(); 5662 } 5663 function onMouseTouchDownContinue(event) { 5664 var originalEvent = event.originalEvent || event; 5665 var isTouchEvent = originalEvent.touches !== undefined; 5666 return _sleeping || 5667 _destroyed || 5668 nativeOverlayScrollbarsAreActive() || 5669 !_scrollbarsDragScrollingCache || 5670 (isTouchEvent && !getPreparedScrollbarsOption("touchSupport")) 5671 ? false 5672 : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; 5673 } 5674 function documentDragMove(event) { 5675 if (onMouseTouchDownContinue(event)) { 5676 var trackLength = scrollbarVarsInfo._trackLength; 5677 var handleLength = scrollbarVarsInfo._handleLength; 5678 var scrollRange = scrollbarVarsInfo._maxScroll; 5679 var scrollRaw = 5680 (getPointerPosition(event) - mouseDownOffset) * 5681 mouseDownInvertedScale; 5682 var scrollDeltaPercent = scrollRaw / (trackLength - handleLength); 5683 var scrollDelta = scrollRange * scrollDeltaPercent; 5684 scrollDelta = isFinite(scrollDelta) ? scrollDelta : 0; 5685 if (_isRTL && isHorizontal && !_rtlScrollBehavior.i) 5686 scrollDelta *= -1; 5687 5688 _viewportElement[scroll]( 5689 MATH.round(mouseDownScroll + scrollDelta) 5690 ); 5691 5692 if (_scrollbarsHandlesDefineScrollPos) 5693 refreshScrollbarHandleOffset( 5694 isHorizontal, 5695 mouseDownScroll + scrollDelta 5696 ); 5697 5698 if (!_supportPassiveEvents) COMPATIBILITY.prvD(event); 5699 } else documentMouseTouchUp(event); 5700 } 5701 function documentMouseTouchUp(event) { 5702 event = event || event.originalEvent; 5703 5704 setupResponsiveEventListener( 5705 _documentElement, 5706 [ 5707 _strMouseTouchMoveEvent, 5708 _strMouseTouchUpEvent, 5709 _strKeyDownEvent, 5710 _strKeyUpEvent, 5711 _strSelectStartEvent, 5712 ], 5713 [ 5714 documentDragMove, 5715 documentMouseTouchUp, 5716 documentKeyDown, 5717 documentKeyUp, 5718 documentOnSelectStart, 5719 ], 5720 true 5721 ); 5722 COMPATIBILITY.rAF()(function () { 5723 setupResponsiveEventListener( 5724 _documentElement, 5725 strClickEvent, 5726 stopClickEventPropagation, 5727 true, 5728 { _capture: true } 5729 ); 5730 }); 5731 5732 if (_scrollbarsHandlesDefineScrollPos) 5733 refreshScrollbarHandleOffset(isHorizontal, true); 5734 5735 _scrollbarsHandlesDefineScrollPos = false;
5736 removeClass(_bodyElement, _classNameDragging); 5737 removeClass(scrollbarVars._handle, strActive); 5738 removeClass(scrollbarVars._track, strActive); 5739 removeClass(scrollbarVars._scrollbar, strActive); 5740 5741 mouseDownScroll = undefined; 5742 mouseDownOffset = undefined; 5743 mouseDownInvertedScale = 1; 5744 5745 decreaseTrackScrollAmount(); 5746 5747 if (trackTimeout !== undefined) { 5748 _base.scrollStop(); 5749 clearTimeout(trackTimeout); 5750 trackTimeout = undefined; 5751 } 5752 5753 if (event) { 5754 var rect = _hostElementNative[LEXICON.bCR](); 5755 var mouseInsideHost = 5756 event.clientX >= rect.left && 5757 event.clientX <= rect.right && 5758 event.clientY >= rect.top && 5759 event.clientY <= rect.bottom; 5760 5761 //if mouse is outside host element 5762 if (!mouseInsideHost) hostOnMouseLeave(); 5763 5764 if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) 5765 refreshScrollbarsAutoHide(false); 5766 } 5767 } 5768 function onHandleMouseTouchDown(event) { 5769 if (onMouseTouchDownContinue(event)) 5770 onHandleMouseTouchDownAction(event); 5771 } 5772 function onHandleMouseTouchDownAction(event) { 5773 mouseDownScroll = _viewportElement[scroll](); 5774 mouseDownScroll = isNaN(mouseDownScroll) ? 0 : mouseDownScroll; 5775 if ((_isRTL && isHorizontal && !_rtlScrollBehavior.n) || !_isRTL) 5776 mouseDownScroll = mouseDownScroll < 0 ? 0 : mouseDownScroll; 5777 5778 mouseDownInvertedScale = getHostElementInvertedScale()[xy]; 5779 mouseDownOffset = getPointerPosition(event); 5780 5781 _scrollbarsHandlesDefineScrollPos = 5782 !getPreparedScrollbarsOption(strSnapHandle); 5783 addClass(_bodyElement, _classNameDragging); 5784 addClass(scrollbarVars._handle, strActive); 5785 addClass(scrollbarVars._scrollbar, strActive); 5786 5787 setupResponsiveEventListener( 5788 _documentElement, 5789 [ 5790 _strMouseTouchMoveEvent, 5791 _strMouseTouchUpEvent, 5792 _strSelectStartEvent, 5793 ], 5794 [documentDragMove, documentMouseTouchUp, documentOnSelectStart] 5795 ); 5796 COMPATIBILITY.rAF()(function () { 5797 setupResponsiveEventListener( 5798 _documentElement, 5799 strClickEvent, 5800 stopClickEventPropagation, 5801 false, 5802 { _capture: true } 5803 ); 5804 }); 5805 5806 if (_msieVersion || !_documentMixed) COMPATIBILITY.prvD(event); 5807 COMPATIBILITY.stpP(event); 5808 } 5809 function onTrackMouseTouchDown(event) { 5810 if (onMouseTouchDownContinue(event)) { 5811 var handleToViewportRatio = 5812 scrollbarVars._info._handleLength / 5813 Math.round( 5814 MATH.min( 5815 1, 5816 _viewportSize[scrollbarVars._w_h] / 5817 _contentScrollSizeCache[scrollbarVars._w_h] 5818 ) * scrollbarVars._info._trackLength 5819 ); 5820 var scrollDistance = MATH.round( 5821 _viewportSize[scrollbarVars._w_h] * handleToViewportRatio 5822 ); 5823 var scrollBaseDuration = 270 * handleToViewportRatio; 5824 var scrollFirstIterationDelay = 400 * handleToViewportRatio; 5825 var trackOffset = 5826 scrollbarVars._track.offset()[scrollbarVars._left_top]; 5827 var ctrlKey = event.ctrlKey; 5828 var instantScroll = event.shiftKey; 5829 var instantScrollTransition = instantScroll && ctrlKey; 5830 var isFirstIteration = true; 5831 var easing = "linear"; 5832 var decreaseScroll; 5833 var finishedCondition; 5834 var scrollActionFinsished = function (transition) { 5835 if (_scrollbarsHandlesDefineScrollPos) 5836 refreshScrollbarHandleOffset(isHorizontal, transition); 5837 }; 5838 var scrollActionInstantFinished = function () { 5839 scrollActionFinsished(); 5840 onHandleMouseTouchDownAction(event); 5841 }; 5842 var scrollAction = function () { 5843 if (!_destroyed) { 5844 var mouseOffset = 5845 (mouseDownOffset - trackOffset) * mouseDownInvertedScale; 5846 var handleOffset = scrollbarVarsInfo._handleOffset; 5847 var trackLength = scrollbarVarsInfo._trackLength; 5848 var handleLength = scrollbarVarsInfo._handleLength; 5849 var scrollRange = scrollbarVarsInfo._maxScroll; 5850 var currScroll = scrollbarVarsInfo._currentScroll; 5851 var scrollDuration = 5852 scrollBaseDuration * scrollDurationFactor; 5853 var timeoutDelay = isFirstIteration 5854 ? MATH.max(scrollFirstIterationDelay, scrollDuration) 5855 : scrollDuration; 5856 var instantScrollPosition = 5857 scrollRange * 5858 ((mouseOffset - handleLength / 2) / 5859 (trackLength - handleLength)); // 100% * positionPercent 5860 var rtlIsNormal = 5861 _isRTL && 5862 isHorizontal && 5863 ((!_rtlScrollBehavior.i && !_rtlScrollBehavior.n) ||
5864 _normalizeRTLCache); 5865 var decreaseScrollCondition = rtlIsNormal 5866 ? handleOffset < mouseOffset 5867 : handleOffset > mouseOffset; 5868 var scrollObj = {}; 5869 var animationObj = { 5870 easing: easing, 5871 step: function (now) { 5872 if (_scrollbarsHandlesDefineScrollPos) { 5873 _viewportElement[scroll](now); //https://github.com/jquery/jquery/issues/4340 5874 refreshScrollbarHandleOffset(isHorizontal, now); 5875 } 5876 }, 5877 }; 5878 instantScrollPosition = isFinite(instantScrollPosition) 5879 ? instantScrollPosition 5880 : 0; 5881 instantScrollPosition = 5882 _isRTL && isHorizontal && !_rtlScrollBehavior.i 5883 ? scrollRange - instantScrollPosition 5884 : instantScrollPosition; 5885 5886 //_base.scrollStop(); 5887 5888 if (instantScroll) { 5889 _viewportElement[scroll](instantScrollPosition); //scroll instantly to new position 5890 if (instantScrollTransition) { 5891 //get the scroll position after instant scroll (in case CSS Snap Points are used) to get the correct snapped scroll position 5892 //and the animation stops at the correct point 5893 instantScrollPosition = _viewportElement[scroll](); 5894 //scroll back to the position before instant scrolling so animation can be performed 5895 _viewportElement[scroll](currScroll); 5896 5897 instantScrollPosition = 5898 rtlIsNormal && _rtlScrollBehavior.i 5899 ? scrollRange - instantScrollPosition 5900 : instantScrollPosition; 5901 instantScrollPosition = 5902 rtlIsNormal && _rtlScrollBehavior.n 5903 ? -instantScrollPosition 5904 : instantScrollPosition; 5905 5906 scrollObj[xy] = instantScrollPosition; 5907 _base.scroll( 5908 scrollObj, 5909 extendDeep(animationObj, { 5910 duration: 130, 5911 complete: scrollActionInstantFinished, 5912 }) 5913 ); 5914 } else scrollActionInstantFinished(); 5915 } else { 5916 decreaseScroll = isFirstIteration 5917 ? decreaseScrollCondition 5918 : decreaseScroll; 5919 finishedCondition = rtlIsNormal 5920 ? decreaseScroll 5921 ? handleOffset + handleLength >= mouseOffset 5922 : handleOffset <= mouseOffset 5923 : decreaseScroll 5924 ? handleOffset <= mouseOffset 5925 : handleOffset + handleLength >= mouseOffset; 5926 5927 if (finishedCondition) { 5928 clearTimeout(trackTimeout); 5929 _base.scrollStop(); 5930 trackTimeout = undefined; 5931 scrollActionFinsished(true); 5932 } else { 5933 trackTimeout = setTimeout(scrollAction, timeoutDelay); 5934 5935 scrollObj[xy] = 5936 (decreaseScroll ? "-=" : "+=") + scrollDistance; 5937 _base.scroll( 5938 scrollObj, 5939 extendDeep(animationObj, { 5940 duration: scrollDuration, 5941 }) 5942 ); 5943 } 5944 isFirstIteration = false; 5945 } 5946 } 5947 }; 5948 if (ctrlKey) increaseTrackScrollAmount(); 5949 5950 mouseDownInvertedScale = getHostElementInvertedScale()[xy]; 5951 mouseDownOffset = COMPATIBILITY.page(event)[xy]; 5952 5953 _scrollbarsHandlesDefineScrollPos = 5954 !getPreparedScrollbarsOption(strSnapHandle); 5955 addClass(_bodyElement, _classNameDragging); 5956 addClass(scrollbarVars._track, strActive); 5957 addClass(scrollbarVars._scrollbar, strActive); 5958 5959 setupResponsiveEventListener( 5960 _documentElement, 5961 [ 5962 _strMouseTouchUpEvent, 5963 _strKeyDownEvent, 5964 _strKeyUpEvent, 5965 _strSelectStartEvent, 5966 ], 5967 [ 5968 documentMouseTouchUp, 5969 documentKeyDown, 5970 documentKeyUp, 5971 documentOnSelectStart, 5972 ] 5973 ); 5974 5975 scrollAction(); 5976 COMPATIBILITY.prvD(event); 5977 COMPATIBILITY.stpP(event); 5978 } 5979 } 5980 function onTrackMouseTouchEnter(event) { 5981 //make sure both scrollbars will stay visible if one scrollbar is hovered if autoHide is "scroll" or "move". 5982 _scrollbarsHandleHovered = true; 5983 if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) 5984 refreshScrollbarsAutoHide(true); 5985 } 5986 function onTrackMouseTouchLeave(event) { 5987 _scrollbarsHandleHovered = false;
vendor: 19,961 bytes, lines 5988-6470
5988 if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) 5989 refreshScrollbarsAutoHide(false); 5990 } 5991 function onScrollbarMouseTouchDown(event) { 5992 COMPATIBILITY.stpP(event); 5993 } 5994 5995 addDestroyEventListener( 5996 scrollbarVars._handle, 5997 _strMouseTouchDownEvent, 5998 onHandleMouseTouchDown 5999 ); 6000 addDestroyEventListener( 6001 scrollbarVars._track, 6002 [_strMouseTouchDownEvent, _strMouseEnter, _strMouseLeave], 6003 [ 6004 onTrackMouseTouchDown, 6005 onTrackMouseTouchEnter, 6006 onTrackMouseTouchLeave, 6007 ] 6008 ); 6009 addDestroyEventListener( 6010 scrollbarVars._scrollbar, 6011 _strMouseTouchDownEvent, 6012 onScrollbarMouseTouchDown 6013 ); 6014 6015 if (_supportTransition) { 6016 addDestroyEventListener( 6017 scrollbarVars._scrollbar, 6018 _strTransitionEndEvent, 6019 function (event) { 6020 if (event.target !== scrollbarVars._scrollbar[0]) return; 6021 refreshScrollbarHandleLength(isHorizontal); 6022 refreshScrollbarHandleOffset(isHorizontal); 6023 } 6024 ); 6025 } 6026 } 6027 6028 /** 6029 * Shows or hides the given scrollbar and applied a class name which indicates if the scrollbar is scrollable or not. 6030 * @param isHorizontal True if the horizontal scrollbar is the target, false if the vertical scrollbar is the target. 6031 * @param shallBeVisible True if the scrollbar shall be shown, false if hidden. 6032 * @param canScroll True if the scrollbar is scrollable, false otherwise. 6033 */ 6034 function refreshScrollbarAppearance( 6035 isHorizontal, 6036 shallBeVisible, 6037 canScroll 6038 ) { 6039 var scrollbarHiddenClassName = isHorizontal 6040 ? _classNameHostScrollbarHorizontalHidden 6041 : _classNameHostScrollbarVerticalHidden; 6042 var scrollbarElement = isHorizontal 6043 ? _scrollbarHorizontalElement 6044 : _scrollbarVerticalElement; 6045 6046 addRemoveClass( 6047 _hostElement, 6048 scrollbarHiddenClassName, 6049 !shallBeVisible 6050 ); 6051 addRemoveClass( 6052 scrollbarElement, 6053 _classNameScrollbarUnusable, 6054 !canScroll 6055 ); 6056 } 6057 6058 /** 6059 * Autoshows / autohides both scrollbars with. 6060 * @param shallBeVisible True if the scrollbars shall be autoshown (only the case if they are hidden by a autohide), false if the shall be auto hidden. 6061 * @param delayfree True if the scrollbars shall be hidden without a delay, false or undefined otherwise. 6062 */ 6063 function refreshScrollbarsAutoHide(shallBeVisible, delayfree) { 6064 clearTimeout(_scrollbarsAutoHideTimeoutId); 6065 if (shallBeVisible) { 6066 //if(_hasOverflowCache.x && _hideOverflowCache.xs) 6067 removeClass( 6068 _scrollbarHorizontalElement, 6069 _classNameScrollbarAutoHidden 6070 ); 6071 //if(_hasOverflowCache.y && _hideOverflowCache.ys) 6072 removeClass( 6073 _scrollbarVerticalElement, 6074 _classNameScrollbarAutoHidden 6075 ); 6076 } else { 6077 var anyActive; 6078 var strActive = "active"; 6079 var hide = function () { 6080 if (!_scrollbarsHandleHovered && !_destroyed) { 6081 anyActive = 6082 _scrollbarHorizontalHandleElement.hasClass(strActive) || 6083 _scrollbarVerticalHandleElement.hasClass(strActive); 6084 if ( 6085 !anyActive && 6086 (_scrollbarsAutoHideScroll || 6087 _scrollbarsAutoHideMove || 6088 _scrollbarsAutoHideLeave) 6089 ) 6090 addClass( 6091 _scrollbarHorizontalElement, 6092 _classNameScrollbarAutoHidden 6093 ); 6094 if ( 6095 !anyActive && 6096 (_scrollbarsAutoHideScroll || 6097 _scrollbarsAutoHideMove || 6098 _scrollbarsAutoHideLeave) 6099 ) 6100 addClass( 6101 _scrollbarVerticalElement, 6102 _classNameScrollbarAutoHidden 6103 ); 6104 } 6105 }; 6106 if (_scrollbarsAutoHideDelay > 0 && delayfree !== true) 6107 _scrollbarsAutoHideTimeoutId = setTimeout( 6108 hide, 6109 _scrollbarsAutoHideDelay 6110 ); 6111 else hide(); 6112 } 6113 } 6114 6115 /** 6116 * Refreshes the handle length of the given scrollbar. 6117 * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. 6118 */ 6119 function refreshScrollbarHandleLength(isHorizontal) { 6120 var handleCSS = {}; 6121 var scrollbarVars = getScrollbarVars(isHorizontal); 6122 var scrollbarVarsInfo = scrollbarVars._info; 6123 var digit = 1000000; 6124 //get and apply intended handle length 6125 var handleRatio = MATH.min( 6126 1, 6127 _viewportSize[scrollbarVars._w_h] / 6128 _contentScrollSizeCache[scrollbarVars._w_h] 6129 ); 6130 handleCSS[scrollbarVars._width_height] = 6131 MATH.floor(handleRatio * 100 * digit) / digit + "%"; //the last * digit / digit is for flooring to the 4th digit 6132 6133 if (!nativeOverlayScrollbarsAreActive()) 6134 scrollbarVars._handle.css(handleCSS); 6135 6136 //measure the handle length to respect min & max length 6137 scrollbarVarsInfo._handleLength = 6138 scrollbarVars._handle[0]["offset" + scrollbarVars._Width_Height]; 6139 scrollbarVarsInfo._handleLengthRatio = handleRatio; 6140 } 6141 6142 /** 6143 * Refreshes the handle offset of the given scrollbar. 6144 * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. 6145 * @param scrollOrTransition The scroll position of the given scrollbar axis to which the handle shall be moved or a boolean which indicates whether a transition shall be applied. If undefined or boolean if the current scroll-offset is taken. (if isHorizontal ? scrollLeft : scrollTop) 6146 */ 6147 function refreshScrollbarHandleOffset( 6148 isHorizontal, 6149 scrollOrTransition 6150 ) { 6151 var transition = type(scrollOrTransition) == TYPES.b; 6152 var transitionDuration = 250; 6153 var isRTLisHorizontal = _isRTL && isHorizontal; 6154 var scrollbarVars = getScrollbarVars(isHorizontal); 6155 var scrollbarVarsInfo = scrollbarVars._info; 6156 var strTranslateBrace = "translate("; 6157 var strTransform = VENDORS._cssProperty("transform"); 6158 var strTransition = VENDORS._cssProperty("transition"); 6159 var nativeScroll = isHorizontal 6160 ? _viewportElement[_strScrollLeft]() 6161 : _viewportElement[_strScrollTop](); 6162 var currentScroll = 6163 scrollOrTransition === undefined || transition 6164 ? nativeScroll 6165 : scrollOrTransition; 6166 6167 //measure the handle length to respect min & max length 6168 var handleLength = scrollbarVarsInfo._handleLength; 6169 var trackLength = 6170 scrollbarVars._track[0]["offset" + scrollbarVars._Width_Height]; 6171 var handleTrackDiff = trackLength - handleLength; 6172 var handleCSS = {}; 6173 var transformOffset; 6174 var translateValue; 6175 6176 //DONT use the variable '_contentScrollSizeCache[scrollbarVars._w_h]' instead of '_viewportElement[0]['scroll' + scrollbarVars._Width_Height]' 6177 // because its a bit behind during the small delay when content size updates 6178 //(delay = mutationObserverContentLag, if its 0 then this var could be used) 6179 var maxScroll = 6180 (_viewportElementNative[_strScroll + scrollbarVars._Width_Height] - 6181 _viewportElementNative["client" + scrollbarVars._Width_Height]) * 6182 (_rtlScrollBehavior.n && isRTLisHorizontal ? -1 : 1); //* -1 if rtl scroll max is negative 6183 var getScrollRatio = function (base) { 6184 return isNaN(base / maxScroll) 6185 ? 0 6186 : MATH.max(0, MATH.min(1, base / maxScroll)); 6187 }; 6188 var getHandleOffset = function (scrollRatio) { 6189 var offset = handleTrackDiff * scrollRatio; 6190 offset = isNaN(offset) ? 0 : offset; 6191 offset = 6192 isRTLisHorizontal && !_rtlScrollBehavior.i 6193 ? trackLength - handleLength - offset 6194 : offset; 6195 offset = MATH.max(0, offset); 6196 return offset; 6197 }; 6198 var scrollRatio = getScrollRatio(nativeScroll); 6199 var unsnappedScrollRatio = getScrollRatio(currentScroll); 6200 var handleOffset = getHandleOffset(unsnappedScrollRatio); 6201 var snappedHandleOffset = getHandleOffset(scrollRatio); 6202 6203 scrollbarVarsInfo._maxScroll = maxScroll; 6204 scrollbarVarsInfo._currentScroll = nativeScroll; 6205 scrollbarVarsInfo._currentScrollRatio = scrollRatio; 6206 6207 if (_supportTransform) { 6208 transformOffset = isRTLisHorizontal 6209 ? -(trackLength - handleLength - handleOffset) 6210 : handleOffset; //in px 6211 //transformOffset = (transformOffset / trackLength * 100) * (trackLength / handleLength); //in % 6212 translateValue = isHorizontal 6213 ? strTranslateBrace + transformOffset + "px, 0)" 6214 : strTranslateBrace + "0, " + transformOffset + "px)"; 6215 6216 handleCSS[strTransform] = translateValue; 6217 6218 //apply or clear up transition 6219 if (_supportTransition) 6220 handleCSS[strTransition] = 6221 transition && 6222 MATH.abs(handleOffset - scrollbarVarsInfo._handleOffset) > 1 6223 ? getCSSTransitionString(scrollbarVars._handle) + 6224 ", " + 6225 (strTransform + _strSpace + transitionDuration + "ms") 6226 : _strEmpty; 6227 } else handleCSS[scrollbarVars._left_top] = handleOffset; 6228 6229 //only apply css if offset has changed and overflow exists. 6230 if (!nativeOverlayScrollbarsAreActive()) { 6231 scrollbarVars._handle.css(handleCSS); 6232 6233 //clear up transition 6234 if (_supportTransform && _supportTransition && transition) { 6235 scrollbarVars._handle.one(_strTransitionEndEvent, function () { 6236 if (!_destroyed) 6237 scrollbarVars._handle.css(strTransition, _strEmpty); 6238 }); 6239 } 6240 } 6241 6242 scrollbarVarsInfo._handleOffset = handleOffset; 6243 scrollbarVarsInfo._snappedHandleOffset = snappedHandleOffset; 6244 scrollbarVarsInfo._trackLength = trackLength; 6245 } 6246 6247 /** 6248 * Refreshes the interactivity of the given scrollbar element. 6249 * @param isTrack True if the track element is the target, false if the handle element is the target. 6250 * @param value True for interactivity false for no interactivity. 6251 */ 6252 function refreshScrollbarsInteractive(isTrack, value) { 6253 var action = value ? "removeClass" : "addClass"; 6254 var element1 = isTrack 6255 ? _scrollbarHorizontalTrackElement 6256 : _scrollbarHorizontalHandleElement; 6257 var element2 = isTrack 6258 ? _scrollbarVerticalTrackElement 6259 : _scrollbarVerticalHandleElement; 6260 var className = isTrack 6261 ? _classNameScrollbarTrackOff 6262 : _classNameScrollbarHandleOff; 6263 6264 element1[action](className); 6265 element2[action](className); 6266 } 6267 6268 /** 6269 * Returns a object which is used for fast access for specific variables. 6270 * @param isHorizontal True if the horizontal scrollbar vars shall be accessed, false if the vertical scrollbar vars shall be accessed. 6271 * @returns {{wh: string, WH: string, lt: string, _wh: string, _lt: string, t: *, h: *, c: {}, s: *}} 6272 */ 6273 function getScrollbarVars(isHorizontal) { 6274 return { 6275 _width_height: isHorizontal ? _strWidth : _strHeight, 6276 _Width_Height: isHorizontal ? "Width" : "Height", 6277 _left_top: isHorizontal ? _strLeft : _strTop, 6278 _Left_Top: isHorizontal ? "Left" : "Top", 6279 _x_y: isHorizontal ? _strX : _strY, 6280 _X_Y: isHorizontal ? "X" : "Y", 6281 _w_h: isHorizontal ? "w" : "h", 6282 _l_t: isHorizontal ? "l" : "t", 6283 _track: isHorizontal 6284 ? _scrollbarHorizontalTrackElement 6285 : _scrollbarVerticalTrackElement, 6286 _handle: isHorizontal 6287 ? _scrollbarHorizontalHandleElement 6288 : _scrollbarVerticalHandleElement, 6289 _scrollbar: isHorizontal 6290 ? _scrollbarHorizontalElement 6291 : _scrollbarVerticalElement, 6292 _info: isHorizontal ? _scrollHorizontalInfo : _scrollVerticalInfo, 6293 }; 6294 } 6295 6296 //==== Scrollbar Corner ====// 6297 6298 /** 6299 * Builds or destroys the scrollbar corner DOM element. 6300 * @param destroy Indicates whether the DOM shall be build or destroyed. 6301 */ 6302 function setupScrollbarCornerDOM(destroy) { 6303 _scrollbarCornerElement = 6304 _scrollbarCornerElement || 6305 selectOrGenerateDivByClass(_classNameScrollbarCorner, true); 6306 6307 if (!destroy) { 6308 if (!_domExists) { 6309 _hostElement.append(_scrollbarCornerElement); 6310 } 6311 } else { 6312 if (_domExists && _initialized) { 6313 removeClass( 6314 _scrollbarCornerElement.removeAttr(LEXICON.s), 6315 _classNamesDynamicDestroy 6316 ); 6317 } else { 6318 remove(_scrollbarCornerElement); 6319 } 6320 } 6321 } 6322 6323 /** 6324 * Initializes all scrollbar corner interactivity events. 6325 */ 6326 function setupScrollbarCornerEvents() { 6327 var insideIFrame = _windowElementNative.top !== _windowElementNative; 6328 var mouseDownPosition = {}; 6329 var mouseDownSize = {}; 6330 var mouseDownInvertedScale = {}; 6331 var reconnectMutationObserver; 6332 6333 function documentDragMove(event) { 6334 if (onMouseTouchDownContinue(event)) { 6335 var pageOffset = getCoordinates(event); 6336 var hostElementCSS = {}; 6337 if (_resizeHorizontal || _resizeBoth) 6338 hostElementCSS[_strWidth] = 6339 mouseDownSize.w + 6340 (pageOffset.x - mouseDownPosition.x) * 6341 mouseDownInvertedScale.x; 6342 if (_resizeVertical || _resizeBoth) 6343 hostElementCSS[_strHeight] = 6344 mouseDownSize.h + 6345 (pageOffset.y - mouseDownPosition.y) * 6346 mouseDownInvertedScale.y; 6347 _hostElement.css(hostElementCSS); 6348 COMPATIBILITY.stpP(event); 6349 } else { 6350 documentMouseTouchUp(event); 6351 } 6352 } 6353 function documentMouseTouchUp(event) { 6354 var eventIsTrusted = event !== undefined; 6355 6356 setupResponsiveEventListener( 6357 _documentElement, 6358 [ 6359 _strSelectStartEvent, 6360 _strMouseTouchMoveEvent, 6361 _strMouseTouchUpEvent, 6362 ], 6363 [documentOnSelectStart, documentDragMove, documentMouseTouchUp], 6364 true 6365 ); 6366 6367 removeClass(_bodyElement, _classNameDragging); 6368 if (_scrollbarCornerElement.releaseCapture) 6369 _scrollbarCornerElement.releaseCapture(); 6370 6371 if (eventIsTrusted) { 6372 if (reconnectMutationObserver) connectMutationObservers(); 6373 _base.update(_strAuto); 6374 } 6375 reconnectMutationObserver = false; 6376 } 6377 function onMouseTouchDownContinue(event) { 6378 var originalEvent = event.originalEvent || event; 6379 var isTouchEvent = originalEvent.touches !== undefined; 6380 return _sleeping || _destroyed 6381 ? false 6382 : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; 6383 } 6384 function getCoordinates(event) { 6385 return _msieVersion && insideIFrame 6386 ? { x: event.screenX, y: event.screenY } 6387 : COMPATIBILITY.page(event); 6388 } 6389 6390 addDestroyEventListener( 6391 _scrollbarCornerElement, 6392 _strMouseTouchDownEvent, 6393 function (event) { 6394 if (onMouseTouchDownContinue(event) && !_resizeNone) { 6395 if (_mutationObserversConnected) { 6396 reconnectMutationObserver = true; 6397 disconnectMutationObservers(); 6398 } 6399 6400 mouseDownPosition = getCoordinates(event); 6401 6402 mouseDownSize.w = 6403 _hostElementNative[LEXICON.oW] - 6404 (!_isBorderBox ? _paddingX : 0); 6405 mouseDownSize.h = 6406 _hostElementNative[LEXICON.oH] - 6407 (!_isBorderBox ? _paddingY : 0); 6408 mouseDownInvertedScale = getHostElementInvertedScale(); 6409 6410 setupResponsiveEventListener( 6411 _documentElement, 6412 [ 6413 _strSelectStartEvent, 6414 _strMouseTouchMoveEvent, 6415 _strMouseTouchUpEvent, 6416 ], 6417 [ 6418 documentOnSelectStart, 6419 documentDragMove, 6420 documentMouseTouchUp, 6421 ] 6422 ); 6423 6424 addClass(_bodyElement, _classNameDragging); 6425 if (_scrollbarCornerElement.setCapture) 6426 _scrollbarCornerElement.setCapture(); 6427 6428 COMPATIBILITY.prvD(event); 6429 COMPATIBILITY.stpP(event); 6430 } 6431 } 6432 ); 6433 } 6434 6435 //==== Utils ====// 6436 6437 /** 6438 * Calls the callback with the given name. The Context of this callback is always _base (this). 6439 * @param name The name of the target which shall be called. 6440 * @param args The args with which the callback shall be called. 6441 * @param dependent Boolean which decides whether the callback shall be fired, undefined is like a "true" value. 6442 */ 6443 function dispatchCallback(name, args, dependent) { 6444 if (dependent === false) return; 6445 if (_initialized) { 6446 var callback = _currentPreparedOptions.callbacks[name]; 6447 var extensionOnName = name; 6448 var ext; 6449 6450 if (extensionOnName.substr(0, 2) === "on") 6451 extensionOnName = 6452 extensionOnName.substr(2, 1).toLowerCase() + 6453 extensionOnName.substr(3); 6454 6455 if (type(callback) == TYPES.f) callback.call(_base, args); 6456 6457 each(_extensions, function () { 6458 ext = this; 6459 if (type(ext.on) == TYPES.f) ext.on(extensionOnName, args); 6460 }); 6461 } else if (!_destroyed) 6462 _callbacksInitQeueue.push({ n: name, a: args }); 6463 } 6464 6465 /** 6466 * Sets the "top, right, bottom, left" properties, with a given prefix, of the given css object. 6467 * @param targetCSSObject The css object to which the values shall be applied. 6468 * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix) 6469 * @param values A array of values which shall be applied to the "top, right, bottom, left" -properties. The array order is [top, right, bottom, left]. 6470 * If this argument is undefined the value '' (empty string)
6470will be applied to all properties. 6471 */ 6472 function setTopRightBottomLeft(targetCSSObject, prefix, values) { 6473 prefix = prefix || _strEmpty; 6474 values = values || [_strEmpty, _strEmpty, _strEmpty, _strEmpty]; 6475 6476 targetCSSObject[prefix + _strTop] = values[0]; 6477 targetCSSObject[prefix + _strRight] = values[1]; 6478 targetCSSObject[prefix + _strBottom] = values[2]; 6479 targetCSSObject[prefix + _strLeft] = values[3]; 6480 } 6481 6482 /** 6483 * Gets the "top, right, bottom, left" CSS properties of the CSS property with the given prefix from the host element. 6484 * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix) 6485 * @param suffix The suffix of the "top, right, bottom, left" css properties. (example: 'border-' is a valid prefix with '-width' is a valid suffix) 6486 * @param zeroX True if the x axis shall be 0. 6487 * @param zeroY True if the y axis shall be 0. 6488 * @returns {{}} The object which contains the numbers of the read CSS properties. 6489 */ 6490 function getTopRightBottomLeftHost(prefix, suffix, zeroX, zeroY) { 6491 suffix = suffix || _strEmpty; 6492 prefix = prefix || _strEmpty; 6493 return { 6494 t: zeroY 6495 ? 0 6496 : parseToZeroOrNumber( 6497 _hostElement.css(prefix + _strTop + suffix) 6498 ), 6499 r: zeroX 6500 ? 0 6501 : parseToZeroOrNumber( 6502 _hostElement.css(prefix + _strRight + suffix) 6503 ), 6504 b: zeroY 6505 ? 0 6506 : parseToZeroOrNumber( 6507 _hostElement.css(prefix + _strBottom + suffix) 6508 ), 6509 l: zeroX 6510 ? 0 6511 : parseToZeroOrNumber( 6512 _hostElement.css(prefix + _strLeft + suffix) 6513 ), 6514 }; 6515 } 6516 6517 /** 6518 * Returns the computed CSS transition string from the given element. 6519 * @param element The element from which the transition string shall be returned. 6520 * @returns {string} The CSS transition string from the given element. 6521 */ 6522 function getCSSTransitionString(element) { 6523 var transitionStr = VENDORS._cssProperty("transition"); 6524 var assembledValue = element.css(transitionStr); 6525 if (assembledValue) return assembledValue; 6526 var regExpString = "\\s*(" + "([^,(]+(\\(.+?\\))?)+" + ")[\\s,]*"; 6527 var regExpMain = new RegExp(regExpString); 6528 var regExpValidate = new RegExp("^(" + regExpString + ")+$"); 6529 var properties = "property duration timing-function delay".split(" "); 6530 var result = []; 6531 var strResult; 6532 var valueArray; 6533 var i = 0; 6534 var j; 6535 var splitCssStyleByComma = function (str) { 6536 strResult = []; 6537 if (!str.match(regExpValidate)) return str; 6538 while (str.match(regExpMain)) { 6539 strResult.push(RegExp.$1); 6540 str = str.replace(regExpMain, _strEmpty); 6541 } 6542 6543 return strResult; 6544 }; 6545 for (; i < properties[LEXICON.l]; i++) { 6546 valueArray = splitCssStyleByComma( 6547 element.css(transitionStr + "-" + properties[i]) 6548 ); 6549 for (j = 0; j < valueArray[LEXICON.l]; j++) 6550 result[j] = 6551 (result[j] ? result[j] + _strSpace : _strEmpty) + valueArray[j]; 6552 } 6553 return result.join(", "); 6554 } 6555 6556 /** 6557 * Generates a Regular Expression which matches with a string which starts with 'os-host'. 6558 * @param {boolean} withCurrClassNameOption The Regular Expression also matches if the string is the current ClassName option (multiple values splitted by space possible). 6559 * @param {boolean} withOldClassNameOption The Regular Expression also matches if the string is the old ClassName option (multiple values splitted by space possible). 6560 */ 6561 function createHostClassNameRegExp( 6562 withCurrClassNameOption, 6563 withOldClassNameOption 6564 ) { 6565 var i; 6566 var split; 6567 var appendix; 6568 var appendClasses = function (classes, condition) { 6569 appendix = ""; 6570 if (condition && typeof classes == TYPES.s) { 6571 split = classes.split(_strSpace); 6572 for (i = 0; i < split[LEXICON.l]; i++) 6573 appendix += "|" + split[i] + "$"; 6574 // split[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') for escaping regex characters 6575 } 6576 return appendix; 6577 }; 6578 6579 return new RegExp( 6580 "(^" + 6581 _classNameHostElement + 6582 "([-_].+|)$)" +
6583 appendClasses(_classNameCache, withCurrClassNameOption) + 6584 appendClasses(_oldClassName, withOldClassNameOption), 6585 "g" 6586 ); 6587 } 6588 6589 /** 6590 * Calculates the host-elements inverted scale. (invertedScale = 1 / scale) 6591 * @returns {{x: number, y: number}} The scale of the host-element. 6592 */ 6593 function getHostElementInvertedScale() { 6594 var rect = _paddingElementNative[LEXICON.bCR](); 6595 return { 6596 x: _supportTransform 6597 ? 1 / 6598 (MATH.round(rect.width) / 6599 _paddingElementNative[LEXICON.oW]) || 1 6600 : 1, 6601 y: _supportTransform 6602 ? 1 / 6603 (MATH.round(rect.height) / 6604 _paddingElementNative[LEXICON.oH]) || 1 6605 : 1, 6606 }; 6607 } 6608 6609 /** 6610 * Checks whether the given object is a HTMLElement. 6611 * @param o The object which shall be checked. 6612 * @returns {boolean} True the given object is a HTMLElement, false otherwise. 6613 */ 6614 function isHTMLElement(o) { 6615 var strOwnerDocument = "ownerDocument"; 6616 var strHTMLElement = "HTMLElement"; 6617 var wnd = 6618 o && o[strOwnerDocument] 6619 ? o[strOwnerDocument].parentWindow || window 6620 : window; 6621 return typeof wnd[strHTMLElement] == TYPES.o 6622 ? o instanceof wnd[strHTMLElement] //DOM2 6623 : o && 6624 typeof o == TYPES.o && 6625 o !== null && 6626 o.nodeType === 1 && 6627 typeof o.nodeName == TYPES.s; 6628 } 6629 6630 /** 6631 * Compares 2 arrays and returns the differences between them as a array. 6632 * @param a1 The first array which shall be compared. 6633 * @param a2 The second array which shall be compared. 6634 * @returns {Array} The differences between the two arrays. 6635 */ 6636 function getArrayDifferences(a1, a2) { 6637 var a = []; 6638 var diff = []; 6639 var i; 6640 var k; 6641 for (i = 0; i < a1.length; i++) a[a1[i]] = true; 6642 for (i = 0; i < a2.length; i++) { 6643 if (a[a2[i]]) delete a[a2[i]]; 6644 else a[a2[i]] = true; 6645 } 6646 for (k in a) diff.push(k); 6647 return diff; 6648 } 6649 6650 /** 6651 * Returns Zero or the number to which the value can be parsed. 6652 * @param value The value which shall be parsed. 6653 * @param toFloat Indicates whether the number shall be parsed to a float. 6654 */ 6655 function parseToZeroOrNumber(value, toFloat) { 6656 var num = toFloat ? parseFloat(value) : parseInt(value, 10); 6657 return isNaN(num) ? 0 : num; 6658 } 6659 6660 /** 6661 * Gets several information of the textarea and returns them as a object or undefined if the browser doesn't support it. 6662 * @returns {{cursorRow: Number, cursorCol, rows: Number, cols: number, wRow: number, pos: number, max : number}} or undefined if not supported. 6663 */ 6664 function getTextareaInfo() { 6665 //read needed values 6666 var textareaCursorPosition = _targetElementNative.selectionStart; 6667 if (textareaCursorPosition === undefined) return; 6668 6669 var textareaValue = _targetElement.val(); 6670 var textareaLength = textareaValue[LEXICON.l]; 6671 var textareaRowSplit = textareaValue.split("\n"); 6672 var textareaLastRow = textareaRowSplit[LEXICON.l]; 6673 var textareaCurrentCursorRowSplit = textareaValue 6674 .substr(0, textareaCursorPosition) 6675 .split("\n"); 6676 var widestRow = 0; 6677 var textareaLastCol = 0; 6678 var cursorRow = textareaCurrentCursorRowSplit[LEXICON.l]; 6679 var cursorCol = 6680 textareaCurrentCursorRowSplit[ 6681 textareaCurrentCursorRowSplit[LEXICON.l] - 1 6682 ][LEXICON.l]; 6683 var rowCols; 6684 var i; 6685 6686 //get widest Row and the last column of the textarea 6687 for (i = 0; i < textareaRowSplit[LEXICON.l]; i++) { 6688 rowCols = textareaRowSplit[i][LEXICON.l]; 6689 if (rowCols > textareaLastCol) { 6690 widestRow = i + 1; 6691 textareaLastCol = rowCols; 6692 } 6693 } 6694 6695 return { 6696 _cursorRow: cursorRow, //cursorRow 6697 _cursorColumn: cursorCol, //cursorCol 6698 _rows: textareaLastRow, //rows 6699 _columns: textareaLastCol, //cols 6700 _widestRow: widestRow, //wRow 6701 _cursorPosition: textareaCursorPosition, //pos 6702 _cursorMax: textareaLength, //max 6703 }; 6704 } 6705 6706 /** 6707 * Determines whether native overlay scrollbars are active. 6708 * @returns {boolean} True if native overlay scrollbars are active, false otherwise. 6709 */ 6710 function nativeOverlayScrollbarsAreActive() { 6711 return ( 6712 _ignoreOverlayScrollbarHidingCache && 6713 _nativeScrollbarIsOverlaid.x && 6714 _nativeScrollbarIsOverlaid.y 6715 ); 6716 } 6717 6718 /** 6719 * Gets the element which is used to measure the content size. 6720 * @returns {*} TextareaCover if target element is textarea else the ContentElement. 6721 */ 6722 function getContentMeasureElement() { 6723 return _isTextarea ? _textareaCoverElement[0] : _contentElementNative; 6724 } 6725 6726 /** 6727 * Generates a string which represents a HTML div with the given classes or attributes. 6728 * @param classesOrAttrs The class of the div as string or a object which represents the attributes of the div. (The class attribute can also be written as "className".) 6729 * @param content The content of the div as string. 6730 * @returns {string} The concated string which represents a HTML div and its content. 6731 */ 6732 function generateDiv(classesOrAttrs, content) { 6733 return ( 6734 "<div " + 6735 (classesOrAttrs 6736 ? type(classesOrAttrs) == TYPES.s 6737 ? 'class="' + classesOrAttrs + '"' 6738 : (function () { 6739 var key; 6740 var attrs = _strEmpty; 6741 if (FRAMEWORK.isPlainObject(classesOrAttrs)) { 6742 for (key in classesOrAttrs) 6743 attrs +=
6744 (key === "c" ? "class" : key) + 6745 '="' + 6746 classesOrAttrs[key] + 6747 '" '; 6748 } 6749 return attrs; 6750 })() 6751 : _strEmpty) + 6752 ">" + 6753 (content || _strEmpty) + 6754 "</div>" 6755 ); 6756 } 6757 6758 /** 6759 * Selects or generates a div with the given class attribute. 6760 * @param className The class names (divided by spaces) of the div which shall be selected or generated. 6761 * @param selectParentOrOnlyChildren The parent element from which of the element shall be selected. (if undefined or boolean its hostElement) 6762 * If its a boolean it decides whether only the children of the host element shall be selected. 6763 * @returns {*} The generated or selected element. 6764 */ 6765 function selectOrGenerateDivByClass( 6766 className, 6767 selectParentOrOnlyChildren 6768 ) { 6769 var onlyChildren = type(selectParentOrOnlyChildren) == TYPES.b; 6770 var selectParent = onlyChildren 6771 ? _hostElement 6772 : selectParentOrOnlyChildren || _hostElement; 6773 6774 return _domExists && !selectParent[LEXICON.l] 6775 ? null 6776 : _domExists 6777 ? selectParent[onlyChildren ? "children" : "find"]( 6778 _strDot + className.replace(/\s/g, _strDot) 6779 ).eq(0) 6780 : FRAMEWORK(generateDiv(className)); 6781 } 6782 6783 /** 6784 * Gets the value of the given property from the given object. 6785 * @param obj The object from which the property value shall be got. 6786 * @param path The property of which the value shall be got. 6787 * @returns {*} Returns the value of the searched property or undefined of the property wasn't found. 6788 */ 6789 function getObjectPropVal(obj, path) { 6790 var splits = path.split(_strDot); 6791 var i = 0; 6792 var val; 6793 for (; i < splits.length; i++) { 6794 if (!obj[LEXICON.hOP](splits[i])) return; 6795 val = obj[splits[i]]; 6796 if (i < splits.length && type(val) == TYPES.o) obj = val; 6797 } 6798 return val; 6799 } 6800 6801 /** 6802 * Sets the value of the given property from the given object. 6803 * @param obj The object from which the property value shall be set. 6804 * @param path The property of which the value shall be set. 6805 * @param val The value of the property which shall be set. 6806 */ 6807 function setObjectPropVal(obj, path, val) { 6808 var splits = path.split(_strDot); 6809 var splitsLength = splits.length; 6810 var i = 0; 6811 var extendObj = {}; 6812 var extendObjRoot = extendObj; 6813 for (; i < splitsLength; i++) 6814 extendObj = extendObj[splits[i]] = i + 1 < splitsLength ? {} : val; 6815 FRAMEWORK.extend(obj, extendObjRoot, true); 6816 } 6817 6818 /** 6819 * Runs a action for each selector inside the updateOnLoad option. 6820 * @param {Function} action The action for each updateOnLoad selector, the arguments the function takes is the index and the value (the selector). 6821 */ 6822 function eachUpdateOnLoad(action) { 6823 var updateOnLoad = _currentPreparedOptions.updateOnLoad; 6824 updateOnLoad = 6825 type(updateOnLoad) == TYPES.s 6826 ? updateOnLoad.split(_strSpace) 6827 : updateOnLoad; 6828 6829 if (COMPATIBILITY.isA(updateOnLoad) && !_destroyed) { 6830 each(updateOnLoad, action); 6831 } 6832 } 6833 6834 //==== Utils Cache ====// 6835 6836 /** 6837 * Compares two values or objects and returns true if they aren't equal. 6838 * @param current The first value or object which shall be compared. 6839 * @param cache The second value or object which shall be compared. 6840 * @param force If true the returned value is always true. 6841 * @returns {boolean} True if both values or objects aren't equal or force is true, false otherwise. 6842 */ 6843 function checkCache(current, cache, force) { 6844 if (force) return force; 6845 if (type(current) == TYPES.o && type(cache) == TYPES.o) { 6846 for (var prop in current) { 6847 if (prop !== "c") {
vendor: 2,815 bytes, lines 6848-6926
6848 if (current[LEXICON.hOP](prop) && cache[LEXICON.hOP](prop)) { 6849 if (checkCache(current[prop], cache[prop])) return true; 6850 } else { 6851 return true; 6852 } 6853 } 6854 } 6855 } else { 6856 return current !== cache; 6857 } 6858 return false; 6859 } 6860 6861 //==== Shortcuts ====// 6862 6863 /** 6864 * jQuery extend method shortcut with a appended "true" as first argument. 6865 */ 6866 function extendDeep() { 6867 return FRAMEWORK.extend.apply( 6868 this, 6869 [true].concat([].slice.call(arguments)) 6870 ); 6871 } 6872 6873 /** 6874 * jQuery addClass method shortcut. 6875 */ 6876 function addClass(el, classes) { 6877 return _frameworkProto.addClass.call(el, classes); 6878 } 6879 6880 /** 6881 * jQuery removeClass method shortcut. 6882 */ 6883 function removeClass(el, classes) { 6884 return _frameworkProto.removeClass.call(el, classes); 6885 } 6886 6887 /** 6888 * Adds or removes the given classes dependent on the boolean value. True for add, false for remove. 6889 */ 6890 function addRemoveClass(el, classes, doAdd) { 6891 return doAdd ? addClass(el, classes) : removeClass(el, classes); 6892 } 6893 6894 /** 6895 * jQuery remove method shortcut. 6896 */ 6897 function remove(el) { 6898 return _frameworkProto.remove.call(el); 6899 } 6900 6901 /** 6902 * Finds the first child element with the given selector of the given element. 6903 * @param el The root element from which the selector shall be valid. 6904 * @param selector The selector of the searched element. 6905 * @returns {*} The first element which is a child of the given element and matches the givens selector. 6906 */ 6907 function findFirst(el, selector) { 6908 return _frameworkProto.find.call(el, selector).eq(0); 6909 } 6910 6911 //==== API ====// 6912 6913 /** 6914 * Puts the instance to sleep. It wont respond to any changes in the DOM and won't update. Scrollbar Interactivity is also disabled as well as the resize handle. 6915 * This behavior can be reset by calling the update method. 6916 */ 6917 _base.sleep = function () { 6918 _sleeping = true; 6919 }; 6920 6921 /** 6922 * Updates the plugin and DOM to the current options. 6923 * This method should only be called if a update is 100% required. 6924 * @param force True if every property shall be updated and the cache shall be ignored. 6925 * !INTERNAL USAGE! : force can be a string "auto", "sync" or "zoom" too 6926 * if "auto" then before a real update the content size and host element attributes gets checked, and if they changed only then the update method will be called.
6927 * if "sync" then the async update process (MutationObserver or UpdateLoop) gets synchronized and a corresponding update takes place if one was needed due to pending changes. 6928 * if "zoom" then a update takes place where it's assumed that content and host size changed 6929 * @returns {boolean|undefined} 6930 * If force is "sync" then a boolean is returned which indicates whether a update was needed due to pending changes. 6931 * If force is "auto" then a boolean is returned whether a update was needed due to attribute or size changes. 6932 * undefined otherwise. 6933 */ 6934 _base.update = function (force) { 6935 if (_destroyed) return; 6936 6937 var attrsChanged; 6938 var contentSizeC; 6939 var isString = type(force) == TYPES.s; 6940 var doUpdateAuto; 6941 var mutHost; 6942 var mutContent; 6943 6944 if (isString) { 6945 if (force === _strAuto) { 6946 attrsChanged = meaningfulAttrsChanged(); 6947 contentSizeC = updateAutoContentSizeChanged(); 6948 doUpdateAuto = attrsChanged || contentSizeC; 6949 if (doUpdateAuto) { 6950 update({ 6951 _contentSizeChanged: contentSizeC, 6952 _changedOptions: _initialized 6953 ? undefined 6954 : _currentPreparedOptions, 6955 }); 6956 } 6957 } else if (force === _strSync) { 6958 if (_mutationObserversConnected) { 6959 mutHost = _mutationObserverHostCallback( 6960 _mutationObserverHost.takeRecords() 6961 ); 6962 mutContent = _mutationObserverContentCallback( 6963 _mutationObserverContent.takeRecords() 6964 ); 6965 } else { 6966 mutHost = _base.update(_strAuto); 6967 } 6968 } else if (force === "zoom") { 6969 update({ 6970 _hostSizeChanged: true, 6971 _contentSizeChanged: true, 6972 }); 6973 } 6974 } else { 6975 force = _sleeping || force; 6976 _sleeping = false; 6977 if (!_base.update(_strSync) || force) update({ _force: force }); 6978 } 6979 6980 updateElementsOnLoad(); 6981 6982 return doUpdateAuto || mutHost || mutContent; 6983 }; 6984 6985 /** 6986 Gets or sets the current options. The update method will be called automatically if new options were set. 6987 * @param newOptions If new options are given, then the new options will be set, if new options aren't given (undefined or a not a plain object) then the current options will be returned. 6988 * @param value If new options is a property path string, then this value will be used to set the option to which the property path string leads. 6989 * @returns {*} 6990 */ 6991 _base.options = function (newOptions, value) { 6992 var option = {}; 6993 var changedOps; 6994 6995 //return current options if newOptions are undefined or empty 6996 if ( 6997 FRAMEWORK.isEmptyObject(newOptions) || 6998 !FRAMEWORK.isPlainObject(newOptions) 6999 ) { 7000 if (type(newOptions) == TYPES.s) { 7001 if (arguments.length > 1) { 7002 setObjectPropVal(option, newOptions, value); 7003 changedOps = setOptions(option); 7004 } else return getObjectPropVal(_currentOptions, newOptions); 7005 } else return _currentOptions; 7006 } else { 7007 changedOps = setOptions(newOptions); 7008 } 7009 7010 if (!FRAMEWORK.isEmptyObject(changedOps)) { 7011 update({ _changedOptions: changedOps }); 7012 } 7013 }; 7014 7015 /** 7016 * Restore the DOM, disconnects all observers, remove all resize observers and put the instance to sleep. 7017 */ 7018 _base.destroy = function () { 7019 if (_destroyed) return; 7020 7021 //remove this instance from auto update loop 7022 autoUpdateLoop.remove(_base); 7023 7024 //disconnect all mutation observers 7025 disconnectMutationObservers(); 7026 7027 //remove all resize observers 7028 setupResizeObserver(_sizeObserverElement); 7029 setupResizeObserver(_sizeAutoObserverElement); 7030 7031 //remove all extensions 7032 for (var extName in _extensions) _base.removeExt(extName); 7033 7034 //remove all 'destroy' events 7035 while (_destroyEvents[LEXICON.l] > 0) _destroyEvents.pop()(); 7036 7037 //remove all events from host element 7038 setupHostMouseTouchEvents(true); 7039 7040 //remove all helper / detection elements 7041 if (_contentGlueElement) remove(_contentGlueElement); 7042 if (_contentArrangeElement) remove(_contentArrangeElement); 7043 if (_sizeAutoObserverAdded) remove(_sizeAutoObserverElement); 7044 7045 //remove all generated DOM 7046 setupScrollbarsDOM(true); 7047 setupScrollbarCornerDOM(true); 7048 setupStructureDOM(true); 7049 7050 //remove all generated image load events 7051 for (var i = 0; i < _updateOnLoadElms[LEXICON.l]; i++) 7052 FRAMEWORK(_updateOnLoadElms[i]).off( 7053 _updateOnLoadEventName, 7054 updateOnLoadCallback 7055 ); 7056 _updateOnLoadElms = undefined; 7057 7058 _destroyed = true; 7059 _sleeping = true; 7060 7061 //remove this instance from the instances list 7062 INSTANCES(pluginTargetElement, 0); 7063 dispatchCallback("onDestroyed"); 7064 7065 //remove all properties and methods 7066 //for (var property in _base) 7067 // delete _base[property]; 7068 //_base = undefined; 7069 }; 7070 7071 /** 7072 * Scrolls to a given position or element. 7073 * @param coordinates 7074 * 1. Can be "coordinates" which looks like: 7075 * { x : ?, y : ? } OR Object with x and y properties 7076 * { left : ?, top : ? } OR Object with left and top properties 7077 * { l : ?, t : ? } OR Object with l and t properties 7078 * [ ?, ? ] OR Array where the first two element are the coordinates (first is x, second is y) 7079 * ? A single value which stays for both axis 7080 * A value can be a number, a string or a calculation. 7081 * 7082 * Operators: 7083 * [NONE] The current scroll will be overwritten by the value. 7084 * '+=' The value will be added to the current scroll offset 7085 * '-=' The value will be subtracted from the current scroll offset 7086 * '*=' The current scroll wil be multiplicated by the value. 7087 * '/=' The current scroll wil be divided by the value. 7088 * 7089 * Units: 7090 * [NONE] The value is the final scroll amount. final = (value * 1) 7091 * 'px' Same as none 7092 * '%' The value is dependent on the current scroll value. final = ((currentScrollValue / 100) * value) 7093 * 'vw' The value is multiplicated by the viewport width. final = (value * viewportWidth) 7094 * 'vh' The value is multiplicated by the viewport height. final = (value * viewportHe
7094ight) 7095 * 7096 * example final values: 7097 * 200, '200px', '50%', '1vw', '1vh', '+=200', '/=1vw', '*=2px', '-=5vh', '+=33%', '+= 50% - 2px', '-= 1vw - 50%' 7098 * 7099 * 2. Can be a HTML or jQuery element: 7100 * The final scroll offset is the offset (without margin) of the given HTML / jQuery element. 7101 * 7102 * 3. Can be a object with a HTML or jQuery element with additional settings: 7103 * { 7104 * el : [HTMLElement, jQuery element], MUST be specified, else this object isn't valid. 7105 * scroll : [string, array, object], Default value is 'always'. 7106 * block : [string, array, object], Default value is 'begin'. 7107 * margin : [number, boolean, array, object] Default value is false. 7108 * } 7109 * 7110 * Possible scroll settings are: 7111 * 'always' Scrolls always. 7112 * 'ifneeded' Scrolls only if the element isnt fully in view. 7113 * 'never' Scrolls never. 7114 * 7115 * Possible block settings are: 7116 * 'begin' Both axis shall be docked to the "begin" edge. - The element will be docked to the top and left edge of the viewport. 7117 * 'end' Both axis shall be docked to the "end" edge. - The element will be docked to the bottom and right edge of the viewport. (If direction is RTL to the bottom and left edge.) 7118 * 'center' Both axis shall be docked to "center". - The element will be centered in the viewport. 7119 * 'nearest' The element will be docked to the nearest edge(s). 7120 * 7121 * Possible margin settings are: -- The actual margin of the element wont be affect, this option affects only the final scroll offset. 7122 * [BOOLEAN] If true the css margin of the element will be used, if false no margin will be used. 7123 * [NUMBER] The margin will be used for all edges. 7124 * 7125 * @param duration The duration of the scroll animation, OR a jQuery animation configuration object. 7126 * @param easing The animation easing. 7127 * @param complete The animation complete callback. 7128 * @returns {{ 7129 * position: {x: number, y: number}, 7130 * ratio: {x: number, y: number}, 7131 * max: {x: number, y: number}, 7132 * handleOffset: {x: number, y: number}, 7133 * handleLength: {x: number, y: number}, 7134 * handleLengthRatio: {x: number, y: number}, t 7135 * rackLength: {x: number, y: number}, 7136 * isRTL: boolean, 7137 * isRTLNormalized: boolean 7138 * }} 7139 */ 7140 _base.scroll = function (coordinates, duration, easing, complete) { 7141 if (arguments.length === 0 || coordinates === undefined) { 7142 var infoX = _scrollHorizontalInfo; 7143 var infoY = _scrollVerticalInfo; 7144 var normalizeInvert = 7145 _normalizeRTLCache && _isRTL && _rtlScrollBehavior.i; 7146 var normalizeNegate = 7147 _normalizeRTLCache && _isRTL && _rtlScrollBehavior.n; 7148 var scrollX = infoX._currentScroll; 7149 var scrollXRatio = infoX._currentScrollRatio; 7150 var maxScrollX = infoX._maxScroll; 7151 scrollXRatio = normalizeInvert ? 1 - scrollXRatio : scrollXRatio; 7152 scrollX = normalizeInvert ? maxScrollX - scrollX : scrollX; 7153 scrollX *= normalizeNegate ? -1 : 1; 7154 maxScrollX *= normalizeNegate ? -1 : 1; 7155 7156 return { 7157 position: { 7158 x: scrollX, 7159 y: infoY._currentScroll, 7160 }, 7161 ratio: { 7162 x: scrollXRatio, 7163 y: infoY._currentScrollRatio, 7164 }, 7165 max: { 7166 x: maxScrollX, 7167 y: infoY._maxScroll, 7168 }, 7169 handleOffset: { 7170 x: infoX._handleOffset, 7171 y: infoY._handleOffset, 7172 }, 7173 handleLength: { 7174 x: infoX._handleLength, 7175 y: infoY._handleLength, 7176 }, 7177 handleLengthRatio: { 7178 x: infoX._handleLengthRatio, 7179 y: infoY._handleLengthRatio, 7180 }, 7181 trackLength: { 7182 x: infoX._trackLength, 7183 y: infoY._trackLength, 7184 }, 7185 snappedHandleOffset: { 7186 x: infoX._snappedHandleOffset, 7187 y: infoY._snappedHandleOffset, 7188 }, 7189 isRTL: _isRTL,
7190 isRTLNormalized: _normalizeRTLCache, 7191 }; 7192 } 7193 7194 _base.update(_strSync); 7195 7196 var normalizeRTL = _normalizeRTLCache; 7197 var coordinatesXAxisProps = [_strX, _strLeft, "l"]; 7198 var coordinatesYAxisProps = [_strY, _strTop, "t"]; 7199 var coordinatesOperators = ["+=", "-=", "*=", "/="]; 7200 var durationIsObject = type(duration) == TYPES.o; 7201 var completeCallback = durationIsObject 7202 ? duration.complete 7203 : complete; 7204 var i; 7205 var finalScroll = {}; 7206 var specialEasing = {}; 7207 var doScrollLeft; 7208 var doScrollTop; 7209 var animationOptions; 7210 var strEnd = "end"; 7211 var strBegin = "begin"; 7212 var strCenter = "center"; 7213 var strNearest = "nearest"; 7214 var strAlways = "always"; 7215 var strNever = "never"; 7216 var strIfNeeded = "ifneeded"; 7217 var strLength = LEXICON.l; 7218 var settingsAxis; 7219 var settingsScroll; 7220 var settingsBlock; 7221 var settingsMargin; 7222 var finalElement; 7223 var elementObjSettingsAxisValues = [_strX, _strY, "xy", "yx"]; 7224 var elementObjSettingsBlockValues = [ 7225 strBegin, 7226 strEnd, 7227 strCenter, 7228 strNearest, 7229 ]; 7230 var elementObjSettingsScrollValues = [ 7231 strAlways, 7232 strNever, 7233 strIfNeeded, 7234 ]; 7235 var coordinatesIsElementObj = coordinates[LEXICON.hOP]("el"); 7236 var possibleElement = coordinatesIsElementObj 7237 ? coordinates.el 7238 : coordinates; 7239 var possibleElementIsJQuery = 7240 possibleElement instanceof FRAMEWORK || JQUERY 7241 ? possibleElement instanceof JQUERY 7242 : false; 7243 var possibleElementIsHTMLElement = possibleElementIsJQuery 7244 ? false 7245 : isHTMLElement(possibleElement); 7246 var updateScrollbarInfos = function () { 7247 if (doScrollLeft) refreshScrollbarHandleOffset(true); 7248 if (doScrollTop) refreshScrollbarHandleOffset(false); 7249 }; 7250 var proxyCompleteCallback = 7251 type(completeCallback) != TYPES.f 7252 ? undefined 7253 : function () { 7254 updateScrollbarInfos(); 7255 completeCallback(); 7256 }; 7257 function checkSettingsStringValue(currValue, allowedValues) { 7258 for (i = 0; i < allowedValues[strLength]; i++) { 7259 if (currValue === allowedValues[i]) return true; 7260 } 7261 return false; 7262 } 7263 function getRawScroll(isX, coordinates) { 7264 var coordinateProps = isX 7265 ? coordinatesXAxisProps 7266 : coordinatesYAxisProps; 7267 coordinates = 7268 type(coordinates) == TYPES.s || type(coordinates) == TYPES.n 7269 ? [coordinates, coordinates] 7270 : coordinates; 7271 7272 if (COMPATIBILITY.isA(coordinates)) 7273 return isX ? coordinates[0] : coordinates[1]; 7274 else if (type(coordinates) == TYPES.o) { 7275 //decides RTL normalization "hack" with .n 7276 //normalizeRTL = type(coordinates.n) == TYPES.b ? coordinates.n : normalizeRTL; 7277 for (i = 0; i < coordinateProps[strLength]; i++) 7278 if (coordinateProps[i] in coordinates) 7279 return coordinates[coordinateProps[i]]; 7280 } 7281 } 7282 function getFinalScroll(isX, rawScroll) { 7283 var isString = type(rawScroll) == TYPES.s; 7284 var operator; 7285 var amount; 7286 var scrollInfo = isX ? _scrollHorizontalInfo : _scrollVerticalInfo; 7287 var currScroll = scrollInfo._currentScroll; 7288 var maxScroll = scrollInfo._maxScroll; 7289 var mult = " * "; 7290 var finalValue; 7291 var isRTLisX = _isRTL && isX; 7292 var normalizeShortcuts = 7293 isRTLisX && _rtlScrollBehavior.n && !normalizeRTL; 7294 var strReplace = "replace";
vendor: 9,408 bytes, lines 7295-7527
7295 var evalFunc = eval; 7296 var possibleOperator; 7297 if (isString) { 7298 //check operator 7299 if (rawScroll[strLength] > 2) { 7300 possibleOperator = rawScroll.substr(0, 2); 7301 if (inArray(possibleOperator, coordinatesOperators) > -1) 7302 operator = possibleOperator; 7303 } 7304 7305 //calculate units and shortcuts 7306 rawScroll = operator ? rawScroll.substr(2) : rawScroll; 7307 rawScroll = rawScroll[strReplace](/min/g, 0) //'min' = 0% 7308 [strReplace](/</g, 0) //'<' = 0% 7309 [strReplace]( 7310 /max/g, 7311 (normalizeShortcuts ? "-" : _strEmpty) + _strHundredPercent 7312 ) //'max' = 100% 7313 [strReplace]( 7314 />/g, 7315 (normalizeShortcuts ? "-" : _strEmpty) + _strHundredPercent 7316 ) //'>' = 100% 7317 [strReplace](/px/g, _strEmpty) 7318 [strReplace]( 7319 /%/g, 7320 mult + 7321 (maxScroll * (isRTLisX && _rtlScrollBehavior.n ? -1 : 1)) / 7322 100.0 7323 ) 7324 [strReplace](/vw/g, mult + _viewportSize.w) 7325 [strReplace](/vh/g, mult + _viewportSize.h); 7326 amount = parseToZeroOrNumber( 7327 isNaN(rawScroll) 7328 ? parseToZeroOrNumber(evalFunc(rawScroll), true).toFixed() 7329 : rawScroll 7330 ); 7331 } else { 7332 amount = rawScroll; 7333 } 7334 7335 if ( 7336 amount !== undefined && 7337 !isNaN(amount) && 7338 type(amount) == TYPES.n 7339 ) { 7340 var normalizeIsRTLisX = normalizeRTL && isRTLisX; 7341 var operatorCurrScroll = 7342 currScroll * 7343 (normalizeIsRTLisX && _rtlScrollBehavior.n ? -1 : 1); 7344 var invert = normalizeIsRTLisX && _rtlScrollBehavior.i; 7345 var negate = normalizeIsRTLisX && _rtlScrollBehavior.n; 7346 operatorCurrScroll = invert 7347 ? maxScroll - operatorCurrScroll 7348 : operatorCurrScroll; 7349 switch (operator) { 7350 case "+=": 7351 finalValue = operatorCurrScroll + amount; 7352 break; 7353 case "-=": 7354 finalValue = operatorCurrScroll - amount; 7355 break; 7356 case "*=": 7357 finalValue = operatorCurrScroll * amount; 7358 break; 7359 case "/=": 7360 finalValue = operatorCurrScroll / amount; 7361 break; 7362 default: 7363 finalValue = amount; 7364 break; 7365 } 7366 finalValue = invert ? maxScroll - finalValue : finalValue; 7367 finalValue *= negate ? -1 : 1; 7368 finalValue = 7369 isRTLisX && _rtlScrollBehavior.n 7370 ? MATH.min(0, MATH.max(maxScroll, finalValue)) 7371 : MATH.max(0, MATH.min(maxScroll, finalValue)); 7372 } 7373 return finalValue === currScroll ? undefined : finalValue; 7374 } 7375 function getPerAxisValue( 7376 value, 7377 valueInternalType, 7378 defaultValue, 7379 allowedValues 7380 ) { 7381 var resultDefault = [defaultValue, defaultValue]; 7382 var valueType = type(value); 7383 var valueArrLength; 7384 var valueArrItem; 7385 7386 //value can be [ string, or array of two strings ] 7387 if (valueType == valueInternalType) { 7388 value = [value, value]; 7389 } else if (valueType == TYPES.a) { 7390 valueArrLength = value[strLength]; 7391 if (valueArrLength > 2 || valueArrLength < 1) 7392 value = resultDefault; 7393 else { 7394 if (valueArrLength === 1) value[1] = defaultValue; 7395 for (i = 0; i < valueArrLength; i++) { 7396 valueArrItem = value[i]; 7397 if ( 7398 type(valueArrItem) != valueInternalType || 7399 !checkSettingsStringValue(valueArrItem, allowedValues) 7400 ) { 7401 value = resultDefault; 7402 break; 7403 } 7404 } 7405 } 7406 } else if (valueType == TYPES.o) 7407 value = [ 7408 value[_strX] || defaultValue, 7409 value[_strY] || defaultValue, 7410 ]; 7411 else value = resultDefault; 7412 return { x: value[0], y: value[1] }; 7413 } 7414 function generateMargin(marginTopRightBottomLeftArray) { 7415 var result = []; 7416 var currValue; 7417 var currValueType; 7418 var valueDirections = [_strTop, _strRight, _strBottom, _strLeft]; 7419 for (i = 0; i < marginTopRightBottomLeftArray[strLength]; i++) { 7420 if (i === valueDirections[strLength]) break; 7421 currValue = marginTopRightBottomLeftArray[i]; 7422 currValueType = type(currValue); 7423 if (currValueType == TYPES.b) 7424 result.push( 7425 currValue 7426 ? parseToZeroOrNumber( 7427 finalElement.css(_strMarginMinus + valueDirections[i]) 7428 ) 7429 : 0 7430 ); 7431 else result.push(currValueType == TYPES.n ? currValue : 0); 7432 } 7433 return result; 7434 } 7435 7436 if (possibleElementIsJQuery || possibleElementIsHTMLElement) { 7437 //get settings 7438 var margin = coordinatesIsElementObj ? coordinates.margin : 0; 7439 var axis = coordinatesIsElementObj ? coordinates.axis : 0; 7440 var scroll = coordinatesIsElementObj ? coordinates.scroll : 0; 7441 var block = coordinatesIsElementObj ? coordinates.block : 0; 7442 var marginDefault = [0, 0, 0, 0]; 7443 var marginType = type(margin); 7444 var marginLength; 7445 finalElement = possibleElementIsJQuery 7446 ? possibleElement 7447 : FRAMEWORK(possibleElement); 7448 7449 if (finalElement[strLength] > 0) { 7450 //margin can be [ boolean, number, array of 2, array of 4, object ] 7451 if (marginType == TYPES.n || marginType == TYPES.b) 7452 margin = generateMargin([margin, margin, margin, margin]); 7453 else if (marginType == TYPES.a) { 7454 marginLength = margin[strLength]; 7455 if (marginLength === 2) 7456 margin = generateMargin([ 7457 margin[0], 7458 margin[1], 7459 margin[0], 7460 margin[1], 7461 ]); 7462 else if (marginLength >= 4) margin = generateMargin(margin); 7463 else margin = marginDefault; 7464 } else if (marginType == TYPES.o) 7465 margin = generateMargin([ 7466 margin[_strTop], 7467 margin[_strRight], 7468 margin[_strBottom], 7469 margin[_strLeft], 7470 ]); 7471 else margin = marginDefault; 7472 7473 //block = type(block) === TYPES.b ? block ? [ strNearest, strBegin ] : [ strNearest, strEnd ] : block; 7474 settingsAxis = checkSettingsStringValue( 7475 axis, 7476 elementObjSettingsAxisValues 7477 ) 7478 ? axis 7479 : "xy"; 7480 settingsScroll = getPerAxisValue( 7481 scroll, 7482 TYPES.s, 7483 strAlways, 7484 elementObjSettingsScrollValues 7485 ); 7486 settingsBlock = getPerAxisValue( 7487 block, 7488 TYPES.s, 7489 strBegin, 7490 elementObjSettingsBlockValues 7491 ); 7492 settingsMargin = margin; 7493 7494 var viewportScroll = { 7495 l: _scrollHorizontalInfo._currentScroll, 7496 t: _scrollVerticalInfo._currentScroll, 7497 }; 7498 // use padding element instead of viewport element because padding element has never padding, margin or position applied. 7499 var viewportOffset = _paddingElement.offset(); 7500 7501 //get coordinates 7502 var elementOffset = finalElement.offset(); 7503 var doNotScroll = { 7504 x: settingsScroll.x == strNever || settingsAxis == _strY, 7505 y: settingsScroll.y == strNever || settingsAxis == _strX, 7506 }; 7507 elementOffset[_strTop] -= settingsMargin[0]; 7508 elementOffset[_strLeft] -= settingsMargin[3]; 7509 var elementScrollCoordinates = { 7510 x: MATH.round( 7511 elementOffset[_strLeft] - 7512 viewportOffset[_strLeft] + 7513 viewportScroll.l 7514 ), 7515 y: MATH.round( 7516 elementOffset[_strTop] - 7517 viewportOffset[_strTop] + 7518 viewportScroll.t 7519 ), 7520 }; 7521 if (_isRTL) { 7522 if (!_rtlScrollBehavior.n && !_rtlScrollBehavior.i) 7523 elementScrollCoordinates.x = MATH.round( 7524 viewportOffset[_strLeft] - 7525 elementOffset[_strLeft] + 7526 viewportScroll.l 7527 );
7528 if (_rtlScrollBehavior.n && normalizeRTL) 7529 elementScrollCoordinates.x *= -1; 7530 if (_rtlScrollBehavior.i && normalizeRTL) 7531 elementScrollCoordinates.x = MATH.round( 7532 viewportOffset[_strLeft] - 7533 elementOffset[_strLeft] + 7534 (_scrollHorizontalInfo._maxScroll - viewportScroll.l) 7535 ); 7536 } 7537 7538 //measuring is required 7539 if ( 7540 settingsBlock.x != strBegin || 7541 settingsBlock.y != strBegin || 7542 settingsScroll.x == strIfNeeded || 7543 settingsScroll.y == strIfNeeded || 7544 _isRTL 7545 ) { 7546 var measuringElm = finalElement[0]; 7547 var rawElementSize = _supportTransform 7548 ? measuringElm[LEXICON.bCR]() 7549 : { 7550 width: measuringElm[LEXICON.oW], 7551 height: measuringElm[LEXICON.oH], 7552 }; 7553 var elementSize = { 7554 w: 7555 rawElementSize[_strWidth] + 7556 settingsMargin[3] + 7557 settingsMargin[1], 7558 h: 7559 rawElementSize[_strHeight] + 7560 settingsMargin[0] + 7561 settingsMargin[2], 7562 }; 7563 var finalizeBlock = function (isX) { 7564 var vars = getScrollbarVars(isX); 7565 var wh = vars._w_h; 7566 var lt = vars._left_top; 7567 var xy = vars._x_y; 7568 var blockIsEnd = 7569 settingsBlock[xy] == 7570 (isX ? (_isRTL ? strBegin : strEnd) : strEnd); 7571 var blockIsCenter = settingsBlock[xy] == strCenter; 7572 var blockIsNearest = settingsBlock[xy] == strNearest; 7573 var scrollNever = settingsScroll[xy] == strNever; 7574 var scrollIfNeeded = settingsScroll[xy] == strIfNeeded; 7575 var vpSize = _viewportSize[wh]; 7576 var vpOffset = viewportOffset[lt]; 7577 var elSize = elementSize[wh]; 7578 var elOffset = elementOffset[lt]; 7579 var divide = blockIsCenter ? 2 : 1; 7580 var elementCenterOffset = elOffset + elSize / 2; 7581 var viewportCenterOffset = vpOffset + vpSize / 2; 7582 var isInView = 7583 elSize <= vpSize && 7584 elOffset >= vpOffset && 7585 elOffset + elSize <= vpOffset + vpSize; 7586 7587 if (scrollNever) doNotScroll[xy] = true; 7588 else if (!doNotScroll[xy]) { 7589 if (blockIsNearest || scrollIfNeeded) { 7590 doNotScroll[xy] = scrollIfNeeded ? isInView : false; 7591 blockIsEnd = 7592 elSize < vpSize 7593 ? elementCenterOffset > viewportCenterOffset 7594 : elementCenterOffset < viewportCenterOffset; 7595 } 7596 elementScrollCoordinates[xy] -= 7597 blockIsEnd || blockIsCenter 7598 ? (vpSize / divide - elSize / divide) * 7599 (isX && _isRTL && normalizeRTL ? -1 : 1) 7600 : 0; 7601 } 7602 }; 7603 finalizeBlock(true); 7604 finalizeBlock(false); 7605 } 7606 7607 if (doNotScroll.y) delete elementScrollCoordinates.y; 7608 if (doNotScroll.x) delete elementScrollCoordinates.x; 7609 7610 coordinates = elementScrollCoordinates; 7611 } 7612 } 7613 7614 finalScroll[_strScrollLeft] = getFinalScroll( 7615 true, 7616 getRawScroll(true, coordinates) 7617 ); 7618 finalScroll[_strScrollTop] = getFinalScroll( 7619 false, 7620 getRawScroll(false, coordinates) 7621 ); 7622 doScrollLeft = finalScroll[_strScrollLeft] !== undefined; 7623 doScrollTop = finalScroll[_strScrollTop] !== undefined; 7624 7625 if ( 7626 (doScrollLeft || doScrollTop) && 7627 (duration > 0 || durationIsObject) 7628 ) { 7629 if (durationIsObject) { 7630 duration.complete = proxyCompleteCallback; 7631 _viewportElement.animate(finalScroll, duration); 7632 } else { 7633 animationOptions = { 7634 duration: duration, 7635 complete: proxyCompleteCallback, 7636 }; 7637 if ( 7638 COMPATIBILITY.isA(easing) || 7639 FRAMEWORK.isPlainObject(easing) 7640 ) { 7641 specialEasing[_strScrollLeft] = easing[0] || easing.x; 7642 specialEasing[_strScrollTop] = easing[1] || easing.y; 7643 animationOptions.specialEasing = specialEasing; 7644 } else { 7645 animationOptions.easing = easing; 7646 } 7647 _viewportElement.animate(finalScroll, animationOptions); 7648 } 7649 } else { 7650 if (doScrollLeft) 7651 _viewportElement[_strScrollLeft](finalScroll[_strScrollLeft]); 7652 if (doScrollTop) 7653 _viewportElement[_strScrollTop](finalScroll[_strScrollTop]); 7654 updateScrollbarInfos(); 7655 } 7656 }; 7657 7658 /** 7659 * Stops all scroll animations. 7660 * @returns {*} The current OverlayScrollbars instance (for chaining). 7661 */ 7662 _base.scrollStop = function (param1, param2, param3) { 7663 _viewportElement.stop(param1, param2, param3); 7664 return _base; 7665 }; 7666 7667 /** 7668 * Returns all relevant elements. 7669 * @param elementName The name of the element which shall be returned. 7670 * @returns {{target: *, host: *, padding: *, viewport: *, content: *, scrollbarHorizontal: {scrollbar: *, track: *, handle: *}, scrollbarVertical: {scrollbar: *, track: *, handle: *}, scrollbarCorner: *} | *} 7671 */ 7672 _base.getElements = function (elementName) { 7673 var obj = { 7674 target: _targetElementNative, 7675 host: _hostElementNative, 7676 padding: _paddingElementNative, 7677 viewport: _viewportElementNative, 7678 content: _contentElementNative, 7679 scrollbarHorizontal: { 7680 scrollbar: _scrollbarHorizontalElement[0], 7681 track: _scrollbarHorizontalTrackElement[0], 7682 handle: _scrollbarHorizontalHandleElement[0], 7683 }, 7684 scrollbarVertical: { 7685 scrollbar: _scrollbarVerticalElement[0], 7686 track: _scrollbarVerticalTrackElement[0], 7687 handle: _scrollbarVerticalHandleElement[0], 7688 }, 7689 scrollbarCorner: _scrollbarCornerElement[0], 7690 }; 7691 return type(elementName) == TYPES.s 7692 ? getObjectPropVal(obj, elementName) 7693 : obj; 7694 }; 7695 7696 /** 7697 * Returns a object which describes the current state of this instance. 7698 * @param stateProperty A specific property from the state object which shall be returned. 7699 * @returns {{widthAuto, heightAuto, overflowAmount, hideOverflow, hasOverflow, contentScrollSize, viewportSize, hostSize, autoUpdate} | *} 7700 */ 7701 _base.getState = function (stateProperty) { 7702 function prepare(obj) { 7703 if (!FRAMEWORK.isPlainObject(obj)) return obj; 7704 var extended = extendDeep({}, obj); 7705 var changePropertyName = function (from, to) { 7706 if (extended[LEXICON.hOP](from)) { 7707 extended[to] = extended[from]; 7708 delete extended[from]; 7709 } 7710 }; 7711 changePropertyName("w", _strWidth); //change w to width 7712 changePropertyName("h", _strHeight); //change h to height 7713 delete extended.c; //delete c (the 'changed' prop) 7714 return extended; 7715 } 7716 var obj = { 7717 destroyed: !!prepare(_destroyed), 7718 sleeping: !!prepare(_sleeping), 7719 autoUpdate: prepare(!_mutationObserversConnected), 7720 widthAuto: prepare(_widthAutoCache), 7721 heightAuto: prepare(_heightAutoCache), 7722 padding: prepare(_cssPaddingCache), 7723 overflowAmount: prepare(_overflowAmountCache), 7724 hideOverflow: prepare(_hideOverflowCache), 7725 hasOverflow: prepare(_hasOverflowCache), 7726 contentScrollSize: prepare(_contentScrollSizeCache), 7727 viewportSize: prepare(_viewportSize), 7728 hostSize: prepare(_hostSizeCache), 7729 documentMixed: prepare(_documentMixed), 7730 }; 7731 return type(stateProperty) == TYPES.s 7732 ? getObjectPropVal(obj, stateProperty) 7733 : obj; 7734 }; 7735 7736 /** 7737 * Gets all or specific extension instance. 7738 * @param extName The name of the extension from which the instance shall be got. 7739 * @returns {{}} The instance of the extension with the given name or undefined if the instance couldn't be found. 7740 */ 7741 _base.ext = function (extName) { 7742 var result; 7743 var privateMethods = _extensionsPrivateMethods.split(" "); 7744 var i = 0; 7745 if (type(extName) == TYPES.s) { 7746 if (_extensions[LEXICON.hOP](extName)) { 7747 result = extendDeep({}, _extensions[extName]); 7748 for (; i < privateMethods.length; i++) 7749 delete result[privateMethods[i]]; 7750 } 7751 } else { 7752 result = {}; 7753 for (i in _extensions) result[i] = extendDeep({}, _base.ext(i)); 7754 } 7755 return result; 7756 }; 7757 7758 /** 7759 * Adds a extension to this instance. 7760 * @param extName The name of the extension which shall be added.
7761 * @param extensionOptions The extension options which shall be used. 7762 * @returns {{}} The instance of the added extension or undefined if the extension couldn't be added properly. 7763 */ 7764 _base.addExt = function (extName, extensionOptions) { 7765 var registeredExtensionObj = _plugin.extension(extName); 7766 var instance; 7767 var instanceAdded; 7768 var instanceContract; 7769 var contractResult; 7770 var contractFulfilled = true; 7771 if (registeredExtensionObj) { 7772 if (!_extensions[LEXICON.hOP](extName)) { 7773 instance = registeredExtensionObj.extensionFactory.call( 7774 _base, 7775 extendDeep({}, registeredExtensionObj.defaultOptions), 7776 FRAMEWORK, 7777 COMPATIBILITY 7778 ); 7779 7780 if (instance) { 7781 instanceContract = instance.contract; 7782 if (type(instanceContract) == TYPES.f) { 7783 contractResult = instanceContract(window); 7784 contractFulfilled = 7785 type(contractResult) == TYPES.b 7786 ? contractResult 7787 : contractFulfilled; 7788 } 7789 if (contractFulfilled) { 7790 _extensions[extName] = instance; 7791 instanceAdded = instance.added; 7792 if (type(instanceAdded) == TYPES.f) 7793 instanceAdded(extensionOptions); 7794 7795 return _base.ext(extName); 7796 } 7797 } 7798 } else return _base.ext(extName); 7799 } else 7800 console.warn( 7801 'A extension with the name "' + extName + "\" isn't registered." 7802 ); 7803 }; 7804 7805 /** 7806 * Removes a extension from this instance. 7807 * @param extName The name of the extension which shall be removed. 7808 * @returns {boolean} True if the extension was removed, false otherwise e.g. if the extension wasn't added before. 7809 */ 7810 _base.removeExt = function (extName) { 7811 var instance = _extensions[extName]; 7812 var instanceRemoved; 7813 if (instance) { 7814 delete _extensions[extName]; 7815 7816 instanceRemoved = instance.removed; 7817 if (type(instanceRemoved) == TYPES.f) instanceRemoved(); 7818 7819 return true; 7820 } 7821 return false; 7822 }; 7823 7824 /** 7825 * Constructs the plugin. 7826 * @param targetElement The element to which the plugin shall be applied. 7827 * @param options The initial options of the plugin. 7828 * @param extensions The extension(s) which shall be added right after the initialization. 7829 * @returns {boolean} True if the plugin was successfully initialized, false otherwise. 7830 */ 7831 function construct(targetElement, options, extensions) { 7832 _defaultOptions = globals.defaultOptions; 7833 _nativeScrollbarStyling = globals.nativeScrollbarStyling; 7834 _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); 7835 _nativeScrollbarIsOverlaid = extendDeep( 7836 {}, 7837 globals.nativeScrollbarIsOverlaid 7838 ); 7839 _overlayScrollbarDummySize = extendDeep( 7840 {}, 7841 globals.overlayScrollbarDummySize 7842 ); 7843 _rtlScrollBehavior = extendDeep({}, globals.rtlScrollBehavior); 7844 7845 //parse & set options but don't update 7846 setOptions(extendDeep({}, _defaultOptions, options)); 7847 7848 _cssCalc = globals.cssCalc; 7849 _msieVersion = globals.msie; 7850 _autoUpdateRecommended = globals.autoUpdateRecommended; 7851 _supportTransition = globals.supportTransition; 7852 _supportTransform = globals.supportTransform; 7853 _supportPassiveEvents = globals.supportPassiveEvents; 7854 _supportResizeObserver = globals.supportResizeObserver; 7855 _supportMutationObserver = globals.supportMutationObserver; 7856 _restrictedMeasuring = globals.restrictedMeasuring; 7857 _documentElement = FRAMEWORK(targetElement.ownerDocument); 7858 _documentElementNative = _documentElement[0]; 7859 _windowElement = FRAMEWORK( 7860 _documentElementNative.defaultView || 7861 _documentElementNative.parentWindow 7862 ); 7863 _windowElementNative = _windowElement[0]; 7864 _htmlElement = findFirst(_documentElement, "html"); 7865 _bodyElement = findFirst(_htmlElement, "body"); 7866 _targetElement = FRAMEWORK(targetElement); 7867 _targetElementNative = _targetElement[0]; 7868 _isTextarea = _targetElement.is("textarea"); 7869 _isBody = _targetElement.is("body"); 7870 _documentMixed = _documentElementNative !== document; 7871 7872 /* On a div Element The if checks only whether: 7873 * - the targetElement has the class "os-host" 7874 * - the targetElement has a a child with the class "os-padding" 7875 * 7876 * If that's the case, its assumed the DOM has already the following structure: 7877 * (The ".os-host" element is the targetElement) 7878 * 7879 * <div class="os-host"> 7880 * <div class="os-resize-observer-host"></div>
7881 * <div class="os-padding"> 7882 * <div class="os-viewport"> 7883 * <div class="os-content"></div> 7884 * </div> 7885 * </div> 7886 * <div class="os-scrollbar os-scrollbar-horizontal "> 7887 * <div class="os-scrollbar-track"> 7888 * <div class="os-scrollbar-handle"></div> 7889 * </div> 7890 * </div> 7891 * <div class="os-scrollbar os-scrollbar-vertical"> 7892 * <div class="os-scrollbar-track"> 7893 * <div class="os-scrollbar-handle"></div> 7894 * </div> 7895 * </div> 7896 * <div class="os-scrollbar-corner"></div> 7897 * </div> 7898 * 7899 * ===================================================================================== 7900 * 7901 * On a Textarea Element The if checks only whether: 7902 * - the targetElement has the class "os-textarea" 7903 * - the targetElement is inside a element with the class "os-content" 7904 * 7905 * If that's the case, its assumed the DOM has already the following structure: 7906 * (The ".os-textarea" (textarea) element is the targetElement) 7907 * 7908 * <div class="os-host-textarea"> 7909 * <div class="os-resize-observer-host"></div> 7910 * <div class="os-padding os-text-inherit"> 7911 * <div class="os-viewport os-text-inherit"> 7912 * <div class="os-content os-text-inherit"> 7913 * <div class="os-textarea-cover"></div> 7914 * <textarea class="os-textarea os-text-inherit"></textarea> 7915 * </div> 7916 * </div> 7917 * </div> 7918 * <div class="os-scrollbar os-scrollbar-horizontal "> 7919 * <div class="os-scrollbar-track"> 7920 * <div class="os-scrollbar-handle"></div> 7921 * </div> 7922 * </div> 7923 * <div class="os-scrollbar os-scrollbar-vertical"> 7924 * <div class="os-scrollbar-track"> 7925 * <div class="os-scrollbar-handle"></div> 7926 * </div> 7927 * </div> 7928 * <div class="os-scrollbar-corner"></div> 7929 * </div> 7930 */ 7931 _domExists = _isTextarea 7932 ? _targetElement.hasClass(_classNameTextareaElement) && 7933 _targetElement.parent().hasClass(_classNameContentElement) 7934 : _targetElement.hasClass(_classNameHostElement) && 7935 _targetElement.children(_strDot + _classNamePaddingElement)[ 7936 LEXICON.l 7937 ]; 7938 7939 var initBodyScroll; 7940 var bodyMouseTouchDownListener; 7941 7942 //check if the plugin hasn't to be initialized 7943 if ( 7944 _nativeScrollbarIsOverlaid.x && 7945 _nativeScrollbarIsOverlaid.y && 7946 !_currentPreparedOptions.nativeScrollbarsOverlaid.initialize 7947 ) { 7948 _initialized = true; // workaround so the onInitializationWithdrawn callback below is fired 7949 dispatchCallback("onInitializationWithdrawn"); 7950 if (_domExists) { 7951 setupStructureDOM(true); 7952 setupScrollbarsDOM(true); 7953 setupScrollbarCornerDOM(true); 7954 } 7955 7956 _initialized = false; 7957 _destroyed = true; 7958 _sleeping = true; 7959 7960 return _base; 7961 } 7962 7963 if (_isBody) { 7964 initBodyScroll = {}; 7965 initBodyScroll.l = MATH.max( 7966 _targetElement[_strScrollLeft](), 7967 _htmlElement[_strScrollLeft](), 7968 _windowElement[_strScrollLeft]() 7969 ); 7970 initBodyScroll.t = MATH.max( 7971 _targetElement[_strScrollTop](), 7972 _htmlElement[_strScrollTop](), 7973 _windowElement[_strScrollTop]() 7974 ); 7975 7976 bodyMouseTouchDownListener = function () { 7977 _viewportElement.removeAttr(LEXICON.ti); 7978 setupResponsiveEventListener( 7979 _viewportElement, 7980 _strMouseTouchDownEvent, 7981 bodyMouseTouchDownListener, 7982 true, 7983 true 7984 ); 7985 }; 7986 } 7987 7988 //build OverlayScrollbars DOM 7989 setupStructureDOM(); 7990 setupScrollbarsDOM(); 7991 setupScrollbarCornerDOM(); 7992 7993 //create OverlayScrollbars events 7994 setupStructureEvents(); 7995 setupScrollbarEvents(true); 7996 setupScrollbarEvents(false); 7997 setupScrollbarCornerEvents(); 7998 7999 //create mutation observers 8000 createMutationObservers(); 8001 8002 //build resize observer for the host element 8003 setupResizeObserver(_sizeObserverElement, hostOnResized); 8004 8005 if (_isBody) { 8006 //apply the body scroll to handle it right in the update method 8007 _viewportElement[_strScrollLeft](initBodyScroll.l)[_strScrollTop]( 8008 initBodyScroll.t 8009 ); 8010 8011 //set the focus on the viewport element so you dont have to click on the page to use keyboard keys (up / down / space) for scrolling 8012 if ( 8013 document.activeElement == targetElement && 8014 _viewportElementNative.focus 8015 ) { 8016 //set a tabindex to make the viewportElement focusable 8017 _viewportElement.attr(LEXICON.ti, "-1"); 8018 _viewportElementNative.focus(); 8019 8020 /* the tabindex has to be removed due to; 8021 * If you set the tabindex attribute on an <div>, then its child content cannot be scrolled with the arrow keys unless you set tabindex on the content, too 8022 * https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex 8023 */ 8024 setupResponsiveEventListener( 8025 _viewportElement, 8026 _strMouseTouchDownEvent, 8027 bodyMouseTouchDownListener, 8028 false, 8029 true 8030 ); 8031 } 8032 } 8033 8034 //update for the first time & initialize cache 8035 _base.update(_strAuto); 8036 8037 //the plugin is initialized now! 8038 _initialized = true; 8039 dispatchCallback("onInitialized"); 8040
8041 //call all callbacks which would fire before the initialized was complete 8042 each(_callbacksInitQeueue, function (index, value) { 8043 dispatchCallback(value.n, value.a); 8044 }); 8045 _callbacksInitQeueue = []; 8046 8047 //add extensions 8048 if (type(extensions) == TYPES.s) extensions = [extensions]; 8049 if (COMPATIBILITY.isA(extensions)) 8050 each(extensions, function (index, value) { 8051 _base.addExt(value); 8052 }); 8053 else if (FRAMEWORK.isPlainObject(extensions)) 8054 each(extensions, function (key, value) { 8055 _base.addExt(key, value); 8056 }); 8057 8058 //add the transition class for transitions AFTER the first update & AFTER the applied extensions (for preventing unwanted transitions) 8059 setTimeout(function () { 8060 if (_supportTransition && !_destroyed) 8061 addClass(_hostElement, _classNameHostTransition); 8062 }, 333); 8063 8064 return _base; 8065 } 8066 8067 if ( 8068 _plugin.valid(construct(pluginTargetElement, options, extensions)) 8069 ) { 8070 INSTANCES(pluginTargetElement, _base); 8071 } 8072 8073 return _base; 8074 } 8075 8076 /** 8077 * Initializes a new OverlayScrollbarsInstance object or changes options if already initialized or returns the current instance. 8078 * @param pluginTargetElements The elements to which the Plugin shall be initialized. 8079 * @param options The custom options with which the plugin shall be initialized. 8080 * @param extensions The extension(s) which shall be added right after initialization. 8081 * @returns {*} 8082 */ 8083 _plugin = window[PLUGINNAME] = function ( 8084 pluginTargetElements, 8085 options, 8086 extensions 8087 ) { 8088 if (arguments[LEXICON.l] === 0) return this; 8089 8090 var arr = []; 8091 var optsIsPlainObj = FRAMEWORK.isPlainObject(options); 8092 var inst; 8093 var result; 8094 8095 //pluginTargetElements is null or undefined 8096 if (!pluginTargetElements) 8097 return optsIsPlainObj || !options ? result : arr; 8098 8099 /* 8100 pluginTargetElements will be converted to: 8101 1. A jQueryElement Array 8102 2. A HTMLElement Array 8103 3. A Array with a single HTML Element 8104 so pluginTargetElements is always a array. 8105 */ 8106 pluginTargetElements = 8107 pluginTargetElements[LEXICON.l] != undefined 8108 ? pluginTargetElements 8109 : [pluginTargetElements[0] || pluginTargetElements]; 8110 initOverlayScrollbarsStatics(); 8111 8112 if (pluginTargetElements[LEXICON.l] > 0) { 8113 if (optsIsPlainObj) { 8114 FRAMEWORK.each(pluginTargetElements, function (i, v) { 8115 inst = v; 8116 if (inst !== undefined) 8117 arr.push( 8118 OverlayScrollbarsInstance( 8119 inst, 8120 options, 8121 extensions, 8122 _pluginsGlobals, 8123 _pluginsAutoUpdateLoop 8124 ) 8125 ); 8126 }); 8127 } else { 8128 FRAMEWORK.each(pluginTargetElements, function (i, v) { 8129 inst = INSTANCES(v); 8130 if ( 8131 (options === "!" && _plugin.valid(inst)) || 8132 (COMPATIBILITY.type(options) == TYPES.f && options(v, inst)) 8133 ) 8134 arr.push(inst); 8135 else if (options === undefined) arr.push(inst); 8136 }); 8137 } 8138 result = arr[LEXICON.l] === 1 ? arr[0] : arr; 8139 } 8140 return result; 8141 }; 8142 8143 /** 8144 * Returns a object which contains global information about the plugin and each instance of it. 8145 * The returned object is just a copy, that means that changes to the returned object won't have any effect to the original object. 8146 */ 8147 _plugin.globals = function () { 8148 initOverlayScrollbarsStatics(); 8149 var globals = FRAMEWORK.extend(true, {}, _pluginsGlobals); 8150 delete globals["msie"]; 8151 return globals; 8152 }; 8153 8154 /** 8155 * Gets or Sets the default options for each new plugin initialization. 8156 * @param newDefaultOptions The object with which the default options shall be extended. 8157 */ 8158 _plugin.defaultOptions = function (newDefaultOptions) { 8159 initOverlayScrollbarsStatics(); 8160 var currDefaultOptions = _pluginsGlobals.defaultOptions; 8161 if (newDefaultOptions === undefined) 8162 return FRAMEWORK.extend(true, {}, currDefaultOptions); 8163 8164 //set the new default options 8165 _pluginsGlobals.defaultOptions = FRAMEWORK.extend( 8166 true, 8167 {}, 8168 currDefaultOptions, 8169 _pluginsOptions._validate( 8170 newDefaultOptions, 8171 _pluginsOptions._template, 8172 true, 8173 currDefaultOptions 8174 )._default 8175 ); 8176 }; 8177 8178 /** 8179 * Checks whether the passed instance is a non-destroyed OverlayScrollbars instance. 8180 * @param osInstance The potential OverlayScrollbars instance which shall be checked. 8181 * @returns {boolean} True if the passed value is a non-destroyed OverlayScrollbars instance, false otherwise. 8182 */ 8183 _plugin.valid = function (osInstance) { 8184 return ( 8185 osInstance instanceof _plugin && !osInstance.getState().destroyed 8186 ); 8187 }; 8188 8189 /** 8190 * Registers, Unregisters or returns a extension. 8191 * Register: Pass the name and the extension. (defaultOptions is optional) 8192 * Unregister: Pass the name and anything except a function as extension parameter. 8193 * Get extension: Pass the name of the extension which shall be got. 8194 * Get all extensions: Pass no arguments. 8195 * @param extensionName The name of the extension which shall be registered, unregistered or returned. 8196 * @param extension A function which generates the instance of the extension or anything other to remove a already registered extension. 8197 * @param defaultOptions The default options which shall be used for the registered extension. 8198 */ 8199 _plugin.extension = function (extensionName, extension, defaultOptions) { 8200 var extNameTypeString = COMPATIBILITY.type(extensionName) == TYPES.s; 8201 var argLen = arguments[LEXICON.l]; 8202 var i = 0; 8203 if (argLen < 1 || !extNameTypeString) { 8204 //return a copy of all extension objects 8205 return FRAMEWORK.extend( 8206 true, 8207 { length: _pluginsExtensions[LEXICON.l] }, 8208 _pluginsExtensions 8209 ); 8210 } else if (extNameTypeString) { 8211 if (COMPATIBILITY.type(extension) == TYPES.f) { 8212 //register extension 8213 _pluginsExtensions.push({ 8214 name: extensionName, 8215 extensionFactory: extension, 8216 defaultOptions: defaultOptions, 8217 }); 8218 } else { 8219 for (; i < _pluginsExtensions[LEXICON.l]; i++) { 8220 if (_pluginsExtensions[i].name === extensionName) { 8221 if (argLen > 1) 8222 _pluginsExtensions.splice(i, 1); //remove extension 8223 else return FRAMEWORK.extend(true, {}, _pluginsExtensions[i]); //return extension with the given name 8224 } 8225 } 8226 } 8227 } 8228 }; 8229 8230 return _plugin; 8231 })(); 8232 8233 if (JQUERY && JQUERY.fn) { 8234 /** 8235 * The jQuery initialization interface. 8236 * @param options The initial options for the construction of the plugin. To initialize the plugin, this option has to be a object! If it isn't a object, the instance(s) are returned and the plugin wont be initialized. 8237 * @param extensions The extension(s) which shall be added right after initialization. 8238 * @returns {*} After initialization it returns the jQuery element array, else it returns the instance(s) of the elements which are selected. 8239 */ 8240 JQUERY.fn.overlayScrollbars = function (options, extensions) { 8241 var _elements = this; 8242 if (JQUERY.isPlainObject(options)) { 8243 JQUERY.each(_elements, function () { 8244 PLUGIN(this, options, extensions); 8245 }); 8246 return _elements; 8247 } else return PLUGIN(_elements, options); 8248 }; 8249 } 8250 return PLUGIN; 8251 } 8252);
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.