From e0e5693493076170beeea09d9b1c1d3f7bccca8a Mon Sep 17 00:00:00 2001 From: REJack Date: Sun, 3 May 2020 13:23:08 +0200 Subject: [PATCH] update plugin files --- plugins/flag-icon-css/flags/1x1/fk.svg | 8 +- plugins/flag-icon-css/flags/1x1/gb.svg | 6 +- plugins/flag-icon-css/flags/1x1/ge.svg | 2 +- plugins/flag-icon-css/flags/1x1/gt.svg | 14 +- plugins/flag-icon-css/flags/1x1/nc.svg | 2 +- plugins/flag-icon-css/flags/1x1/ni.svg | 12 +- plugins/flag-icon-css/flags/1x1/np.svg | 2 +- plugins/flag-icon-css/flags/1x1/nz.svg | 4 +- plugins/flag-icon-css/flags/1x1/pf.svg | 2 +- plugins/flag-icon-css/flags/1x1/tt.svg | 2 +- plugins/flag-icon-css/flags/1x1/vg.svg | 10 +- plugins/flag-icon-css/flags/4x3/ge.svg | 2 +- plugins/flag-icon-css/flags/4x3/gt.svg | 14 +- plugins/flag-icon-css/flags/4x3/nc.svg | 2 +- plugins/fontawesome-free/css/svg-with-js.css | 2 +- .../fontawesome-free/css/svg-with-js.min.css | 2 +- .../webfonts/fa-regular-400.woff2 | Bin 13584 -> 13584 bytes plugins/fullcalendar-bootstrap/main.esm.js | 2 +- plugins/fullcalendar-bootstrap/main.js | 2 +- plugins/fullcalendar-bootstrap/main.min.js | 2 +- .../ion-rangeslider/css/ion.rangeSlider.css | 6 +- .../css/ion.rangeSlider.min.css | 2 +- plugins/jszip/jszip.js | 0 plugins/jszip/jszip.min.js | 0 .../css/OverlayScrollbars.css | 1248 +- .../css/OverlayScrollbars.min.css | 22 +- .../overlayScrollbars/js/OverlayScrollbars.js | 13304 ++++++++-------- .../js/jquery.overlayScrollbars.js | 11140 ++++++------- plugins/select2/js/i18n/af.js | 2 +- plugins/select2/js/i18n/ar.js | 2 +- plugins/select2/js/i18n/az.js | 2 +- plugins/select2/js/i18n/bg.js | 2 +- plugins/select2/js/i18n/bn.js | 2 +- plugins/select2/js/i18n/bs.js | 2 +- plugins/select2/js/i18n/ca.js | 2 +- plugins/select2/js/i18n/cs.js | 2 +- plugins/select2/js/i18n/da.js | 2 +- plugins/select2/js/i18n/de.js | 2 +- plugins/select2/js/i18n/dsb.js | 2 +- plugins/select2/js/i18n/el.js | 2 +- plugins/select2/js/i18n/en.js | 2 +- plugins/select2/js/i18n/es.js | 2 +- plugins/select2/js/i18n/et.js | 2 +- plugins/select2/js/i18n/eu.js | 2 +- plugins/select2/js/i18n/fa.js | 2 +- plugins/select2/js/i18n/fi.js | 2 +- plugins/select2/js/i18n/fr.js | 2 +- plugins/select2/js/i18n/gl.js | 2 +- plugins/select2/js/i18n/he.js | 2 +- plugins/select2/js/i18n/hi.js | 2 +- plugins/select2/js/i18n/hr.js | 2 +- plugins/select2/js/i18n/hsb.js | 2 +- plugins/select2/js/i18n/hu.js | 2 +- plugins/select2/js/i18n/hy.js | 2 +- plugins/select2/js/i18n/id.js | 2 +- plugins/select2/js/i18n/is.js | 2 +- plugins/select2/js/i18n/it.js | 2 +- plugins/select2/js/i18n/ja.js | 2 +- plugins/select2/js/i18n/ka.js | 2 +- plugins/select2/js/i18n/km.js | 2 +- plugins/select2/js/i18n/ko.js | 2 +- plugins/select2/js/i18n/lt.js | 2 +- plugins/select2/js/i18n/lv.js | 2 +- plugins/select2/js/i18n/mk.js | 2 +- plugins/select2/js/i18n/ms.js | 2 +- plugins/select2/js/i18n/nb.js | 2 +- plugins/select2/js/i18n/ne.js | 2 +- plugins/select2/js/i18n/nl.js | 2 +- plugins/select2/js/i18n/pl.js | 2 +- plugins/select2/js/i18n/ps.js | 2 +- plugins/select2/js/i18n/pt-BR.js | 2 +- plugins/select2/js/i18n/pt.js | 2 +- plugins/select2/js/i18n/ro.js | 2 +- plugins/select2/js/i18n/ru.js | 2 +- plugins/select2/js/i18n/sk.js | 2 +- plugins/select2/js/i18n/sl.js | 2 +- plugins/select2/js/i18n/sq.js | 2 +- plugins/select2/js/i18n/sr-Cyrl.js | 2 +- plugins/select2/js/i18n/sr.js | 2 +- plugins/select2/js/i18n/sv.js | 2 +- plugins/select2/js/i18n/th.js | 2 +- plugins/select2/js/i18n/tk.js | 2 +- plugins/select2/js/i18n/tr.js | 2 +- plugins/select2/js/i18n/uk.js | 2 +- plugins/select2/js/i18n/vi.js | 2 +- plugins/select2/js/i18n/zh-CN.js | 2 +- plugins/select2/js/i18n/zh-TW.js | 2 +- 87 files changed, 12966 insertions(+), 12966 deletions(-) mode change 100755 => 100644 plugins/jszip/jszip.js mode change 100755 => 100644 plugins/jszip/jszip.min.js diff --git a/plugins/flag-icon-css/flags/1x1/fk.svg b/plugins/flag-icon-css/flags/1x1/fk.svg index f99271969..12a34c46d 100644 --- a/plugins/flag-icon-css/flags/1x1/fk.svg +++ b/plugins/flag-icon-css/flags/1x1/fk.svg @@ -1,14 +1,14 @@ + + + + - - - - diff --git a/plugins/flag-icon-css/flags/1x1/gb.svg b/plugins/flag-icon-css/flags/1x1/gb.svg index 33fac0759..ef048dc2a 100644 --- a/plugins/flag-icon-css/flags/1x1/gb.svg +++ b/plugins/flag-icon-css/flags/1x1/gb.svg @@ -1,7 +1,7 @@ - - - + + + diff --git a/plugins/flag-icon-css/flags/1x1/ge.svg b/plugins/flag-icon-css/flags/1x1/ge.svg index 9e4ea3537..ac1d87bb4 100644 --- a/plugins/flag-icon-css/flags/1x1/ge.svg +++ b/plugins/flag-icon-css/flags/1x1/ge.svg @@ -2,5 +2,5 @@ - + diff --git a/plugins/flag-icon-css/flags/1x1/gt.svg b/plugins/flag-icon-css/flags/1x1/gt.svg index 22c84fa69..761801ca4 100644 --- a/plugins/flag-icon-css/flags/1x1/gt.svg +++ b/plugins/flag-icon-css/flags/1x1/gt.svg @@ -1,17 +1,17 @@ - - - - + + + + - - - + + + diff --git a/plugins/flag-icon-css/flags/1x1/nc.svg b/plugins/flag-icon-css/flags/1x1/nc.svg index 9235f5f1f..2bdf6ee5b 100644 --- a/plugins/flag-icon-css/flags/1x1/nc.svg +++ b/plugins/flag-icon-css/flags/1x1/nc.svg @@ -9,6 +9,6 @@ - + diff --git a/plugins/flag-icon-css/flags/1x1/ni.svg b/plugins/flag-icon-css/flags/1x1/ni.svg index 2cc7e6163..8f68d4225 100644 --- a/plugins/flag-icon-css/flags/1x1/ni.svg +++ b/plugins/flag-icon-css/flags/1x1/ni.svg @@ -1,10 +1,14 @@ + + + + + - @@ -19,11 +23,7 @@ - - - - - + diff --git a/plugins/flag-icon-css/flags/1x1/np.svg b/plugins/flag-icon-css/flags/1x1/np.svg index 9788faf0f..f34ee8c63 100644 --- a/plugins/flag-icon-css/flags/1x1/np.svg +++ b/plugins/flag-icon-css/flags/1x1/np.svg @@ -8,7 +8,7 @@ - + diff --git a/plugins/flag-icon-css/flags/1x1/nz.svg b/plugins/flag-icon-css/flags/1x1/nz.svg index e426d1493..5283a96ed 100644 --- a/plugins/flag-icon-css/flags/1x1/nz.svg +++ b/plugins/flag-icon-css/flags/1x1/nz.svg @@ -36,6 +36,6 @@ - - + + diff --git a/plugins/flag-icon-css/flags/1x1/pf.svg b/plugins/flag-icon-css/flags/1x1/pf.svg index 6b197bcea..94ff90cb2 100644 --- a/plugins/flag-icon-css/flags/1x1/pf.svg +++ b/plugins/flag-icon-css/flags/1x1/pf.svg @@ -5,7 +5,7 @@ - + diff --git a/plugins/flag-icon-css/flags/1x1/tt.svg b/plugins/flag-icon-css/flags/1x1/tt.svg index 8ab3e7719..87e439a07 100644 --- a/plugins/flag-icon-css/flags/1x1/tt.svg +++ b/plugins/flag-icon-css/flags/1x1/tt.svg @@ -1,5 +1,5 @@ - + diff --git a/plugins/flag-icon-css/flags/1x1/vg.svg b/plugins/flag-icon-css/flags/1x1/vg.svg index 260acdecd..9572de348 100644 --- a/plugins/flag-icon-css/flags/1x1/vg.svg +++ b/plugins/flag-icon-css/flags/1x1/vg.svg @@ -1,16 +1,16 @@ + + + + - - - - - + diff --git a/plugins/flag-icon-css/flags/4x3/ge.svg b/plugins/flag-icon-css/flags/4x3/ge.svg index cec14a005..8abdee305 100644 --- a/plugins/flag-icon-css/flags/4x3/ge.svg +++ b/plugins/flag-icon-css/flags/4x3/ge.svg @@ -2,5 +2,5 @@ - + diff --git a/plugins/flag-icon-css/flags/4x3/gt.svg b/plugins/flag-icon-css/flags/4x3/gt.svg index 75f2d960b..724e9702a 100644 --- a/plugins/flag-icon-css/flags/4x3/gt.svg +++ b/plugins/flag-icon-css/flags/4x3/gt.svg @@ -1,17 +1,17 @@ - - - - + + + + - - - + + + diff --git a/plugins/flag-icon-css/flags/4x3/nc.svg b/plugins/flag-icon-css/flags/4x3/nc.svg index 680afb910..4a2ac30c4 100644 --- a/plugins/flag-icon-css/flags/4x3/nc.svg +++ b/plugins/flag-icon-css/flags/4x3/nc.svg @@ -9,6 +9,6 @@ - + diff --git a/plugins/fontawesome-free/css/svg-with-js.css b/plugins/fontawesome-free/css/svg-with-js.css index 49b1315a4..dbca9475a 100644 --- a/plugins/fontawesome-free/css/svg-with-js.css +++ b/plugins/fontawesome-free/css/svg-with-js.css @@ -1,5 +1,5 @@ /*! - * Font Awesome Free 5.11.2 by @fontawesome - https://fontawesome.com + * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) */ svg:not(:root).svg-inline--fa { diff --git a/plugins/fontawesome-free/css/svg-with-js.min.css b/plugins/fontawesome-free/css/svg-with-js.min.css index 435a6dcba..08ef08c98 100644 --- a/plugins/fontawesome-free/css/svg-with-js.min.css +++ b/plugins/fontawesome-free/css/svg-with-js.min.css @@ -1,5 +1,5 @@ /*! - * Font Awesome Free 5.11.2 by @fontawesome - https://fontawesome.com + * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) */ .svg-inline--fa,svg:not(:root).svg-inline--fa{overflow:visible}.svg-inline--fa{display:inline-block;font-size:inherit;height:1em;vertical-align:-.125em}.svg-inline--fa.fa-lg{vertical-align:-.225em}.svg-inline--fa.fa-w-1{width:.0625em}.svg-inline--fa.fa-w-2{width:.125em}.svg-inline--fa.fa-w-3{width:.1875em}.svg-inline--fa.fa-w-4{width:.25em}.svg-inline--fa.fa-w-5{width:.3125em}.svg-inline--fa.fa-w-6{width:.375em}.svg-inline--fa.fa-w-7{width:.4375em}.svg-inline--fa.fa-w-8{width:.5em}.svg-inline--fa.fa-w-9{width:.5625em}.svg-inline--fa.fa-w-10{width:.625em}.svg-inline--fa.fa-w-11{width:.6875em}.svg-inline--fa.fa-w-12{width:.75em}.svg-inline--fa.fa-w-13{width:.8125em}.svg-inline--fa.fa-w-14{width:.875em}.svg-inline--fa.fa-w-15{width:.9375em}.svg-inline--fa.fa-w-16{width:1em}.svg-inline--fa.fa-w-17{width:1.0625em}.svg-inline--fa.fa-w-18{width:1.125em}.svg-inline--fa.fa-w-19{width:1.1875em}.svg-inline--fa.fa-w-20{width:1.25em}.svg-inline--fa.fa-pull-left{margin-right:.3em;width:auto}.svg-inline--fa.fa-pull-right{margin-left:.3em;width:auto}.svg-inline--fa.fa-border{height:1.5em}.svg-inline--fa.fa-li{width:2em}.svg-inline--fa.fa-fw{width:1.25em}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers-text{left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter{background-color:#ff253a;border-radius:1em;-webkit-box-sizing:border-box;box-sizing:border-box;color:#fff;height:1.5em;line-height:1;max-width:5em;min-width:1.5em;overflow:hidden;padding:.25em;right:0;text-overflow:ellipsis;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-bottom-right{bottom:0;right:0;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom right;transform-origin:bottom right}.fa-layers-bottom-left{bottom:0;left:0;right:auto;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom left;transform-origin:bottom left}.fa-layers-top-right{right:0;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-top-left{left:0;right:auto;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top left;transform-origin:top left}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;position:relative;width:2.5em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.svg-inline--fa.fa-stack-1x{height:1em;width:1.25em}.svg-inline--fa.fa-stack-2x{height:2em;width:2.5em}.fa-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.svg-inline--fa .fa-primary{fill:var(--fa-primary-color,currentColor);opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa .fa-secondary{fill:var(--fa-secondary-color,currentColor)}.svg-inline--fa .fa-secondary,.svg-inline--fa.fa-swap-opacity .fa-primary{opacity:.4;opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-secondary{opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa mask .fa-primary,.svg-inline--fa mask .fa-secondary{fill:#000}.fad.fa-inverse{color:#fff} \ No newline at end of file diff --git a/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 b/plugins/fontawesome-free/webfonts/fa-regular-400.woff2 index 2e72e872c61b8a0b541de0a009ffeb8f538cbf5a..7e0118e526eb53511cb57e7cfaf515784fee4345 100644 GIT binary patch literal 13584 zcmV+rHSfxIPew8T0RR9105uQ*4FCWD0EH|705rA%O9Bi400000000000000000000 z0000#Mn+Uk92y=5U;u|&5eN!_-9Uk@N&z+kBm;z03xYNP1Rw>9TL+IT8yRaC#xYae z4xrTj=RL^&|34)`jUj`_9q62HRTU@G3g7X=Vg1b6uhqq7u2e{@>ogp;1Gm5-a0ndb zszDw81qS5!`3YCJ0$ph2KdxyZy?beXaxZw$ zb^xFVm7EhZa?(t?&6iXAncv$?dlNWuVZoRbcDX^R?D_! zTY*yQu*)D=;&0Uy{d=*ymjN^Nn0a_g!*-Y6r7M|)RY0_Km&y`gX#iCi081MlgfV7A zd~|GxbgN0*P1&TAEJ-942rVI(1O!V0q4WfjP-6w)?wi)0-QSq|~Q$ zFo9}%MD41`OdYyQ<)wJ@_GChes%)f?06@AX@h z`u|J9UtaPsHAkQ+p|;qThGzbZ|@P2e(-3;+WO&z?)=%K0%lA674|Ti(*zzV&~ey%(cq z|G)kF_Fp6(_z2MuLmWw@kwHG?w6dAcxXKv!dC52Y#^*87RP!vb)@5#RlY27yA+@TJ3puO#= zt5q#7A@9#h{+>PJjHh?Mk(*?u^Z)u&w_eoKx?4B-;_o78Q8mh}tVts>KKzGgbiir` zOrgnP=O#C!-ajMlFTFiZRuZu;r>TwB1@1^Q#eNTE(z++o0dvIpv0>n8&>&rQd=Lf$ zBQbHrgsW?`Qh{M{NlK2!5jTVE@Hj28Vmaa{b|N{vj0?W2IhuIH(T%1e5|YM*Vm|N& zj@Jc&I1SD;00yrxT-q4=d1`RjmK0#`b4a7aTvUA=fPh^}*PTT4r=;+1JJk}+{nbMwdsTJxW$!m1 zR=YPh>(7v~a|f*Sasx#GChdXTQnOi`N*Wl2cd$8NtvfzY$b4bS-e&@p+#szILI$OO z#TQC?AxuF`NBqW2zG}*CutrIiGER_UL;!ru!19%mQ6&@i=B#U?=|WZRa?Yz1vp4iZ zb|L#K)(N$%8Umk!{UGA#d`4MQ=#;EQ4sAkg{8pOa9LBAPxJpAJPn%jRgd}-fd_gb- z9RnvZfc3tQ);8a6Xj4&GFqo@Zoj6(7i#GHUGjKL`!ovD|4C2D9T{OA=ZR3n$nAKL! zGU}Z)vBbGNAs+2B&3-;D!!QkEmS_aBTd1%D4GGpg`oM&Ejd&OFKH^JI!q`b@WXJAH z`xSlT{P=>y`(3`LiQ^0HVM|1_;Bi4FR|>35+hCy6Gzjn$dIm1w5sC*eB4^M{;8h#i zEw|$YDVSK5lqvD2Kz8OSVvM*Oj4b>#1#I3x1ldNr&jyq(R%F8OzRGIw#O1=ujH@@u zV6}{E2Gw6`C)eGC_ZD>ni3LnB3`$-_Fs!pxK4XyQ)<8Zh+i%NqK#LpNwsF)j$k0Zi z6pjqaYHBDQJ`$&1J9;?w84&uhqx%d>^~kZ>A`gfE41=Svq1(A)FwOD>1eoLLv|IH$ zr~s|O^QA5iF%V6}I#aNB-NAYlmLAe4h0r-x4?>f}+*ZPp(!?JKM^7m1GiX9$%=wJb zDEgcOio#6Mz7Y{Ly2Mh4Pwr@m!SuGJ#LaB1Tq$}VMZuBfYlBsBe4OStJbZvHTnmk_ zTGLt{MWj~G07^9|3Z#?}P!mO^M zz=mR~lJW=h*$L_&v~NO4J#qp%wWBCMr&m%&#T)OU&JQ{Ts)t(x@;&qahb%lORry6F z4sjaj+=momXE8V#Sgx@hU<%K9o2$Hnc(9HbuN2zTBB;TtdC^=+v?7XtQ`rVCjHQ^5 zDSm!9fOx%=+m{rE+h1Yj^VvpLX#FK1_D-A{{A2t7xeF49PgUmfvO7T^ycp~ymo8q4t4z5bE@rGL z^h?Pu`7Lc!-#x1YRnojHXa(80Htl5dn)GFZ(in6i{kQQN>Pcf!e*%{DC)4Vfx7;hB z(yAk$lrx3XFVP-c!5KzH_4lU3bPxu*9QOjOXMkeT0HT8&;}D3Iic%?zWI$tT3Wwg2 zo+i&}p(9*oa|-bW#|-fTt6d#cc@eg8&_v(_YMdH!!?Wh~(#|rWsnRC<@qL@lsI01< z$Dt$-n=3p0qEUhwOgEc1+v2{INMp~BX#Huz>X%GRB8~7 zwwOws4q^-BP9wW}jfUDNPW53gfrjm(sfZg>@2bzJ@j--tGcuO1dnACTMe+KrVMH zz>dzEmmjr0VTvkkqz@~&>FV6q??FS{k1DHM8P=Y}!kWR!ZvTkYE8H@ttKh}AH9b_- z-s2P+;evPV$hnc|T_LoM0(pwA>o~Qlff7EVt~$*U8z#b6^)J1$U%IcIhz3r_ZQ1R# zDZJvVg=xyP+q{A0%K-kmb#jq?G*~N7mATEP=xFiUA!F^Dsuz3IZ(&w~2$$fvSf!bfCPVmcrITz|XlObgJ9SYP|g16&Ze< zAY(fl$9957Fz~Vsk4?(fcBUb;0UaqXx z=V(~2m;Krb=@wp5SX1k`1y&a|eNRmKT~nuUB!0~r`b=kXsvk+{deHNrSHI#&s9!T> zRnq|s3Io)&1Gg1}i4QM)_4jg66Z+ePVAtJ;8jAeeMDAnjF|=Mf$11x)A+tFfp}6pPAtIduThgDz=7IXuT{B5-EQ8L`ZNe-Ls9CPFE&{XG?ZmK z``|64qZ6q|Vw|h}L#;LutO?F=Who!-5~4tHo>h~x!Zr{He^_prmcPteB1?pr7C2ng z2#;ZWDjH%6wX{R{4sL-sQok8_IFmY4sEj;BbP?leG}Q;B9!oH;%S+>U;3BE+Ut$b7 zHPjoFEZ545nrNaaRM<$Xg*?&deYPdf{RV&&Zgx=A75O}J}_+Q=`G^gRaH91jNa@&ZOUebH*{<<9Tw-{ zHF}_i+S2}p4}TnRCeyvR0MICU2q5|RDs)i0Q8;PYUHHl&FKLrWS*ee2(P>v+Z?qW&YOzg}(0hrFG27DZ1|H!@WsEdVq7( z9Cub8zVeE7>Mem*E`Vq=Ec0Z?Gtn8q)FP_qU9(w zt|P`)oRFFD;};oHA78f7Ft(7}dsl-4#Co{-ZSxR3+-6zpFKjU%?OU}K-T#*Ios|jm zi;^NsfDdg7&98c+6lJ)%Xb-{;L@=3L4+;+oe4legVRJ~JdDIhlvy9NB=~I)QcMjh9 zPTa!U;M38Qy5wN(iyR*_^tJamMNp0!=#eaq$bDqMY;7I1!2Wdvbo1xPw#{X_8iF3Bhp0< zv_Mz~9d?%VB}!=>#7(ZYXi2!FbrPZy`0`ysPsFG*aSSE_@CwrsOSgtShfv&&M@rq1 zzM~EW2SFzb^O%&Yg91cz^$aD-;fL&J-Y&n0UDTJ-Ok5Y4*KrZiVc;yPNWX{uT@+r z62o;(t68;6`QYOuZrAL1vci7`CQ`kQ>r0E5NHAurCa#|8-cF0LG;-&i9`3B>)oV|( z=AAv}6v!UQ7!37TI+4(zS)#4!Z8cMsELTk~Wml@34tfVrqQ7i|ko5xLMoU_L!^W13 zw$+Lg5dGd#A&6`XD8}g!xwA=-f#_NdVlepF5-3RiRM4Mj z_r0B#fse(v-b!{2*{LfAYwEzEW15ZabYYc7ISxWxIC?U#9>*@%IT+3sP zX^}H>e~PQPT%%6OM!I54lrbfU9QdS`3&b&mP{8zW&F~QBjuzV;#rE_7on?3XbL-=5BJr~CihE1l`*{uXEdkbI)@yz99ZVtDTlScs|( zP2BUZ&HgnRFE2GqXolAq8kjv1HQc=gddU_4lR~5NVpzjIfEV9Q|xj(k(rE*0v zxf(^!E;mY3lkXAf%dMVj+Tc9iP@@wlr^N@|j%d1d)D~ed~26*#_S-WSr*v6bqsK5 z(e+8wgrgsW2L}6b3w_z@P*|IE;!hkgx|FI(EaP@JseigwQP(WhV|2+?(}a7vqu6GW zL4IsI3@VWqH&+&~3j}Umt3S>PW=+*)66vf=`KVNQ`$>mu`?NKohDXxJT#&0 zx`m44*W_Id-9H~TMwB!eZjlQEnsy%-JOhT?T%v6(n@S znj%j~h=R~_qUQNkSfZ*_l4?cCaNy}>zmS8AIg-kms|^&GD;#}rKsb`B#X(8AtrQB% zoCmZYi{Xled456>>ZLz#fT5<6& zVB9tmT6py2c*77G$b~oQ21~(``Z){asTcjSNv@m@5g*U@3#m@fI2|Wp+Zs22E-k5A zU2@uV4IJZ9-FT_ir&NkrLYJN=CDvTAwf!|Wm15*ArFRqke|HRmNHrR^Y|+T4XzYo< zs6}WbXMm`NVjZZY9wTAwfas@x1TiLNlGUD;C2G3#RrSR4HBd}=5VaF+fi4@|vx;+Z z;th54s&or|)5eS2ggzzP;o9tKR6Xl2UDl zFT(*L^_d@OhR&)aTrub+wL#=MhInHG4C3 zAB?Ig^tRTof zNhSP3fWqph}Qr^%a1T8TxKcAEcp znX(s(W~y0_>3?8M_Nhw``=be9GJ{woJnuWXoNz3+E>%7OHI235pLmD{cAH8pT};`3 z@d)NL35H>NrO-35o%9YgYkXX666e;_a)+ynY(RxJ&)5C7NQN|wGwLJ~`q&6qF3_xb zCD~#}xC;{gR_swnYAe4P6zK3HEe@IP$85_6V^!9p4>27>{E{WP0=t1erD(!XBai{1 zx}Gxuc8@oF&4$SFC#fBJ9eDn+BExRO<9^7)Z}`-61VT;?!3HREN&S0vSZ`?)woPPc zb&y^krIRjxayZM7>aD@vJXX5WQ_BIYE@Ziyn+zxeY6C1wlIgG;9 zHrMZl`w( z?>%+a*pXv08K9S{Pfjgxpk316h^viWPx@Wjc^5dQPO7`S3~N>?R%HYFyq*pSvJSG9<3aup{DR9yUx$br^_>NF!we((;}t@$M+VT% z_&Y#_`(eO?Rc)L30T#{iDHr)fOuP$Ekt2a=lrzGa9IbLZ3A%|6)q?7z(~0j*>C|5{(CVv_-Fi?S2fu08_U;Z|;Y|wzLzj zszG%BX*y|TiadJK#c#FmO;e&FR|*=rRv6Ou>WGlWc562Ve$xOFVwf+?UScg+wMFpe zWwaJuTlVvU9Skh4M3Lvk^1AH-CS^XbrC)&{-&sYJ>vBkuznW1SG<7sc_9Hu0U7^~& ztZlJ+gmOkyiv#U}eBB*v>%YCN@sQSYp=!zylEgT(gZZqiI6f|O=C|5du+}VxzM0XQ zMqTgH6AwO_>&OEWdd>*v8LLHYp}HNT^k!ZK4`%EvPKUt}1oP{yPOaWEO)bsBPN=5x{aKr}ymwUPLn z4DIZ^w*8=sQ_G3zvcA*6`01WK7sENO@NPfjl+kzDQdiW{{M`FWv=v>$B(m6cJXT~h zieiIoSkLQ6z1vc!;d-t!A5K4m(buxJs3?JW71IYhmM(Qv1NsSS{za;t0?_gmK~Uhc zQmwLMn*+}d1htnc5F~-lbV;KWmADS!@E`9b%?2RX7}eCL1h1G=9-If~iR#rB%lH`uZAF`?(rcFvS6 zftT1P&Ez9;pFl>}akg#~7Q~aZPIz}~5(LVUGyJ7q%4m45I!7Rvf*+M}1@&9$=gJqn9a6f#ZJ-?@GCoNc{7UGs?a^=UivCmh_bFhhjhNYpE zwBia8R_r}$z>#W!_GnFc7F}F0*AqbCUrlyuf!AAk9=py{ky2}Zg zqa2q!m@ErA`r|@F$mube?>N2E#QiEyKu~EaX7GL`kyv?u5Yy`u)c>1jI4CxZvF^dn zdbG9U!CJ8z z?D;uVmz1Q_CMSl4{_F|n!l5Sl+{R^lt)KdUH@Xc%*F2Plrg8 zv=xIIuaY{7a<>X9KdF84&K!Q_^)K^=T3^&*=ioU%j<_Dj4GnIa8>l5yim8qc$3Afw zZkO0~B>QMXa8k&e@JYje3D^kn-f~G)2l!!DNParinXTYQ-7VKP{krq()>WP8$gXXc zK{zOhm90e(JgFw!TY}3ZWDR^0$eVXklNZ&Iw7Vn9u9=-j>(e65;W28Sf&(}bT8tjU(_96H5=97DTDO)aY<>_Q0g7G2Qf&aF{{j4OS4M-b> z{#6`1B>7&mYbb@re|I^fJ-5X^WPTTk_7>hxoNn$KBt;o~{TBIp4^t3Uoogn4nv0pZ zbQYC;g$2HUE(j8wrp9Tfr;Tycrn5oEnpT)`N=J=7?a5Cm+aC=+inTX+R;FlEG|b#w zre;>9T=WJ~vxb@H_744)dE>Z;xkL%NarFzgZM&`eun;XZX0!!7PnGNKrbh%cajsJx zIg#1ec*wp5nW0w2c?*5bBHIUQOScrzTk86_ABoAzXk))DV_We*v?)8r|#SxG%TP@LYKBEWio!~RL{-pTZS_QLFE^b87P@BKY*B15T`ruO{* zBfrzRn6hUpwx@oMrQv*irL)?;>=F*1bJ3z>4R>S=#04KsFz^;Gej8ehl8?XJE;=A4 zDwy#o$(xJ@Ub+|J)j(j9y;(>M-QD@ar_%C%!LI6x@1dw*2))e*Q-7wid1)m6f? zU|-g!!!%!ecBL*P^?o1SD*ttwzT&AYzH}dg#0urJDC+zJ>t1#JK%`?;bH&e96j7C+ zlyTk|1;x-Psxr)&!O7op{=H)4*b16OVoLgE3C|c-L++ci&?Mav>PkWxVusn%b&;8= zy3xh(eiP5KhcC}12d@*TDDcKNth*awivHw%U&)a=EW9gegvI!tI~(sL2sN>)(=F*Y0W z&s5P$c{~Gu)~`~8ji9T~3QwFCJv-B(Edw0kqBBmR@w@8pVmO>tRuLMbojYDV9upNs zd+b^BnC5f7%x)G2@DJrROEL(x}DF>YkHWY$~`g(hZY`5eeNpt1kQ*~Yd+$fQngmi&%FckAb+ndkcJ ze^JcI&=7De;lh0g^dNH!k7k@Um=(k9dNrsIEADGi!*tXs;W>MZwu zk@{ZxCPsIYFOwaF?~9$KGrlcx_n}n>e%2!ZnUR9GEX42=7XpRJ`lZ-n@y!9yBL{ME z@kR$z%auB<6?`*J@v1wki;h&!PC<|q6lk6z9@I(C_E~7Q+9%)or~P8`qU_Y^MHl{F zFci&!NK*3_s4HCWk(`aZHX99M*T+@CXlbu+oP9~nc@5KVqTB7y)Fv=7IOaQggeMXRI2;B8K(V!08zF1*M-%)tnTE_2eevTpjJ`fP?1tf&YCf}N zhCtm$!T4WF0MuF=02#}T#DMTGV1!Sp-5Sa#KZZF=0!x!YZQ6zVK5KcgvsMREktfW) z`hCCF7hRyNl=%P7Hes}HXG{2#YZ31NY6=Qq1nfWpy^&tzMWOBR8HDeRd;xEVQsR4{ z&+#~tS+PfVd`ktQs~Nb)uMY(?PFmOhCsvj%IxzQusDPNpy5`DqUF!_rO(_mz`H%4~ zl-2W#iLt6UEaQHXUeL!VYm39)_U6XIIPo5R#g^ScVrFmT777Bj!-I_b_Zfq5ds<;a zq-!%G%u-ooa~BBi3zjc`mQd=e#;QQINr$XU+amFc?Xh$%A zuJY9ULCgHW-65yui7NCLjA^pQE;(V%2l|7mDYilK)jUC`Tx5GAohGua8UN z9hc5o)Kd==4+tIM4q+1BnRpGVUtlcGc`J}bI!;&e>oHg>RrW*h;iZIaypVtyUX$RL zhT~<3w>Kig$Cu)F{1G_*5p*-A+u;U?Q4O#i=cS3pU0lh~?Ir}b0=o&CCCSgAK{STh z3oMwKwqi9mj-+Xg`Afozk0yn89&!zb#k?zFr4b8iH6Z%~v1(f!DJ(U3p)LxU#68H^ zw5ir;Oc$X6vmeEOBusj171pBIT#MZv|!TRIt z34ajk@g|2&Q^(pamXK3;41ocddQk*PNf9vf^XOFV-I$e|Tu&CDIXX@E;uH%{0BtUt z&D91P&Z!Nq(P{n{M?WoBV|=b`+SJyNlr)Rn{>+DqB~^cUf8}za8~gvSfc$;9 zD*Hf*HJL=(bf07Z^)vpLJo;fet)1$oxvAT*an{PrR>rw;w~lWuiNHuOQ-Li)d)5%H z?;8p=zC53<+Lbw`Fqvsi^C3{3N>Jg8rOLSe2? zbzzd!XDAi6acsQ#r+uWQY53^>uuOB*Y|N(*DjAjc_hMezVi~yq2JR5i*~X6-{T)^! zBdcu1wqpKX^l{_!hSth|^l1>G3xnV6y)OBuvb6zxF5(zCw6$5>@FRKv35CU)R33w8 zXhLf{-s7G6oQEKkq-GyBky806`HZ$YZfVO8lJ zO<*GHNuQjYH7d^v`>GaK{h4xWbKT7cKC{05vQ;iK8Z7i2%VIFDG2jyAi8#Y=YRR7Q zPOxagBlZ*(tvM3AIl5j)@^&@iXJQGC73%!6aI;N?k^e19DbDYa`}Mbf_+waNwYZrs=iD2XM?@pQgVo&h=XD$T$}*FPgrPJDrUopZIlGNwpbx3P(D5t8j$l(j6&MdEpeG_ zs|=B4b!OaO9yy$%iqI6r5Q|WCPSw}uAG#t-J6!$7evSPnuV(a*2rb~L%;8b_f^wO* zat4ve$R-kLu;uFyo;BbVGfgKW+=G_KK>U4X`$=z{tcvat#0cVwhV5BBUD1`_-MHay zvo*NYvp3k<+^#0D`u(N8;fZq}^e#7p3}*6sWJ zPP?sdVS%g%!>rBxh3KmJ_P+CdU4GS#ewxJi)2ll(NSjT()tv!`WBQEF)u$4O-k)VG z0|yOv7)-p)C~xh-g(D0blWAj|hr1>DLG7wFZBs&cW$4^eUY=v_jKw@Lkh8eZW70Oe zPOVzmCoN`TSmo}H$`f0yuUD!0bI&Fbudk+QX{)ajlYYq%e`>1Ymr@~K5vm}yEm2$bJ5Kz+J8zWEbL&yMAtFs42JIhMJE z*IzI7q@P;6zEE(B&66j4emwGPR-EdXU_?3Ygkk5CT9Yb+mXYEst6^=X6ZWSz4r=uV z2cD8Hol!AWGtzZ?!hDQ^?(+Bq=iH>St@~~$*CELlaN-ept zRoR0Yj?3tlDGc&y4w*A8Hz;J?8TeZD`}gWvT&l~1m7B$CGCs_5pmvnFniQ5b5hWe( zFr-r|O-Fnrm60p;!4jV%ErpRa5&4Ha&VrcoMGrLS6;YUdlpJ4Gv=wzPe$NDAkDRO~ zZRiUU+8c`Yu)_ZfMt3LigSa%VATVh+8pMy|vnG*2Vq{^&bge4lEI^z`2`&v!CM>)( zm~!T)=HxgoSc@K~>dkyYe{n582wTqLT5iGM-{?2?$OJ9;ZMAQ^?Hw$M-=*pDmiEps zh;aiAMbT%}ytAd&@s=pbk>xj6kA)kCvsWh=@(z0N-wyUxb3;P7jP;Wk$cvBxC3q)5 zYKj_4;K#%15ZC;}KEdIgas)DYm!g2Z{&e)gpZj*6tlb*>@7uW~aE#N)2J5x+G;D&at-k z$Xj;HH;@505b|T@C~3+(kNJcKIHI#dmA|cz%blC0rl5epCNnzEQxIhz$8}s+Q~SjE zQ}No)Y;?AyV`!|-eY zhxwoPImN~^9lK$TZkZy?Zu_Cp+;miPV~wA``-vT1de}3sX6yxhg<0 z0^|2_j#e_ys3d3!Mq=a^osiBgaI)*_B$>bvt9J-mk-IX8%+$G{8{95EEj#*=qRz^%SWFb@7e}!`aq%gi;PK3h}Ojs zdrOoxO7+r2LL5LlKWSF7*t+h=!9F61Dd5m+%g{Lr-HL&_4IUV}W9>Upx1E*Rq+5=> zF?909G8KlEG{J!1Cc4c^{9{X2#DN7Yl{Nb1$HDqdD(lp}NcGr(o3TR=0VH9;Q;ywt zD-C?tZ4IvamJ|15GO3sXVnwh%n%YeSnr(U04)T+$3dj7;$~6v#|4G~BM>-*ofh-=W zg8%*cmSfQmupR&N?^Xv5Uw-d_Bbz{>LN`O!e;r(-XaP6}V+`m9G7~o2u|KeY8{h#j zLhd;r5Z2T{Qu@{R+h*w-E5Z0Sne!JX_!)2|M{;#WYGu5|jDRU(h%>RXn1dWviJlZ& zT9A&0Du8ZCQv~ z1Y@^S6nNMlDF$HU)D#oI!A7xw0JjZ$`EU5Z$}ROT2w)Nt06dNyjHCdL8>qVPi(r=UVM?D{nQ%~VVwQ@wr(QQVumMA5tlCo9!W${VTVrj$n~YX zklNcI;|T;`R_yTfM0ipC9x^Y&*Sv$=H~g>s0?4u6ELFq|Oo69EnMu202!E zf+;8;q^UvcOU`NPvi~X12+c-neMFkvDL>>x%hMS}NSdi8nq!y!LtU{7ztc8esa6eH z)~}LFb_$I0%s?zpaVY%IDw6d>K)!`ClM+NMD}(-Hs*xnD5x$fs0V9V9%Qms;qAhqr zponZL5t)a+jZ&~Hj_rLCi@r*B|rWNcz;W^Q3=wcc!Z`@`{czFcqj$Mg06e1CsSJ@?NLw02fO zyJo1pXYu>MWYq!JZe`epMPyH)drt{A>@ZNBDB2Bl_LZ`|ZD>Rg(PXd&V1% z#$?VIEY2Pna{$G>+M}10FxSH>98jn88l4o(qmQ7~EucdHr;Qn$#6{q>XH1eOuS87G zdC>42LwJvngDXP0x-LKY?dGD4Ykg4$wc_)DgIsdwrQAA$Gal@}f#QJqj4TC5#&nmL z#!I&#^AN=fRp6;`GZ#=eE%lw-3c$T}p8 zCJSI0X$qKqcpz2}L~iQa=kl$5YN!MPx|JA*6Rd3QSYu0z1rw(WL~%==t>rF>WbClI zW}kvoLQgp?jW|%=FnLQ@N85i94JS1OuO9i$$14}ql4U*-*N_>6g8E2jd~JsoNPgPS z6j0Drdx2+UTFHM9d7BCpR96@>9@bVD;W6XIy!canFnm?+!?PF$=b==R9BU1;EPv>$ z+f-V4b+}sI6`rh;-)}BU#a=3%ag5S*V=x=}!mr}@(*>o%u+B%DCo@r-+)Q^UI0MBc zY|_k8GHS#w1dlH~4;jYs>O$1l?NNi$0rb)FoS;ks0O=Pt7ifkx0tz5Yxgvt+vj{uB zuq|pvJ!c3((abern*)kW=hO_fZlfu<1;U0$8$MX)+l6wFi%W2&M0a#=PI<%EJc?FD zakPwLE5nXsRj`;%a;Wnl8$DAI0rwB61_$13iir2(Kp@+t{{@Jd(|_$(-OBTZ=`~5l zn_Gyvf>^>3KiKE8^9QMRYM$8nRkZhzH@)?N?)Teqbwdmufl)z(WIrDHr z%?H_C3qpERgPmOv>f}b9sbJTWxBo`DeuTP;pmw@*R2@N>@K;?WZw)`MY_yd3TbOl* z2zUwTb}}1JOs0?oJsCoRdxo~flZhS*^ACfQg&}NG!iUui;NLG(Q(>mOIlQ4A4TAG} W8!VVrwhAGt$p&j$lnnbyiU9!e_&Ztv literal 13584 zcmV+rHSfxIPew8T0RR9105uQ*4FCWD0EI9B05rA%N`HI+00000000000000000000 z0000#Mn+Uk92y=5U;u|&5eN!_-9&+{Q2{mrBm;z03xYNP1Rw>9TL+IT8z5^nTE9~|uwV!F;y3O+YE39pZ|N28FY4PJu2$H3 zwt4=(TZ*$_Rk_DfdaDnmgoy0^tDf0?U*O5kE~4p6|czy+q2W+<8!wiFwuw#@XBy1M3XU0G`PZ7oM#V_Ey^mUU|i@y`wK*Ncxs zOE~dfDdf|kYhiUl8U`&Q(=SDyQ%uKr!!YGaE#|9m1p10W?__xHWWjeFRX7&V_sY^`7 z9TJxE-74g>OVA0BZ`w^i0OkZxga$CA;vSqA@`!^N%BeMT{mryLfs+&#j7eda3j~s; zy?mN_@BCVRd`4f*mu#zL+cE@7Y0ya-1dFh&X-iwJ-k6^s-$#TfIRoJm=o*-3&J%bE z4S@DWcY2-nwf63PK+s`H^+%firvF8$_nsu@=}C5EM@bZgY%e(u$q@2pN0ODS?PPZx z2Npgs8Iqkii%vc;wMRrn|L5B4nk!mruV|aoF-4-?vnvE}Rd%$4%vlY~7CW?vXaOa% z5+IO}uvWeMQ4kP-7gdM9teuXWK9d`?STGO^fI+aV1;laP6>#L;EWrh7Jwt(JV3ptO ztO0{-Ih;hoxoho*HW`e5biUoWQj}78KxZW(MrzJZAYB%%Atb~7<}vpA|Gi|e<_xe8 z#Ydq6Tp-wFl1(XfX-qDQs9_0pETfqg+StOU_}Ir~uJMBJ_?aKumx(4@$;KvVFx^ZG zEVso?{?F@<_|VsW>u+8;lAN^Ur!cN8&H8Lie+Dv?FLNPx@-#mTdSugU_Rj4^T?g0W zX4ToH-O%3d?a7|$g)$$ZOPYv;=$owq02Ejuhu<3^`; zIiK-E>i&t1^>kbJG~(lB`hUkA_QAKl@s$s}?Mb(~#Z7K>jVoQ^B4;?!@s6>lJ#1)o zD_CN_v4$JQd0ynV%Wk!3q_BfJEVon*2Rkb>J?MNqH|bCMbX1gwI^3ZSwyzy^wz7pK z<^SUk-?^IulZ-jcamSzVz2(L$F0K}T7ePZb;v=)Nm_}rL_zw>UEX{x^G+F1|v@*Tt zL(WGi`u#Z3k%;MX>MZ_OxFgmS-Fqk#+dUB%Fh}fsY-F&XL4&xmD-^R~bBp^I?EHN;a%N#|QNDeRKg72z>A0E-yjV23`kTfO~^MMDZfy=lc z5KDtI4S>Nb6fSM>-7?lVY)1;X?0d>e(_2k;A>k1U?hC+siA52E9I~ttLqs-;wqc0} zp@|1G9UzjG0`B+qK?iu)!`-yTy4GH0fI{bK507jS-8<%SOajR~ParDT4WY>D8s@$W z6{mb`f!d1l?en`@PC2iSaE-%L0u8-je5COHL3Ll04lMj=*bk)+C#8Zq1pKb4#jMfZ z2EsvZ6o=Ajen{TcPM4stTZpO-JrHt8Y1@m4!59_3FK#uWxv#pf<)|pm{_OMSWjZ|l zaPN?E@B~bHT%!oUq&<{-YO!b{rGb(A0Gl3jdw!yj_`=XWPRN01(1nVAqU_-n{yo-1r@g*Q(>?SOtvG-Q{i10fx9WHcL|5MT=}&r7TY3_4AR4t~bYzy&-a@dRcl7<4eu)`qm{wcSn% zCRQmWMuI5-O+Q795qEOuf}Zfoc<2kqy85DyzX0mj^2|p3x$M)dt-% zsQywbx%M`Ep!5wSI@w?vP=ZA;th-k}V^EadK|Z7Hw`Hlr3L9F~I%-*DaHG`nM+Ov| zYKn)C#Hlup9*%wcrFrb=z5_}>a;&l-!r?!|;3#b5cA;6^aC`v)=6G6ZvsMEP&^r7; znd%S&(Lk(m4SU-itXCoRkUk}ZDX``t3^gRE7E($Re;{2m;c&oW35hXhvqqxma{*M- zxGBarGJ?ibSo+Y(8!fT8-n5i>>5a^lqW4kc9A3V*vnq~{v)qP<53qx4k+D^4n#-ez zlxKXL*FjiabMXID~I*&FYo&JH*QnvZ)2iaiVdk1RYWvi!mdrvwjl z?n6p(uo#>SER)#|FpcM;C3I0nJXk}FS4!h)5!BAAxw^TEXhjqOJ(a2B!q^JgxEADw zIuNgS3j316aQiE)TrN}3NTat1>b)CVgMW1Y?OsUn(`U|~4_}6N@7}ns)$Y$->{I8? zUb>XLNgg~HpD+X4pG(*7-oG32SM~gb^Qm$-rzXbPgBJty$)$^z;tJQUhl@FHNb^#% zOMT1gm3QAQ55S}aMbInKackO%ww>^0gVH!mqJp=H>iS7*(Rcz@`%`Fj!dvVW&~mee zVy>OZpMHtBgUVF`-~Qv~Kc=!kn!d37_*+ml$un!!d}KVtPuuO#>?MDZO>53$;R zoIxjCh^`$uH$CZ@DX!W8BV=nB79Z<(kuGXd+kQ7sfZKqA) zC0{MHDVw%L9V<{B`0LKeMgGy^%{-OnH5#&Q#A^qcpd4`)DEB14LyyBWsx42xG-IV4 zWD(HK{BjDp=Cy5O5V4*U=!#qK3lO**Z5!0BO^QNbH zi<67O5m-a<)VmJe9LyPM1%Z};+r%O0K-I%)22fv7OW|lC;OBgkI@Rr^bwNLGLyjLe zz}TMR++NTL241$|u}L}F&J=_8rZl zWnsBq_G>F-TSQso4WsSlc}-T$J+b+Bb%WAX__b*0Gd-A7{fH&|p#2XzpkHxV>eoy~ z)pP)ZwE^ndNl?w=^23in|D6tM!hV|&EFXKMYFOr&d6NNXlc&ihjHKa^@6!J6QVR2B2#Eh0)3=UTS~FKi8g@P~98Z0XCaC9-9N?SR8Y zUF|W9PerSqLM`PKzC}17kJN8Qna-rnfCQ2yjTJH5`}qnIeO8Mw~YZWFq2?0?7=0i z#g*SW>;R`jEZ7ICXm!^3E|#ERhzzTHOBaz2pP7QV3a2_v@3$)&&pMmSUhmeiLau`i zH+RUXb~5(1xx&6%NYF|xAP%t{C-#zohAVEPL+9N&Z#;+0|ertHKx}S=T6mnfRS*qC`20|BisgKZNDhiddJ#4Wm`9V3a0h$Yrew|cS z_^T8yBBDmH3$)A+vgZvkZh|Y@=T3D65O>)*2eF|B!q+iC-6k+|5~6l*ZsbW=n>LX9~Si^M1v8x}Jf@i7Y<#fWJu1h@Ra?=+Z<*NH zxiGgV$+PO*$Pj5gvRrMZPQpv15?cra-M z{EKaduOX7CAYuj|0(~^lcf^M+S3)I+2{oq)U5=fLavL}b(yO5q50Cj_@2nA=C6H@G zq>CKtfb;`eA0va}8oCblD50;aT1LRPXO?pp%7VOv*7iL)gS-u8{1sA|D(6+5Dj zs8Y~P4A(TR;Z!f>Iv*!-n`Xw66~Qym1*u-gwWY<2Bsr(Ljhk^pnxDF7W#TO5s8CQ;B~II^wj?KD#5jL>Z%rI#z44tfVrx_{XMARi^djh3|h z#szya+FmP8K=gV`l^~{tQ?1l{Ja?oyQvk?8%;}N##evR)f>XVd^T%?*RF6&knGH5K zyTy7QQ9u+C;@k*o_Ff@t{T46nTIul}$iCF5;jH9bvT=cStbSRVc!p}T@}#q$y}9RE z7cfx>#!t#xIhqsG0+neTRi~P0BKHEp#mxjJJAh zhn&#|Q`HLQ(AH$SB?sx|ZI~=5JyM_n=JOBG)#4z7kPQ^JWV5;HT+)9q^`0w{Sh^sYS zKJc&1{52gft_(+OUT+xfO9Pvb$I*^b(jX?xzBR&JRS+hDu_sZm$UdrzV06(-7n)`Z zJ&K-Qs#8;wnM&IO{bM<-C&h!1*g+3;$-iM}?|EV!2=w5J-cIXwlm4pKlK zlxCmOpXqF?gjZ6HsSfpX8=1p08KnyV2FsWK)phwy|rM<7@&igUQL-0m*fQrTRS&LvtC# zY;t5p;!-dt1Z|Hhy@qZW=8lv$2U8HTrnsQiFh8IuCRKs8O9bbaFljgr*u8c2SJ1rc z+%TkT9)kxK|M5z5+3HZ(n0De%95JR+x=kGGc6Vidx>nKGEY)L7C3M?{d%CO8W|D#G z*mM{)qOM+{EnXK0+deMnYs2+vGC554%hMNXhJnlRDe0B(6=~w+%Hk^ z1d9zcO`hn$u5NYe1^r~wu(9&91{c@5vj$64< zasHaVtD*Pj!`g_ECc`arVL;O^M6g5B9YOyy+hjwaFjh%T<3M#?V43TJvIrG6TKnpK2{{MrY!(^o zf)LD?*3|~bMWpwhND~WZRRJ;+`MA%f15N4ROiS`p`fpY3Gs*NoWz3h)5#>7mr+S74l)l`A5pLnqfib)kj?Ln!kw&x^HQ`v$KAv`#hsn@h3=0_g6on-;|Px;CB3V zYtVNkV#z7_(WN9|QS|l=Esnh~N)45rxiVnPA1>Q>eF)x`HBIB5VaSG-2DFRS>13WH z6NW2^_DJX-D#pc?^MJ>0$zE8f&9J@gNVJluImMOvQi6 z2<8+Ch7tS4(6g|U^bRyD0$gko=hoNshAPW!z=bA1FoRZ|jHp{@^hs3fVgcU<;JFCO_@jVY#JD#Ma8t z>LR^9N+(tP>~M~y^jm|yd8|~$=avIFUC0VmFBwn7S(Ux@R8S;+J;l$nmLgFS8x;OJ|$seddC@yCW;(`AD|vK|1cNNOZO~ z^nogSWA5@n z7rh%<>zZOlPGDwxRC;<8mpR0=8$8!hl%&u^7x!_+A~B{tFt8nSiQ;~Dw83ot_B(q_ z?qd|N{q$%@2cY)IKXaeiu28bD?8O_hF*!Y!lGwm{KnXI|~Yp-~Q;hnd&KLf3n+aF*|R9 zU@l%Y#K7l*AfTik1XN2D-2(%lP6z&lKUnXW?4EQ`w`)Yl#6*MJ;ci{_*5n44F~(60 z_O55Wt%nYJ8}jmgAmF7tym5oui#_M`Hn#0c8w}zcIJxma@yHVXwo@)wOE3;;rx3xR zbrmfqTXN%dL9ca#BJVLA;42h5UE%jbkyGbgA+rHCdBK}-dk{4!#MouepR*|3ntsw% z){pi-O&V6DN@6En{Fci-X-d}RiGW6y1p+laS{PJY@9f6GZrp`L=;j6FEVepVZ{~gd zI#z?ODd%P34k{K;GT-we`Cax9qtXG`+$Tej?=&0HUIDQMtAlEVCJzTme`4pVN2%G% znr5qqk~ySU7-|o#*6o3H#*`aBke!hRCw)_r)u22tWUf%gUmNK+Mj~i!TJnU&_2KNU;EYkR zoQ}?GyXl?GN@iS_^_>Qcp6T9uIg06y>I%|N=%q`SxMP+S1@qE3W zA0K8#`(8il{pLC~%XgFZQ2MCU-sUwnTM~R7)eAY6EOFETls;0yWs;o(&}Tz+#Q!?5;bP_?s1Lf-R?ywKljbi_bFs>^Sd!yg85e6LIoLEf)7H?4 zUw#dS9euYNFnAXrcv#wtmv143zLX%l>Z~8L2D9QnxVYx%S;rXC6pnr3^{PMKjhMRI z{&b&>R&BfTzYHa9k>h(y9|`~$UaBXd5k(;cXUZQUskzA5dVDtjLrf#@{;0a1PnyCw zHY?i9b$!6U*aqj3179VN=K@A9+!*Ape zCI~r|U*kWTS{mAvGXx!Qd@c^rZj^v9C(?w?rshTp2x8H+w6wA)_!uA+T|^LEdo@XY zloL`0ljVW-zPQj3a(hhXJ5H}Od7r`;5>}dq>VH@T!&MLaQN1ByeZTnz!{Q^UYai{b z=d`pxT0{L53=h zyS_&uAdI6MP;j|DcHDCeU>g%4 zNKVd}#T=}}w%N{ylPDHitPP}xND?2ztySJMA zp|B)YwFW`3_}VCcAtsBEwQ%u3{@hdQ{Frvbp7xka#f*GjpBhmvTTrts`)~y=vXqp# z-Er?S2l zIo^VO1md9o0%?#`hmYy+jI;D1clY+Q2V4RwcGO7)qoAurP;(RSk#94C2>Q#ETW ztFiI0eG9Ub7THBJW%UB1A$}HX`kQU+v1^wd%g&DJ`*dKZ3*uNTv~01qau@>HG*&(2BX@=PCzLlyHcn z>=7adLoL5rH)95;VDrTfvY}%m;Nc4>MSCPXW!QC@Z%;#$aIaREqNEC_CST`eT9)Eg zC)NM!M7lkEaTXzbEl)v&HhfLLzX2jfpStfWIa0g1>PqT>Vtmh?fpy{n)bVd&S&oD0 z=w4ShpqZsP*yTj<#lE@aj3U+$qnvsvJOo!5lS+ZDCDtsI2#XP|EiYf|IM*`DYDNB; zC|V((Z`YsoD`k;GoKU5A!^z3yvV?g;m$T|0^%uV}{P$gOZ`l{- zE$goSXDHzRkDZ*rDkJO5k~aNhJ8L`)1bgaW;3FGgQ>B@PrLCkyC&EOlCaR>uv3v#6s~mI=*iZ-`=B%Z4N=NvMf zgtP&)hPFT3+BkP$ebXD!g@X6l6V_nVy(2-asj3pu#~r1fN*ZZ=v*dRaiZ^<0x@k^u z^e?j6nQ9z{9#Fael#rugvP7K{$zyegdKLqV-AMZ3pR^o#sa<>r`a_fHMXNQGg1*Gl>?}sBR9`jK>HI<8T-Z3IzaQDb~ysHwAN&g4J2NtmVClqqWrDUJB%epqFwk ztz{}t-Bw2ZG${mXcZGoZay=Xp{&}1kSZcQ@xrC<>b8%>C3gAk=^e}J@JAT@#P!jTt z)?2^-*LvF};tFB#?+hbK^KOQaJH7_-4Ycmb}%Kr z8~QAdB3TuCwI?=LAllkpH@NjmV9I6I_5Fz!=kO2CImj=B)9E+d+3p)1QG1BRk@VmZ z_NB6VZZRCMNI+BXC+HPrgt(?S@?B3}JcJSKjjq_dCrm)=nYEdSfNfAe_2ENmKh&01 zQ~=Vs2?@wjQDjpm5Z)UuS@t5SRI0+RX*F_4)RJ2MCE=tHc1#i!tgBm;>UX^JWhE&H zCZO)S?;fM5*fV2-jjyFSXfV8nbg3lhE=1t~%$VtHFl0GhCq%Osbn{~JT>*|LM}PtAOuhlu&({~{zU9cqpPAdvH*$`~OcCPDSv^H3q_*h2Xbfc8JFp_MIEgrt7i;Zk5v_<0Nis2EkW`T?unfNs zG#Fct`vX^xH9D;7I{J2jkdVrz@^pZ)hl3!gsg2D1JT}$))@S7=_wNhP9Gj*Gaq>ka z0j+MU)!hm-oRb?|W8?W3M?cM4V*;;j+}PS+Ff1f@IJ;<}r0ApfS1u1s>5l2rY$6ag z9h!4so&a;7Ep=v~Cn8Ycze0|>cMp61uTTpN4|A)Py?6RW!JgPs>i!MlAVNGY>&rfTr!Q~Azv)k3{6>eX^BB{NY%)I?}= zfIWKv)BBULrR}R)OZ@7j=7%h6gZFuS(#S$yfcBK(sXR>e`uO1W(Ml>M^)6Shx<@(tnpOLfBkm^|9s=N z1%HQ?2*^fTzAdP~7i?>M+0at;k3It!ywv~gzMH~-s#+R=FZfIyleZ3w>xD!gAWB%Q zQQ_112F5hjby#TRe5Q9|cbP=3I+Jtk;?OIi6XkU#-I=OOi3V z=W2<*DNi_m%qQ^KY}<~+ZjP0nv3}Kr5KF@evoaeX7k$E9nR!&AGYaVN_$>^6D;&e%- zz0R=8436W$a;yp~uUMIlJG33NO!VVXAFBdH{t6o5nDTn#uRb!>#4*`Kz58Kia&nd< zW$>?$wVdMt0UHA7m?F&iK9j(dqKFJAhp91evtb9?QI!M`{6#j`JVLI~Wz!`pA98_Y zchR=DqHJ{^%AL;WkeFx^0LIR7BY|Y%mYvMaUM~rEZ?=G7sAP&NNY>H^$y|~3?7Py? zy1MjmQCw-M+a1?NToJ4Xpq!SeBK%3fjo;edj?9I0V^%&4^D;w5hWX--2ITBx!=R>g zb3zuwB1Xhno|W*IMFOQNW~yy*unlDwRDNULp{r|YySq={r?&s(<MFX%Erl^<# zLAgk4ITePfIWSCy%->A^#Q`s0Y`UpY9<+Qq`1h$*D7|sA3W|>x$BSDx9KYDp)xGNb zTerNe)&{S7)&^^<*Hs6s`mnm3aTWbCh65L#hYqS^l8`LkET0Qz_v)~JH}lAti9+a| zW&8f1GhWL(h$rsGFlQ6DlCyEXgLIzM6I9daX9y>rS=Et=-(+O3>Il&tkIw8^bvg<5 z{w$;Gn4Bnw&dA<`@|GT|9HLrjG%NKy(#fG(G@I72%3bZu6I-mWS7`-v&KuyHtH>Jis++LkX@>YyQx(rix!5+242Har zo5L}+urrvWIY)8%5!$j$kr=(dGVsH_U@ZoTb-SK?4KZZXz>Cu6%R!f$rQN7v zaGEUWE*mhy4}a+&5D`~d88HF=ztFhmvdGxp4JCstbaQM6E=Yoj8Sz?6!%oVaSy;rW z?|dTU&oXBt$}Bv>WuSu^6JHrn{7GK!W%b;6+RsnZQ+w_dv*vnk|Adcb#IsN8)1Uqv zPg~6Hub0vIpPK!?l(C9UX06Z%3j>cf7tN~eQgGPkEQ~8(@IZrJU5av!5fZCyTTu1t_e>!1 z$VhL}hQB1_y`g9iDeAv)&K?6dj74VgLJfO3VcY~ReH`hBXBEwyu9eL^o#45|@Y1Mc zqM}N}iD!RmPOcL*Yw_b${b|qmFRrN$!sfHMrm|q*pX%3ki+L^ht+ju<^*tm^+^z2N zmi5jriSYtzqO8xTcyCRu>P$!-|MtQP+*5KtEh2 znB<=Xs)#BuiJJ&zfGpF;{k$VPB?x4~Zbbq11@kcgeIe~QRk{_D3(5#6?NLTI6`0zJ z*eyZ0a!msi>sj&$7G>S-2)lq85U_liI2H&r@hJy_4s7p3n>oXOX$ga>@;i~2xd+S> za&vbT1I$dnP8lmR%)vj7IuR{f{L7?IxsUZm<9x%;^Nl&>#NF_MZ+8mXtmFt0sxrv) zaJDYj(RbpOZC57LfGdcbEho$KTo&LOpos2vMgF!qA#raKnSu-go6Oj}OhuG_0@HC_ zh3lE~r{Xo8+1PB(z|yc)%oSyJIx_kyRlyA9JMzliHPH~vj~blQeTzdb=!_rj~+<7A94Y z`sxtb2#nufakRp@dO1#mGpv!DcT6;=(8;K)6J{+7LYYw){ih0_b!&~;*-8ejRn$sj zpvc7Y|3ivlc5mny&vH4aPckIKZqyn!x$Fn4=~$+)@uMSa!B=c}^-AU zI2u-I>c9Rh9bQ_&ws4ygzhpc4Gh@)_CEWv#Zh*%c>yw>?c}^?LRq&!B*R1^-%+++E zsdFXXRAkGGtqBY(NrwTyOKcwTEZhN%dm1JTgQn3QWgu&k;Oz#W=((<0@|G$&!7gqb{A7nTf{zGj~Upf(Y z0e>E;0{;p2&Bth8Fth&y;H{S!yzjjS9$)GcCZX%W|9=p!5VZiDgE0nl1DOe%?g@Wj z0XM({U_{;vW>;(;{K_WAJC|;pTYxqVqjmNWu~|+ zUoC|Zep>Mls}f)x2MC4iqI>Yk$_>fVwHnqX5@}OH5^a>hkCT)oQ!M3>Bz-BDT)9K} zh&LHjAjM_{6-1o*M1{k!6{rXx+l7jRXIJ7F|BYVQV+;LbMVtVjG7(UsgsNmvhER4= zmd0G99I8q#<zdj#?-1PwaQvFE7k$KlL_@^iv-*4Wq-cJ>g$=hp!h~*_a}zkfKu!c6}*# zZ1AwE8HC`=iWL8b8FwBYYi%f;1GX5_(cYvy;qlaaqE!DG-cm0Ny(mXmEyV^riBiFE zizz5itf|)IOR6+=+5ePJNIme9vcNI9g`aHfBzuJ-B%D+e&6Q^VP;aclr`jer)nX*e z{!$u;odTOY+Y(i!I21vcw8;j+V&7b~T?ZVImDTbwUB^R~7%y%P7MoZHB`UF*VrpfF zWruq2;6&DCavq5*cJBeJ;vdDna0jo6m-HGpRB@+l<@>$tt}fE~;sH&-JXliNe=<4Yk7#bOyn3|beSgzKa?QVZKp3ax+?f!Va-kP5qw02fO zyJo1pXYu>MWYq!JZe`epMPyH)drt{A>@ZNBDB2Bl_LZ`|ZD>Rg(M`c*Yx! z##GK2EY2Pna{$G>#-o>%FxSH>98jn8TAdWkqmQ7~EucdHw~ZN`!bRY42LwJvngDXP0x-LKQ?dHOaYkg6MwBmEWgIsdwrQAA$Gal@}f#QJqj4TC5#&oBb z#!I&#^AN=fRp6;`GZ#=eO>LZ=;wHaC<`Ds2= zKtWgT1-_AKCI12BZ7NVuU17+0SX*6$$BY;A;!owlRI6eip2aXY52cdiSZkSO`9ojb zrqar*!_)FE_hgm)esftW_EO=DW0a;FgV|Uuf+~JLT~R8G=zO$!G847Q%XEi=Gf-T@ zCd?H|Mvd5p;PIu(LxFL_O=L{hznz<(IaKJj#IyFNr+wK(H0%61B1wL5s+l6wFi%W2&M0a#=L3yLsEQ(e| zakPwlE5nXsRj`;%awzjK8$DC01KuA{4Gz576j9ZS1A$_f`WGN!PW`oCeJjr!rq?7H zZ*C!G2C;;p>foGd7YtJE)I72CD{1c`Z+hzk-S4;K%FQB*F|4_WYTb{UQUZ^i<<7$i zH6L_oTM*Kl8t&|ZP$xI)Oa-$~-u@fq`Vr|Wg4*fMRdobm!e4onyfyr^*=R}cw=nAr z5%3z)?PNBdm`ouFdNPEB_Y7@|Clfss<{t(p3q#nXgb&LZz`tLor@~Bmb9h5L8U*L{ WHdrvLEDIs3sRnCWlnnbyiU9zl#y(5{ diff --git a/plugins/fullcalendar-bootstrap/main.esm.js b/plugins/fullcalendar-bootstrap/main.esm.js index 951ec2a59..7fd26fe36 100644 --- a/plugins/fullcalendar-bootstrap/main.esm.js +++ b/plugins/fullcalendar-bootstrap/main.esm.js @@ -1,5 +1,5 @@ /*! -FullCalendar Bootstrap Plugin v4.3.0 +FullCalendar Bootstrap Plugin v4.4.0 Docs & License: https://fullcalendar.io/ (c) 2019 Adam Shaw */ diff --git a/plugins/fullcalendar-bootstrap/main.js b/plugins/fullcalendar-bootstrap/main.js index dabccf1e6..5f966890c 100644 --- a/plugins/fullcalendar-bootstrap/main.js +++ b/plugins/fullcalendar-bootstrap/main.js @@ -1,5 +1,5 @@ /*! -FullCalendar Bootstrap Plugin v4.3.0 +FullCalendar Bootstrap Plugin v4.4.0 Docs & License: https://fullcalendar.io/ (c) 2019 Adam Shaw */ diff --git a/plugins/fullcalendar-bootstrap/main.min.js b/plugins/fullcalendar-bootstrap/main.min.js index 107ed48b1..b875bee48 100644 --- a/plugins/fullcalendar-bootstrap/main.min.js +++ b/plugins/fullcalendar-bootstrap/main.min.js @@ -1,5 +1,5 @@ /*! -FullCalendar Bootstrap Plugin v4.3.0 +FullCalendar Bootstrap Plugin v4.4.0 Docs & License: https://fullcalendar.io/ (c) 2019 Adam Shaw */ diff --git a/plugins/ion-rangeslider/css/ion.rangeSlider.css b/plugins/ion-rangeslider/css/ion.rangeSlider.css index 17e1684fb..93c0da807 100644 --- a/plugins/ion-rangeslider/css/ion.rangeSlider.css +++ b/plugins/ion-rangeslider/css/ion.rangeSlider.css @@ -1,7 +1,7 @@ /** -Ion.RangeSlider, 2.3.0 -© Denis Ineshin, 2010 - 2018, IonDen.com -Build date: 2018-12-11 23:23:51 +Ion.RangeSlider, 2.3.1 +© Denis Ineshin, 2010 - 2019, IonDen.com +Build date: 2019-12-19 16:51:02 */ .irs { position: relative; diff --git a/plugins/ion-rangeslider/css/ion.rangeSlider.min.css b/plugins/ion-rangeslider/css/ion.rangeSlider.min.css index 8558320de..8b34de170 100644 --- a/plugins/ion-rangeslider/css/ion.rangeSlider.min.css +++ b/plugins/ion-rangeslider/css/ion.rangeSlider.min.css @@ -1 +1 @@ -/*!Ion.RangeSlider, 2.3.0, © Denis Ineshin, 2010 - 2018, IonDen.com, Build date: 2018-12-11 23:23:51*/.irs{position:relative;display:block;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:12px;font-family:Arial,sans-serif}.irs-line{position:relative;display:block;overflow:hidden;outline:none !important}.irs-bar{position:absolute;display:block;left:0;width:0}.irs-shadow{position:absolute;display:none;left:0;width:0}.irs-handle{position:absolute;display:block;box-sizing:border-box;cursor:default;z-index:1}.irs-handle.type_last{z-index:2}.irs-min,.irs-max{position:absolute;display:block;cursor:default}.irs-min{left:0}.irs-max{right:0}.irs-from,.irs-to,.irs-single{position:absolute;display:block;top:0;left:0;cursor:default;white-space:nowrap}.irs-grid{position:absolute;display:none;bottom:0;left:0;width:100%;height:20px}.irs-with-grid .irs-grid{display:block}.irs-grid-pol{position:absolute;top:0;left:0;width:1px;height:8px;background:#000}.irs-grid-pol.small{height:4px}.irs-grid-text{position:absolute;bottom:0;left:0;white-space:nowrap;text-align:center;font-size:9px;line-height:9px;padding:0 3px;color:#000}.irs-disable-mask{position:absolute;display:block;top:0;left:-1%;width:102%;height:100%;cursor:default;background:rgba(0,0,0,0);z-index:2}.lt-ie9 .irs-disable-mask{background:#000;filter:alpha(opacity=0);cursor:not-allowed}.irs-disabled{opacity:.4}.irs-hidden-input{position:absolute !important;display:block !important;top:0 !important;left:0 !important;width:0 !important;height:0 !important;font-size:0 !important;line-height:0 !important;padding:0 !important;margin:0 !important;overflow:hidden;outline:none !important;z-index:-9999 !important;background:none !important;border-style:solid !important;border-color:transparent !important}.irs--flat{height:40px}.irs--flat.irs-with-grid{height:60px}.irs--flat .irs-line{top:25px;height:12px;background-color:#e1e4e9;border-radius:4px}.irs--flat .irs-bar{top:25px;height:12px;background-color:#ed5565}.irs--flat .irs-bar--single{border-radius:4px 0 0 4px}.irs--flat .irs-shadow{height:1px;bottom:16px;background-color:#e1e4e9}.irs--flat .irs-handle{top:22px;width:16px;height:18px;background-color:transparent}.irs--flat .irs-handle>i:first-child{position:absolute;display:block;top:0;left:50%;width:2px;height:100%;margin-left:-1px;background-color:#da4453}.irs--flat .irs-handle.state_hover>i:first-child,.irs--flat .irs-handle:hover>i:first-child{background-color:#a43540}.irs--flat .irs-min,.irs--flat .irs-max{top:0;padding:1px 3px;color:#999;font-size:10px;line-height:1.333;text-shadow:none;background-color:#e1e4e9;border-radius:4px}.irs--flat .irs-from,.irs--flat .irs-to,.irs--flat .irs-single{color:white;font-size:10px;line-height:1.333;text-shadow:none;padding:1px 5px;background-color:#ed5565;border-radius:4px}.irs--flat .irs-from:before,.irs--flat .irs-to:before,.irs--flat .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#ed5565}.irs--flat .irs-grid-pol{background-color:#e1e4e9}.irs--flat .irs-grid-text{color:#999}.irs--big{height:55px}.irs--big.irs-with-grid{height:70px}.irs--big .irs-line{top:33px;height:12px;background-color:white;background:linear-gradient(to bottom, #ddd -50%, white 150%);border:1px solid #ccc;border-radius:12px}.irs--big .irs-bar{top:33px;height:12px;background-color:#92bce0;border:1px solid #428bca;background:linear-gradient(to bottom, #ffffff 0%, #428bca 30%, #b9d4ec 100%);box-shadow:inset 0 0 1px 1px rgba(255,255,255,0.5)}.irs--big .irs-bar--single{border-radius:12px 0 0 12px}.irs--big .irs-shadow{height:1px;bottom:16px;background-color:rgba(66,139,202,0.5)}.irs--big .irs-handle{top:25px;width:30px;height:30px;border:1px solid rgba(0,0,0,0.3);background-color:#cbcfd5;background:linear-gradient(to bottom, white 0%, #B4B9BE 30%, white 100%);box-shadow:1px 1px 2px rgba(0,0,0,0.2),inset 0 0 3px 1px white;border-radius:30px}.irs--big .irs-handle.state_hover,.irs--big .irs-handle:hover{border-color:rgba(0,0,0,0.45);background-color:#939ba7;background:linear-gradient(to bottom, white 0%, #919BA5 30%, white 100%)}.irs--big .irs-min,.irs--big .irs-max{top:0;padding:1px 5px;color:white;text-shadow:none;background-color:#9f9f9f;border-radius:3px}.irs--big .irs-from,.irs--big .irs-to,.irs--big .irs-single{color:white;text-shadow:none;padding:1px 5px;background-color:#428bca;background:linear-gradient(to bottom, #428bca 0%, #3071a9 100%);border-radius:3px}.irs--big .irs-grid-pol{background-color:#428bca}.irs--big .irs-grid-text{color:#428bca}.irs--modern{height:55px}.irs--modern.irs-with-grid{height:55px}.irs--modern .irs-line{top:25px;height:5px;background-color:#d1d6e0;background:linear-gradient(to bottom, #e0e4ea 0%, #d1d6e0 100%);border:1px solid #a3adc1;border-bottom-width:0;border-radius:5px}.irs--modern .irs-bar{top:25px;height:5px;background:#20b426;background:linear-gradient(to bottom, #20b426 0%, #18891d 100%)}.irs--modern .irs-bar--single{border-radius:5px 0 0 5px}.irs--modern .irs-shadow{height:1px;bottom:21px;background-color:rgba(209,214,224,0.5)}.irs--modern .irs-handle{top:37px;width:12px;height:13px;border:1px solid #a3adc1;border-top-width:0;box-shadow:1px 1px 1px rgba(0,0,0,0.1);border-radius:0 0 3px 3px}.irs--modern .irs-handle>i:nth-child(1){position:absolute;display:block;top:-4px;left:1px;width:6px;height:6px;border:1px solid #a3adc1;background:white;transform:rotate(45deg)}.irs--modern .irs-handle>i:nth-child(2){position:absolute;display:block;box-sizing:border-box;top:0;left:0;width:10px;height:12px;background:#e9e6e6;background:linear-gradient(to bottom, white 0%, #e9e6e6 100%);border-radius:0 0 3px 3px}.irs--modern .irs-handle>i:nth-child(3){position:absolute;display:block;box-sizing:border-box;top:3px;left:3px;width:4px;height:5px;border-left:1px solid #a3adc1;border-right:1px solid #a3adc1}.irs--modern .irs-handle.state_hover,.irs--modern .irs-handle:hover{border-color:#7685a2;background:#c3c7cd;background:linear-gradient(to bottom, #ffffff 0%, #919ba5 30%, #ffffff 100%)}.irs--modern .irs-handle.state_hover>i:nth-child(1),.irs--modern .irs-handle:hover>i:nth-child(1){border-color:#7685a2}.irs--modern .irs-handle.state_hover>i:nth-child(3),.irs--modern .irs-handle:hover>i:nth-child(3){border-color:#48536a}.irs--modern .irs-min,.irs--modern .irs-max{top:0;font-size:10px;line-height:1.333;text-shadow:none;padding:1px 5px;color:white;background-color:#d1d6e0;border-radius:5px}.irs--modern .irs-from,.irs--modern .irs-to,.irs--modern .irs-single{font-size:10px;line-height:1.333;text-shadow:none;padding:1px 5px;background-color:#20b426;color:white;border-radius:5px}.irs--modern .irs-from:before,.irs--modern .irs-to:before,.irs--modern .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#20b426}.irs--modern .irs-grid{height:25px}.irs--modern .irs-grid-pol{background-color:#dedede}.irs--modern .irs-grid-text{color:silver;font-size:13px}.irs--sharp{height:50px;font-size:12px;line-height:1}.irs--sharp.irs-with-grid{height:57px}.irs--sharp .irs-line{top:30px;height:2px;background-color:black;border-radius:2px}.irs--sharp .irs-bar{top:30px;height:2px;background-color:#ee22fa}.irs--sharp .irs-bar--single{border-radius:2px 0 0 2px}.irs--sharp .irs-shadow{height:1px;bottom:21px;background-color:rgba(0,0,0,0.5)}.irs--sharp .irs-handle{top:25px;width:10px;height:10px;background-color:#a804b2}.irs--sharp .irs-handle>i:first-child{position:absolute;display:block;top:100%;left:0;width:0;height:0;border:5px solid transparent;border-top-color:#a804b2}.irs--sharp .irs-handle.state_hover,.irs--sharp .irs-handle:hover{background-color:black}.irs--sharp .irs-handle.state_hover>i:first-child,.irs--sharp .irs-handle:hover>i:first-child{border-top-color:black}.irs--sharp .irs-min,.irs--sharp .irs-max{color:white;font-size:14px;line-height:1;top:0;padding:3px 4px;opacity:.4;background-color:#a804b2;border-radius:2px}.irs--sharp .irs-from,.irs--sharp .irs-to,.irs--sharp .irs-single{font-size:14px;line-height:1;text-shadow:none;padding:3px 4px;background-color:#a804b2;color:white;border-radius:2px}.irs--sharp .irs-from:before,.irs--sharp .irs-to:before,.irs--sharp .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#a804b2}.irs--sharp .irs-grid{height:25px}.irs--sharp .irs-grid-pol{background-color:#dedede}.irs--sharp .irs-grid-text{color:silver;font-size:13px}.irs--round{height:50px}.irs--round.irs-with-grid{height:65px}.irs--round .irs-line{top:36px;height:4px;background-color:#dee4ec;border-radius:4px}.irs--round .irs-bar{top:36px;height:4px;background-color:#006cfa}.irs--round .irs-bar--single{border-radius:4px 0 0 4px}.irs--round .irs-shadow{height:4px;bottom:21px;background-color:rgba(222,228,236,0.5)}.irs--round .irs-handle{top:26px;width:24px;height:24px;border:4px solid #006cfa;background-color:white;border-radius:24px;box-shadow:0 1px 3px rgba(0,0,255,0.3)}.irs--round .irs-handle.state_hover,.irs--round .irs-handle:hover{background-color:#f0f6ff}.irs--round .irs-min,.irs--round .irs-max{color:#333;font-size:14px;line-height:1;top:0;padding:3px 5px;background-color:rgba(0,0,0,0.1);border-radius:4px}.irs--round .irs-from,.irs--round .irs-to,.irs--round .irs-single{font-size:14px;line-height:1;text-shadow:none;padding:3px 5px;background-color:#006cfa;color:white;border-radius:4px}.irs--round .irs-from:before,.irs--round .irs-to:before,.irs--round .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#006cfa}.irs--round .irs-grid{height:25px}.irs--round .irs-grid-pol{background-color:#dedede}.irs--round .irs-grid-text{color:silver;font-size:13px}.irs--square{height:50px}.irs--square.irs-with-grid{height:60px}.irs--square .irs-line{top:31px;height:4px;background-color:#dedede}.irs--square .irs-bar{top:31px;height:4px;background-color:black}.irs--square .irs-shadow{height:2px;bottom:21px;background-color:#dedede}.irs--square .irs-handle{top:25px;width:16px;height:16px;border:3px solid black;background-color:white;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.irs--square .irs-handle.state_hover,.irs--square .irs-handle:hover{background-color:#f0f6ff}.irs--square .irs-min,.irs--square .irs-max{color:#333;font-size:14px;line-height:1;top:0;padding:3px 5px;background-color:rgba(0,0,0,0.1)}.irs--square .irs-from,.irs--square .irs-to,.irs--square .irs-single{font-size:14px;line-height:1;text-shadow:none;padding:3px 5px;background-color:black;color:white}.irs--square .irs-grid{height:25px}.irs--square .irs-grid-pol{background-color:#dedede}.irs--square .irs-grid-text{color:silver;font-size:11px} \ No newline at end of file +/*!Ion.RangeSlider, 2.3.1, © Denis Ineshin, 2010 - 2019, IonDen.com, Build date: 2019-12-19 16:51:02*/.irs{position:relative;display:block;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:12px;font-family:Arial,sans-serif}.irs-line{position:relative;display:block;overflow:hidden;outline:none !important}.irs-bar{position:absolute;display:block;left:0;width:0}.irs-shadow{position:absolute;display:none;left:0;width:0}.irs-handle{position:absolute;display:block;box-sizing:border-box;cursor:default;z-index:1}.irs-handle.type_last{z-index:2}.irs-min,.irs-max{position:absolute;display:block;cursor:default}.irs-min{left:0}.irs-max{right:0}.irs-from,.irs-to,.irs-single{position:absolute;display:block;top:0;left:0;cursor:default;white-space:nowrap}.irs-grid{position:absolute;display:none;bottom:0;left:0;width:100%;height:20px}.irs-with-grid .irs-grid{display:block}.irs-grid-pol{position:absolute;top:0;left:0;width:1px;height:8px;background:#000}.irs-grid-pol.small{height:4px}.irs-grid-text{position:absolute;bottom:0;left:0;white-space:nowrap;text-align:center;font-size:9px;line-height:9px;padding:0 3px;color:#000}.irs-disable-mask{position:absolute;display:block;top:0;left:-1%;width:102%;height:100%;cursor:default;background:rgba(0,0,0,0);z-index:2}.lt-ie9 .irs-disable-mask{background:#000;filter:alpha(opacity=0);cursor:not-allowed}.irs-disabled{opacity:.4}.irs-hidden-input{position:absolute !important;display:block !important;top:0 !important;left:0 !important;width:0 !important;height:0 !important;font-size:0 !important;line-height:0 !important;padding:0 !important;margin:0 !important;overflow:hidden;outline:none !important;z-index:-9999 !important;background:none !important;border-style:solid !important;border-color:transparent !important}.irs--flat{height:40px}.irs--flat.irs-with-grid{height:60px}.irs--flat .irs-line{top:25px;height:12px;background-color:#e1e4e9;border-radius:4px}.irs--flat .irs-bar{top:25px;height:12px;background-color:#ed5565}.irs--flat .irs-bar--single{border-radius:4px 0 0 4px}.irs--flat .irs-shadow{height:1px;bottom:16px;background-color:#e1e4e9}.irs--flat .irs-handle{top:22px;width:16px;height:18px;background-color:transparent}.irs--flat .irs-handle>i:first-child{position:absolute;display:block;top:0;left:50%;width:2px;height:100%;margin-left:-1px;background-color:#da4453}.irs--flat .irs-handle.state_hover>i:first-child,.irs--flat .irs-handle:hover>i:first-child{background-color:#a43540}.irs--flat .irs-min,.irs--flat .irs-max{top:0;padding:1px 3px;color:#999;font-size:10px;line-height:1.333;text-shadow:none;background-color:#e1e4e9;border-radius:4px}.irs--flat .irs-from,.irs--flat .irs-to,.irs--flat .irs-single{color:white;font-size:10px;line-height:1.333;text-shadow:none;padding:1px 5px;background-color:#ed5565;border-radius:4px}.irs--flat .irs-from:before,.irs--flat .irs-to:before,.irs--flat .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#ed5565}.irs--flat .irs-grid-pol{background-color:#e1e4e9}.irs--flat .irs-grid-text{color:#999}.irs--big{height:55px}.irs--big.irs-with-grid{height:70px}.irs--big .irs-line{top:33px;height:12px;background-color:white;background:linear-gradient(to bottom, #ddd -50%, white 150%);border:1px solid #ccc;border-radius:12px}.irs--big .irs-bar{top:33px;height:12px;background-color:#92bce0;border:1px solid #428bca;background:linear-gradient(to bottom, #ffffff 0%, #428bca 30%, #b9d4ec 100%);box-shadow:inset 0 0 1px 1px rgba(255,255,255,0.5)}.irs--big .irs-bar--single{border-radius:12px 0 0 12px}.irs--big .irs-shadow{height:1px;bottom:16px;background-color:rgba(66,139,202,0.5)}.irs--big .irs-handle{top:25px;width:30px;height:30px;border:1px solid rgba(0,0,0,0.3);background-color:#cbcfd5;background:linear-gradient(to bottom, white 0%, #B4B9BE 30%, white 100%);box-shadow:1px 1px 2px rgba(0,0,0,0.2),inset 0 0 3px 1px white;border-radius:30px}.irs--big .irs-handle.state_hover,.irs--big .irs-handle:hover{border-color:rgba(0,0,0,0.45);background-color:#939ba7;background:linear-gradient(to bottom, white 0%, #919BA5 30%, white 100%)}.irs--big .irs-min,.irs--big .irs-max{top:0;padding:1px 5px;color:white;text-shadow:none;background-color:#9f9f9f;border-radius:3px}.irs--big .irs-from,.irs--big .irs-to,.irs--big .irs-single{color:white;text-shadow:none;padding:1px 5px;background-color:#428bca;background:linear-gradient(to bottom, #428bca 0%, #3071a9 100%);border-radius:3px}.irs--big .irs-grid-pol{background-color:#428bca}.irs--big .irs-grid-text{color:#428bca}.irs--modern{height:55px}.irs--modern.irs-with-grid{height:55px}.irs--modern .irs-line{top:25px;height:5px;background-color:#d1d6e0;background:linear-gradient(to bottom, #e0e4ea 0%, #d1d6e0 100%);border:1px solid #a3adc1;border-bottom-width:0;border-radius:5px}.irs--modern .irs-bar{top:25px;height:5px;background:#20b426;background:linear-gradient(to bottom, #20b426 0%, #18891d 100%)}.irs--modern .irs-bar--single{border-radius:5px 0 0 5px}.irs--modern .irs-shadow{height:1px;bottom:21px;background-color:rgba(209,214,224,0.5)}.irs--modern .irs-handle{top:37px;width:12px;height:13px;border:1px solid #a3adc1;border-top-width:0;box-shadow:1px 1px 1px rgba(0,0,0,0.1);border-radius:0 0 3px 3px}.irs--modern .irs-handle>i:nth-child(1){position:absolute;display:block;top:-4px;left:1px;width:6px;height:6px;border:1px solid #a3adc1;background:white;transform:rotate(45deg)}.irs--modern .irs-handle>i:nth-child(2){position:absolute;display:block;box-sizing:border-box;top:0;left:0;width:10px;height:12px;background:#e9e6e6;background:linear-gradient(to bottom, white 0%, #e9e6e6 100%);border-radius:0 0 3px 3px}.irs--modern .irs-handle>i:nth-child(3){position:absolute;display:block;box-sizing:border-box;top:3px;left:3px;width:4px;height:5px;border-left:1px solid #a3adc1;border-right:1px solid #a3adc1}.irs--modern .irs-handle.state_hover,.irs--modern .irs-handle:hover{border-color:#7685a2;background:#c3c7cd;background:linear-gradient(to bottom, #ffffff 0%, #919ba5 30%, #ffffff 100%)}.irs--modern .irs-handle.state_hover>i:nth-child(1),.irs--modern .irs-handle:hover>i:nth-child(1){border-color:#7685a2}.irs--modern .irs-handle.state_hover>i:nth-child(3),.irs--modern .irs-handle:hover>i:nth-child(3){border-color:#48536a}.irs--modern .irs-min,.irs--modern .irs-max{top:0;font-size:10px;line-height:1.333;text-shadow:none;padding:1px 5px;color:white;background-color:#d1d6e0;border-radius:5px}.irs--modern .irs-from,.irs--modern .irs-to,.irs--modern .irs-single{font-size:10px;line-height:1.333;text-shadow:none;padding:1px 5px;background-color:#20b426;color:white;border-radius:5px}.irs--modern .irs-from:before,.irs--modern .irs-to:before,.irs--modern .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#20b426}.irs--modern .irs-grid{height:25px}.irs--modern .irs-grid-pol{background-color:#dedede}.irs--modern .irs-grid-text{color:silver;font-size:13px}.irs--sharp{height:50px;font-size:12px;line-height:1}.irs--sharp.irs-with-grid{height:57px}.irs--sharp .irs-line{top:30px;height:2px;background-color:black;border-radius:2px}.irs--sharp .irs-bar{top:30px;height:2px;background-color:#ee22fa}.irs--sharp .irs-bar--single{border-radius:2px 0 0 2px}.irs--sharp .irs-shadow{height:1px;bottom:21px;background-color:rgba(0,0,0,0.5)}.irs--sharp .irs-handle{top:25px;width:10px;height:10px;background-color:#a804b2}.irs--sharp .irs-handle>i:first-child{position:absolute;display:block;top:100%;left:0;width:0;height:0;border:5px solid transparent;border-top-color:#a804b2}.irs--sharp .irs-handle.state_hover,.irs--sharp .irs-handle:hover{background-color:black}.irs--sharp .irs-handle.state_hover>i:first-child,.irs--sharp .irs-handle:hover>i:first-child{border-top-color:black}.irs--sharp .irs-min,.irs--sharp .irs-max{color:white;font-size:14px;line-height:1;top:0;padding:3px 4px;opacity:.4;background-color:#a804b2;border-radius:2px}.irs--sharp .irs-from,.irs--sharp .irs-to,.irs--sharp .irs-single{font-size:14px;line-height:1;text-shadow:none;padding:3px 4px;background-color:#a804b2;color:white;border-radius:2px}.irs--sharp .irs-from:before,.irs--sharp .irs-to:before,.irs--sharp .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#a804b2}.irs--sharp .irs-grid{height:25px}.irs--sharp .irs-grid-pol{background-color:#dedede}.irs--sharp .irs-grid-text{color:silver;font-size:13px}.irs--round{height:50px}.irs--round.irs-with-grid{height:65px}.irs--round .irs-line{top:36px;height:4px;background-color:#dee4ec;border-radius:4px}.irs--round .irs-bar{top:36px;height:4px;background-color:#006cfa}.irs--round .irs-bar--single{border-radius:4px 0 0 4px}.irs--round .irs-shadow{height:4px;bottom:21px;background-color:rgba(222,228,236,0.5)}.irs--round .irs-handle{top:26px;width:24px;height:24px;border:4px solid #006cfa;background-color:white;border-radius:24px;box-shadow:0 1px 3px rgba(0,0,255,0.3)}.irs--round .irs-handle.state_hover,.irs--round .irs-handle:hover{background-color:#f0f6ff}.irs--round .irs-min,.irs--round .irs-max{color:#333;font-size:14px;line-height:1;top:0;padding:3px 5px;background-color:rgba(0,0,0,0.1);border-radius:4px}.irs--round .irs-from,.irs--round .irs-to,.irs--round .irs-single{font-size:14px;line-height:1;text-shadow:none;padding:3px 5px;background-color:#006cfa;color:white;border-radius:4px}.irs--round .irs-from:before,.irs--round .irs-to:before,.irs--round .irs-single:before{position:absolute;display:block;content:"";bottom:-6px;left:50%;width:0;height:0;margin-left:-3px;overflow:hidden;border:3px solid transparent;border-top-color:#006cfa}.irs--round .irs-grid{height:25px}.irs--round .irs-grid-pol{background-color:#dedede}.irs--round .irs-grid-text{color:silver;font-size:13px}.irs--square{height:50px}.irs--square.irs-with-grid{height:60px}.irs--square .irs-line{top:31px;height:4px;background-color:#dedede}.irs--square .irs-bar{top:31px;height:4px;background-color:black}.irs--square .irs-shadow{height:2px;bottom:21px;background-color:#dedede}.irs--square .irs-handle{top:25px;width:16px;height:16px;border:3px solid black;background-color:white;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.irs--square .irs-handle.state_hover,.irs--square .irs-handle:hover{background-color:#f0f6ff}.irs--square .irs-min,.irs--square .irs-max{color:#333;font-size:14px;line-height:1;top:0;padding:3px 5px;background-color:rgba(0,0,0,0.1)}.irs--square .irs-from,.irs--square .irs-to,.irs--square .irs-single{font-size:14px;line-height:1;text-shadow:none;padding:3px 5px;background-color:black;color:white}.irs--square .irs-grid{height:25px}.irs--square .irs-grid-pol{background-color:#dedede}.irs--square .irs-grid-text{color:silver;font-size:11px} \ No newline at end of file diff --git a/plugins/jszip/jszip.js b/plugins/jszip/jszip.js old mode 100755 new mode 100644 diff --git a/plugins/jszip/jszip.min.js b/plugins/jszip/jszip.min.js old mode 100755 new mode 100644 diff --git a/plugins/overlayScrollbars/css/OverlayScrollbars.css b/plugins/overlayScrollbars/css/OverlayScrollbars.css index 9a8ff7107..d4721ca58 100644 --- a/plugins/overlayScrollbars/css/OverlayScrollbars.css +++ b/plugins/overlayScrollbars/css/OverlayScrollbars.css @@ -1,624 +1,624 @@ -/*! - * OverlayScrollbars - * https://github.com/KingSora/OverlayScrollbars - * - * Version: 1.11.0 - * - * Copyright KingSora | Rene Haas. - * https://github.com/KingSora - * - * Released under the MIT license. - * Date: 29.02.2020 - */ - -/* -OVERLAY SCROLLBARS CORE: -*/ - -html.os-html, -html.os-html > .os-host { - display: block; - overflow: hidden; - box-sizing: border-box; - height: 100% !important; - width: 100% !important; - min-width: 100% !important; - min-height: 100% !important; - margin: 0 !important; - position: absolute !important; /* could be position: fixed; but it causes issues on iOS (-webkit-overflow-scrolling: touch) */ -} -html.os-html > .os-host > .os-padding { - position: absolute; /* could be position: fixed; but it causes issues on iOS (-webkit-overflow-scrolling: touch) */ -} -body.os-dragging, -body.os-dragging * { - cursor: default; -} -.os-host, -.os-host-textarea { - position: relative; - overflow: visible !important; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-wrap: nowrap; - flex-wrap: nowrap; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - -ms-flex-line-pack: start; - align-content: flex-start; - -webkit-box-align: start; - -ms-flex-align: start; - -ms-grid-row-align: flex-start; - align-items: flex-start; -} -.os-host-flexbox { - overflow: hidden !important; - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} -.os-host-flexbox > .os-size-auto-observer { - height: inherit !important; -} -.os-host-flexbox > .os-content-glue { - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - -ms-flex-negative: 0; - flex-shrink: 0; -} -.os-host-flexbox > .os-size-auto-observer, -.os-host-flexbox > .os-content-glue { - min-height: 0; - min-width: 0; - -webkit-box-flex: 0; - -ms-flex-positive: 0; - flex-grow: 0; - -ms-flex-negative: 1; - flex-shrink: 1; - -ms-flex-preferred-size: auto; - flex-basis: auto; -} -#os-dummy-scrollbar-size { - position: fixed; - opacity: 0; - -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=0)'; - visibility: hidden; - overflow: scroll; - height: 500px; - width: 500px; -} -#os-dummy-scrollbar-size > div { - width: 200%; - height: 200%; - margin: 10px 0; -} -/* fix restricted measuring */ -#os-dummy-scrollbar-size:before, -#os-dummy-scrollbar-size:after, -.os-content:before, -.os-content:after { - content: ''; - display: table; - width: 0.01px; - height: 0.01px; - line-height: 0; - font-size: 0; - flex-grow: 0; - flex-shrink: 0; - visibility: hidden; -} -#os-dummy-scrollbar-size, -.os-viewport { - -ms-overflow-style: scrollbar !important; -} -.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size, -.os-viewport-native-scrollbars-invisible.os-viewport { - scrollbar-width: none !important; -} -.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size::-webkit-scrollbar, -.os-viewport-native-scrollbars-invisible.os-viewport::-webkit-scrollbar, -.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size::-webkit-scrollbar-corner, -.os-viewport-native-scrollbars-invisible.os-viewport::-webkit-scrollbar-corner { - display: none !important; - width: 0px !important; - height: 0px !important; - visibility: hidden !important; - background: transparent !important; -} -.os-content-glue { - box-sizing: inherit; - max-height: 100%; - max-width: 100%; - width: 100%; - pointer-events: none; -} -.os-padding { - box-sizing: inherit; - direction: inherit; - position: absolute; - overflow: visible; - padding: 0; - margin: 0; - left: 0; - top: 0; - bottom: 0; - right: 0; - width: auto !important; - height: auto !important; - z-index: 1; -} -.os-host-overflow > .os-padding { - overflow: hidden; -} -.os-viewport { - direction: inherit !important; - box-sizing: inherit !important; - resize: none !important; - outline: none !important; - position: absolute; - overflow: hidden; - top: 0; - left: 0; - bottom: 0; - right: 0; - padding: 0; - margin: 0; - -webkit-overflow-scrolling: touch; -} -.os-content-arrange { - position: absolute; - z-index: -1; - min-height: 1px; - min-width: 1px; - pointer-events: none; -} -.os-content { - direction: inherit; - box-sizing: border-box !important; - position: relative; - display: block; - height: 100%; - width: 100%; - height: 100%; - width: 100%; - visibility: visible; -} -.os-content > .os-textarea { - box-sizing: border-box !important; - direction: inherit !important; - background: transparent !important; - outline: 0px none transparent !important; - overflow: hidden !important; - position: absolute !important; - display: block !important; - top: 0 !important; - left: 0 !important; - margin: 0 !important; - border-radius: 0px !important; - float: none !important; - -webkit-filter: none !important; - filter: none !important; - border: none !important; - resize: none !important; - -webkit-transform: none !important; - transform: none !important; - max-width: none !important; - max-height: none !important; - box-shadow: none !important; - -webkit-perspective: none !important; - perspective: none !important; - opacity: 1 !important; - z-index: 1 !important; - clip: auto !important; - vertical-align: baseline !important; - padding: 0px; -} -.os-host-rtl > .os-padding > .os-viewport > .os-content > .os-textarea { - right: 0 !important; -} -.os-content > .os-textarea-cover { - z-index: -1; - pointer-events: none; -} -.os-content > .os-textarea[wrap='off'] { - white-space: pre !important; - margin: 0px !important; -} -.os-text-inherit { - font-family: inherit; - font-size: inherit; - font-weight: inherit; - font-style: inherit; - font-variant: inherit; - text-transform: inherit; - text-decoration: inherit; - text-indent: inherit; - text-align: inherit; - text-shadow: inherit; - text-overflow: inherit; - letter-spacing: inherit; - word-spacing: inherit; - line-height: inherit; - unicode-bidi: inherit; - direction: inherit; - color: inherit; - cursor: text; -} -.os-resize-observer, -.os-resize-observer-host { - box-sizing: inherit; - display: block; - visibility: hidden; - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; - overflow: hidden; - pointer-events: none; - z-index: -1; -} -.os-resize-observer-host { - padding: inherit; - border: inherit; - border-color: transparent; - border-style: solid; - box-sizing: border-box; -} -.os-resize-observer-host > .os-resize-observer { - height: 200%; - width: 200%; - padding: inherit; - border: inherit; - margin: 0px; - display: block; - box-sizing: content-box; -} -.os-resize-observer-host.observed { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; -} -.os-resize-observer-host.observed > .os-resize-observer { - position: relative; - flex-grow: 1; - flex-shrink: 0; - flex-basis: auto; -} -.os-size-auto-observer { - box-sizing: inherit !important; - height: 100%; - width: inherit; - max-width: 1px; - position: relative; - float: left; - max-height: 1px; - overflow: hidden; - z-index: -1; - padding: 0; - margin: 0; - pointer-events: none; - -webkit-box-flex: inherit; - -ms-flex-positive: inherit; - flex-grow: inherit; - -ms-flex-negative: 0; - flex-shrink: 0; - -ms-flex-preferred-size: 0; - flex-basis: 0; -} -.os-size-auto-observer > .os-resize-observer { - width: 1000%; - height: 1000%; - min-height: 1px; - min-width: 1px; -} -.os-resize-observer-item { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - overflow: hidden; - z-index: -1; - opacity: 0; - direction: ltr !important; - -webkit-box-flex: 0 !important; - -ms-flex: none !important; - flex: none !important; -} -.os-resize-observer-item-final { - position: absolute; - left: 0; - top: 0; - -webkit-transition: none !important; - transition: none !important; - -webkit-box-flex: 0 !important; - -ms-flex: none !important; - flex: none !important; -} -.os-resize-observer { - -webkit-animation-duration: 0.001s; - animation-duration: 0.001s; - -webkit-animation-name: os-resize-observer-dummy-animation; - animation-name: os-resize-observer-dummy-animation; -} -object.os-resize-observer { - box-sizing: border-box !important; -} -@-webkit-keyframes os-resize-observer-dummy-animation { - from { - z-index: 0; - } - to { - z-index: -1; - } -} -@keyframes os-resize-observer-dummy-animation { - from { - z-index: 0; - } - to { - z-index: -1; - } -} - -/* -CUSTOM SCROLLBARS AND CORNER CORE: -*/ - -.os-host-transition > .os-scrollbar, -.os-host-transition > .os-scrollbar-corner { - -webkit-transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s; - transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s; -} -html.os-html > .os-host > .os-scrollbar { - position: absolute; /* could be position: fixed; but it causes issues on iOS (-webkit-overflow-scrolling: touch) */ - z-index: 999999; /* highest z-index of the page */ -} -.os-scrollbar, -.os-scrollbar-corner { - position: absolute; - opacity: 1; - -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)'; - z-index: 1; -} -.os-scrollbar-corner { - bottom: 0; - right: 0; -} -.os-scrollbar { - pointer-events: none; -} -.os-scrollbar-track { - pointer-events: auto; - position: relative; - height: 100%; - width: 100%; - padding: 0 !important; - border: none !important; -} -.os-scrollbar-handle { - pointer-events: auto; - position: absolute; - width: 100%; - height: 100%; -} -.os-scrollbar-handle-off, -.os-scrollbar-track-off { - pointer-events: none; -} -.os-scrollbar.os-scrollbar-unusable, -.os-scrollbar.os-scrollbar-unusable * { - pointer-events: none !important; -} -.os-scrollbar.os-scrollbar-unusable .os-scrollbar-handle { - opacity: 0 !important; -} -.os-scrollbar-horizontal { - bottom: 0; - left: 0; -} -.os-scrollbar-vertical { - top: 0; - right: 0; -} -.os-host-rtl > .os-scrollbar-horizontal { - right: 0; -} -.os-host-rtl > .os-scrollbar-vertical { - right: auto; - left: 0; -} -.os-host-rtl > .os-scrollbar-corner { - right: auto; - left: 0; -} -.os-scrollbar-auto-hidden, -.os-padding + .os-scrollbar-corner, -.os-host-resize-disabled.os-host-scrollbar-horizontal-hidden > .os-scrollbar-corner, -.os-host-scrollbar-horizontal-hidden > .os-scrollbar-horizontal, -.os-host-resize-disabled.os-host-scrollbar-vertical-hidden > .os-scrollbar-corner, -.os-host-scrollbar-vertical-hidden > .os-scrollbar-vertical, -.os-scrollbar-horizontal.os-scrollbar-auto-hidden + .os-scrollbar-vertical + .os-scrollbar-corner, -.os-scrollbar-horizontal + .os-scrollbar-vertical.os-scrollbar-auto-hidden + .os-scrollbar-corner, -.os-scrollbar-horizontal.os-scrollbar-auto-hidden + .os-scrollbar-vertical.os-scrollbar-auto-hidden + .os-scrollbar-corner { - opacity: 0; - visibility: hidden; - pointer-events: none; -} -.os-scrollbar-corner-resize-both { - cursor: nwse-resize; -} -.os-host-rtl > .os-scrollbar-corner-resize-both { - cursor: nesw-resize; -} -.os-scrollbar-corner-resize-horizontal { - cursor: ew-resize; -} -.os-scrollbar-corner-resize-vertical { - cursor: ns-resize; -} -.os-dragging .os-scrollbar-corner.os-scrollbar-corner-resize { - cursor: default; -} -.os-host-resize-disabled.os-host-scrollbar-horizontal-hidden > .os-scrollbar-vertical { - top: 0; - bottom: 0; -} -.os-host-resize-disabled.os-host-scrollbar-vertical-hidden > .os-scrollbar-horizontal, -.os-host-rtl.os-host-resize-disabled.os-host-scrollbar-vertical-hidden > .os-scrollbar-horizontal { - right: 0; - left: 0; -} -.os-scrollbar:hover, -.os-scrollbar-corner.os-scrollbar-corner-resize { - opacity: 1 !important; - visibility: visible !important; -} -.os-scrollbar-corner.os-scrollbar-corner-resize { - background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB3aWR0aD0iMTAiICAgaGVpZ2h0PSIxMCIgICB2ZXJzaW9uPSIxLjEiPiAgPGcgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTEwNDIuMzYyMikiICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmUiPiAgICA8cGF0aCAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eTowLjQ5NDExNzY1O2ZpbGwtcnVsZTpldmVub2RkO3N0cm9rZTpub25lIiAgICAgICBkPSJtIDcuNDI0MjE4NywxMDQyLjM2MjIgYyAtMC43MjM1NzkyLDAgLTEuMzEwMTU2MiwwLjU4NjYgLTEuMzEwMTU2MiwxLjMxMDIgMCwwLjI5OSAwLjEwNDM0MTksMC41NzEgMC4yNzI5NDkyLDAuNzkxNSAwLjIwOTEwMjQsMC4xNDEzIDAuNDY1NjIwNiwwLjIxODQgMC43MzY5NjI5LDAuMjE4NCAwLjcyMzU3OTMsMCAxLjMxMDE1NjMsLTAuNTg2NiAxLjMxMDE1NjMsLTEuMzEwMiAwLC0wLjI3MTMgLTAuMDc3MDkzLC0wLjUyNzggLTAuMjE4MzU5NCwtMC43MzcgLTAuMjIwNDk0MSwtMC4xNjg2IC0wLjQ5MjU0NDMsLTAuMjcyOSAtMC43OTE1NTI4LC0wLjI3MjkgeiBtIDAsMy4wODQzIGMgLTAuNzIzNTc5MiwwIC0xLjMxMDE1NjIsMC41ODY2IC0xLjMxMDE1NjIsMS4zMTAyIDAsMC4yOTkgMC4xMDQzNDE5LDAuNTcxIDAuMjcyOTQ5MiwwLjc5MTUgMC4yMDkxMDI0LDAuMTQxMyAwLjQ2NTYyMDYsMC4yMTg0IDAuNzM2OTYyOSwwLjIxODQgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjYgMS4zMTAxNTYzLC0xLjMxMDIgMCwtMC4yNzEzIC0wLjA3NzA5MywtMC41Mjc4IC0wLjIxODM1OTQsLTAuNzM2OSAtMC4yMjA0OTQxLC0wLjE2ODYgLTAuNDkyNTQ0MywtMC4yNzMgLTAuNzkxNTUyOCwtMC4yNzMgeiBtIC0zLjA4NDMyNjEsMCBjIC0wLjcyMzU3OTMsMCAtMS4zMTAxNTYzLDAuNTg2NiAtMS4zMTAxNTYzLDEuMzEwMiAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MSAwLjI3Mjk0OTIsMC43OTE1IDAuMjA5MTAyNCwwLjE0MTMgMC40NjU2MjA3LDAuMjE4NCAwLjczNjk2MjksMC4yMTg0IDAuNzIzNTc5MywwIDEuMzEwMTU2MywtMC41ODY2IDEuMzEwMTU2MywtMS4zMTAyIDAsLTAuMjcxMyAtMC4wNzcwOTMsLTAuNTI3OCAtMC4yMTgzNTk0LC0wLjczNjkgLTAuMjIwNDk0LC0wLjE2ODYgLTAuNDkyNTQ0MiwtMC4yNzMgLTAuNzkxNTUyNywtMC4yNzMgeiBtIC0zLjAyOTczNjQsMy4wMjk4IEMgMC41ODY1NzY5MywxMDQ4LjQ3NjMgMCwxMDQ5LjA2MjggMCwxMDQ5Ljc4NjQgYyAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MTEgMC4yNzI5NDkyMiwwLjc5MTYgMC4yMDkxMDIyOSwwLjE0MTIgMC40NjU2MjA2NSwwLjIxODMgMC43MzY5NjI4OCwwLjIxODMgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjUgMS4zMTAxNTYzLC0xLjMxMDEgMCwtMC4yNzE0IC0wLjA3NzA5MywtMC41Mjc5IC0wLjIxODM1OTQsLTAuNzM3IC0wLjIyMDQ5NDEsLTAuMTY4NiAtMC40OTI1NDQzLC0wLjI3MjkgLTAuNzkxNTUyOCwtMC4yNzI5IHogbSAzLjAyOTczNjQsMCBjIC0wLjcyMzU3OTMsMCAtMS4zMTAxNTYzLDAuNTg2NSAtMS4zMTAxNTYzLDEuMzEwMSAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MTEgMC4yNzI5NDkyLDAuNzkxNiAwLjIwOTEwMjQsMC4xNDEyIDAuNDY1NjIwNywwLjIxODMgMC43MzY5NjI5LDAuMjE4MyAwLjcyMzU3OTMsMCAxLjMxMDE1NjMsLTAuNTg2NSAxLjMxMDE1NjMsLTEuMzEwMSAwLC0wLjI3MTQgLTAuMDc3MDkzLC0wLjUyNzkgLTAuMjE4MzU5NCwtMC43MzcgLTAuMjIwNDk0LC0wLjE2ODYgLTAuNDkyNTQ0MiwtMC4yNzI5IC0wLjc5MTU1MjcsLTAuMjcyOSB6IG0gMy4wODQzMjYxLDAgYyAtMC43MjM1NzkyLDAgLTEuMzEwMTU2MiwwLjU4NjUgLTEuMzEwMTU2MiwxLjMxMDEgMCwwLjI5OSAwLjEwNDM0MTksMC41NzExIDAuMjcyOTQ5MiwwLjc5MTYgMC4yMDkxMDI0LDAuMTQxMiAwLjQ2NTYyMDYsMC4yMTgzIDAuNzM2OTYyOSwwLjIxODMgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjUgMS4zMTAxNTYzLC0xLjMxMDEgMCwtMC4yNzE0IC0wLjA3NzA5MywtMC41Mjc5IC0wLjIxODM1OTQsLTAuNzM3IC0wLjIyMDQ5NDEsLTAuMTY4NiAtMC40OTI1NDQzLC0wLjI3MjkgLTAuNzkxNTUyOCwtMC4yNzI5IHoiLz4gIDwvZz4gIDxnICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmUiPiAgICA8cGF0aCAgICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpldmVub2RkO3N0cm9rZTpub25lIiAgICAgICBkPSJtIDguMjE1NzcxNSwwLjI3Mjk0OTIyIGMgMC4xNDEyNjY3LDAuMjA5MTAyMjkgMC4yMTgzNTk0LDAuNDY1NjIwNjUgMC4yMTgzNTk0LDAuNzM2OTYyODggMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MyAtMS4zMTAxNTYzLDEuMzEwMTU2MyAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTk0IDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDc2IC0wLjIwNTUxNzYsLTAuNzk3Nzk2NTkgLTAuNTE4NjAzNSwtMS4wMzcyMDY5OCB6IG0gMCwzLjA4NDMyNjE4IGMgMC4xNDEyNjY3LDAuMjA5MTAyMyAwLjIxODM1OTQsMC40NjU2MjA2IDAuMjE4MzU5NCwwLjczNjk2MjkgMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MiAtMS4zMTAxNTYzLDEuMzEwMTU2MiAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTkzIDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY3IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogbSAtMy4wODQzMjYyLDAgYyAwLjE0MTI2NjcsMC4yMDkxMDIzIDAuMjE4MzU5NCwwLjQ2NTYyMDYgMC4yMTgzNTk0LDAuNzM2OTYyOSAwLDAuNzIzNTc5MyAtMC41ODY1NzcsMS4zMTAxNTYyIC0xLjMxMDE1NjMsMS4zMTAxNTYyIC0wLjI3MTM0MjIsMCAtMC41Mjc4NjA1LC0wLjA3NzA5MyAtMC43MzY5NjI5LC0wLjIxODM1OTMgMC4yMzk0MTA0LDAuMzEzMDg1OSAwLjYxMjYzNjMsMC41MTg2MDM1IDEuMDM3MjA3MSwwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYyLC0wLjU4NjU3NyAxLjMxMDE1NjIsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NSwtMC43OTc3OTY3IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogTSAyLjEwMTcwOSw2LjM4NzAxMTcgYyAwLjE0MTI2NjcsMC4yMDkxMDI0IDAuMjE4MzU5NCwwLjQ2NTYyMDYgMC4yMTgzNTk0LDAuNzM2OTYyOSAwLDAuNzIzNTc5MyAtMC41ODY1NzcsMS4zMTAxNTYzIC0xLjMxMDE1NjMsMS4zMTAxNTYzIC0wLjI3MTM0MjIzLDAgLTAuNTI3ODYwNTksLTAuMDc3MDkzIC0wLjczNjk2Mjg4LC0wLjIxODM1OTQgMC4yMzk0MTAzOSwwLjMxMzA4NTkgMC42MTI2MzYyMiwwLjUxODYwMzUgMS4wMzcyMDY5OCwwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY2IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogbSAzLjAyOTczNjMsMCBjIDAuMTQxMjY2NywwLjIwOTEwMjQgMC4yMTgzNTk0LDAuNDY1NjIwNiAwLjIxODM1OTQsMC43MzY5NjI5IDAsMC43MjM1NzkzIC0wLjU4NjU3NywxLjMxMDE1NjMgLTEuMzEwMTU2MywxLjMxMDE1NjMgLTAuMjcxMzQyMiwwIC0wLjUyNzg2MDUsLTAuMDc3MDkzIC0wLjczNjk2MjksLTAuMjE4MzU5NCAwLjIzOTQxMDQsMC4zMTMwODU5IDAuNjEyNjM2MywwLjUxODYwMzUgMS4wMzcyMDcxLDAuNTE4NjAzNSAwLjcyMzU3OTMsMCAxLjMxMDE1NjIsLTAuNTg2NTc3IDEuMzEwMTU2MiwtMS4zMTAxNTYzIDAsLTAuNDI0NTcwOCAtMC4yMDU1MTc1LC0wLjc5Nzc5NjYgLTAuNTE4NjAzNSwtMS4wMzcyMDcgeiBtIDMuMDg0MzI2MiwwIGMgMC4xNDEyNjY3LDAuMjA5MTAyNCAwLjIxODM1OTQsMC40NjU2MjA2IDAuMjE4MzU5NCwwLjczNjk2MjkgMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MyAtMS4zMTAxNTYzLDEuMzEwMTU2MyAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTk0IDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY2IC0wLjUxODYwMzUsLTEuMDM3MjA3IHoiIC8+ICA8L2c+PC9zdmc+); - background-repeat: no-repeat; - background-position: 100% 100%; - pointer-events: auto !important; -} -.os-host-rtl > .os-scrollbar-corner.os-scrollbar-corner-resize { - -webkit-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.os-host-overflow { - overflow: hidden !important; -} -.os-host-overflow-x { -} -.os-host-overflow-y { -} - -/* -THEMES: -*/ - -/* NONE THEME: */ -.os-theme-none > .os-scrollbar-horizontal, -.os-theme-none > .os-scrollbar-vertical, -.os-theme-none > .os-scrollbar-corner { - display: none !important; -} -.os-theme-none > .os-scrollbar-corner-resize { - display: block !important; - min-width: 10px; - min-height: 10px; -} -/* DARK & LIGHT THEME: */ -.os-theme-dark > .os-scrollbar-horizontal, -.os-theme-light > .os-scrollbar-horizontal { - right: 10px; - height: 10px; -} -.os-theme-dark > .os-scrollbar-vertical, -.os-theme-light > .os-scrollbar-vertical { - bottom: 10px; - width: 10px; -} -.os-theme-dark.os-host-rtl > .os-scrollbar-horizontal, -.os-theme-light.os-host-rtl > .os-scrollbar-horizontal { - left: 10px; - right: 0; -} -.os-theme-dark > .os-scrollbar-corner, -.os-theme-light > .os-scrollbar-corner { - height: 10px; - width: 10px; -} -.os-theme-dark > .os-scrollbar-corner, -.os-theme-light > .os-scrollbar-corner { - background-color: transparent; -} -.os-theme-dark > .os-scrollbar, -.os-theme-light > .os-scrollbar { - padding: 2px; - box-sizing: border-box; - background: transparent; -} -.os-theme-dark > .os-scrollbar.os-scrollbar-unusable, -.os-theme-light > .os-scrollbar.os-scrollbar-unusable { - background: transparent; -} -.os-theme-dark > .os-scrollbar > .os-scrollbar-track, -.os-theme-light > .os-scrollbar > .os-scrollbar-track { - background: transparent; -} -.os-theme-dark > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle { - min-width: 30px; -} -.os-theme-dark > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle { - min-height: 30px; -} -.os-theme-dark.os-host-transition > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light.os-host-transition > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { - -webkit-transition: background-color 0.3s; - transition: background-color 0.3s; -} -.os-theme-dark > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-dark > .os-scrollbar > .os-scrollbar-track, -.os-theme-light > .os-scrollbar > .os-scrollbar-track { - border-radius: 10px; -} -.os-theme-dark > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(0, 0, 0, 0.4); -} -.os-theme-light > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(255, 255, 255, 0.4); -} -.os-theme-dark > .os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(0, 0, 0, .55); -} -.os-theme-light > .os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(255, 255, 255, .55); -} -.os-theme-dark > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { - background: rgba(0, 0, 0, .7); -} -.os-theme-light > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { - background: rgba(255, 255, 255, .7); -} -.os-theme-dark > .os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-dark > .os-scrollbar-vertical .os-scrollbar-handle:before, -.os-theme-light > .os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-light > .os-scrollbar-vertical .os-scrollbar-handle:before { - content: ''; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: block; -} -.os-theme-dark.os-host-scrollbar-horizontal-hidden > .os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-dark.os-host-scrollbar-vertical-hidden > .os-scrollbar-vertical .os-scrollbar-handle:before, -.os-theme-light.os-host-scrollbar-horizontal-hidden > .os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-light.os-host-scrollbar-vertical-hidden > .os-scrollbar-vertical .os-scrollbar-handle:before { - display: none; -} -.os-theme-dark > .os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-light > .os-scrollbar-horizontal .os-scrollbar-handle:before { - top: -6px; - bottom: -2px; -} -.os-theme-dark > .os-scrollbar-vertical .os-scrollbar-handle:before, -.os-theme-light > .os-scrollbar-vertical .os-scrollbar-handle:before { - left: -6px; - right: -2px; -} -.os-host-rtl.os-theme-dark > .os-scrollbar-vertical .os-scrollbar-handle:before, -.os-host-rtl.os-theme-light > .os-scrollbar-vertical .os-scrollbar-handle:before { - right: -6px; - left: -2px; -} +/*! + * OverlayScrollbars + * https://github.com/KingSora/OverlayScrollbars + * + * Version: 1.11.0 + * + * Copyright KingSora | Rene Haas. + * https://github.com/KingSora + * + * Released under the MIT license. + * Date: 29.02.2020 + */ + +/* +OVERLAY SCROLLBARS CORE: +*/ + +html.os-html, +html.os-html > .os-host { + display: block; + overflow: hidden; + box-sizing: border-box; + height: 100% !important; + width: 100% !important; + min-width: 100% !important; + min-height: 100% !important; + margin: 0 !important; + position: absolute !important; /* could be position: fixed; but it causes issues on iOS (-webkit-overflow-scrolling: touch) */ +} +html.os-html > .os-host > .os-padding { + position: absolute; /* could be position: fixed; but it causes issues on iOS (-webkit-overflow-scrolling: touch) */ +} +body.os-dragging, +body.os-dragging * { + cursor: default; +} +.os-host, +.os-host-textarea { + position: relative; + overflow: visible !important; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + -ms-flex-line-pack: start; + align-content: flex-start; + -webkit-box-align: start; + -ms-flex-align: start; + -ms-grid-row-align: flex-start; + align-items: flex-start; +} +.os-host-flexbox { + overflow: hidden !important; + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} +.os-host-flexbox > .os-size-auto-observer { + height: inherit !important; +} +.os-host-flexbox > .os-content-glue { + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + -ms-flex-negative: 0; + flex-shrink: 0; +} +.os-host-flexbox > .os-size-auto-observer, +.os-host-flexbox > .os-content-glue { + min-height: 0; + min-width: 0; + -webkit-box-flex: 0; + -ms-flex-positive: 0; + flex-grow: 0; + -ms-flex-negative: 1; + flex-shrink: 1; + -ms-flex-preferred-size: auto; + flex-basis: auto; +} +#os-dummy-scrollbar-size { + position: fixed; + opacity: 0; + -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=0)'; + visibility: hidden; + overflow: scroll; + height: 500px; + width: 500px; +} +#os-dummy-scrollbar-size > div { + width: 200%; + height: 200%; + margin: 10px 0; +} +/* fix restricted measuring */ +#os-dummy-scrollbar-size:before, +#os-dummy-scrollbar-size:after, +.os-content:before, +.os-content:after { + content: ''; + display: table; + width: 0.01px; + height: 0.01px; + line-height: 0; + font-size: 0; + flex-grow: 0; + flex-shrink: 0; + visibility: hidden; +} +#os-dummy-scrollbar-size, +.os-viewport { + -ms-overflow-style: scrollbar !important; +} +.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size, +.os-viewport-native-scrollbars-invisible.os-viewport { + scrollbar-width: none !important; +} +.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size::-webkit-scrollbar, +.os-viewport-native-scrollbars-invisible.os-viewport::-webkit-scrollbar, +.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size::-webkit-scrollbar-corner, +.os-viewport-native-scrollbars-invisible.os-viewport::-webkit-scrollbar-corner { + display: none !important; + width: 0px !important; + height: 0px !important; + visibility: hidden !important; + background: transparent !important; +} +.os-content-glue { + box-sizing: inherit; + max-height: 100%; + max-width: 100%; + width: 100%; + pointer-events: none; +} +.os-padding { + box-sizing: inherit; + direction: inherit; + position: absolute; + overflow: visible; + padding: 0; + margin: 0; + left: 0; + top: 0; + bottom: 0; + right: 0; + width: auto !important; + height: auto !important; + z-index: 1; +} +.os-host-overflow > .os-padding { + overflow: hidden; +} +.os-viewport { + direction: inherit !important; + box-sizing: inherit !important; + resize: none !important; + outline: none !important; + position: absolute; + overflow: hidden; + top: 0; + left: 0; + bottom: 0; + right: 0; + padding: 0; + margin: 0; + -webkit-overflow-scrolling: touch; +} +.os-content-arrange { + position: absolute; + z-index: -1; + min-height: 1px; + min-width: 1px; + pointer-events: none; +} +.os-content { + direction: inherit; + box-sizing: border-box !important; + position: relative; + display: block; + height: 100%; + width: 100%; + height: 100%; + width: 100%; + visibility: visible; +} +.os-content > .os-textarea { + box-sizing: border-box !important; + direction: inherit !important; + background: transparent !important; + outline: 0px none transparent !important; + overflow: hidden !important; + position: absolute !important; + display: block !important; + top: 0 !important; + left: 0 !important; + margin: 0 !important; + border-radius: 0px !important; + float: none !important; + -webkit-filter: none !important; + filter: none !important; + border: none !important; + resize: none !important; + -webkit-transform: none !important; + transform: none !important; + max-width: none !important; + max-height: none !important; + box-shadow: none !important; + -webkit-perspective: none !important; + perspective: none !important; + opacity: 1 !important; + z-index: 1 !important; + clip: auto !important; + vertical-align: baseline !important; + padding: 0px; +} +.os-host-rtl > .os-padding > .os-viewport > .os-content > .os-textarea { + right: 0 !important; +} +.os-content > .os-textarea-cover { + z-index: -1; + pointer-events: none; +} +.os-content > .os-textarea[wrap='off'] { + white-space: pre !important; + margin: 0px !important; +} +.os-text-inherit { + font-family: inherit; + font-size: inherit; + font-weight: inherit; + font-style: inherit; + font-variant: inherit; + text-transform: inherit; + text-decoration: inherit; + text-indent: inherit; + text-align: inherit; + text-shadow: inherit; + text-overflow: inherit; + letter-spacing: inherit; + word-spacing: inherit; + line-height: inherit; + unicode-bidi: inherit; + direction: inherit; + color: inherit; + cursor: text; +} +.os-resize-observer, +.os-resize-observer-host { + box-sizing: inherit; + display: block; + visibility: hidden; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + overflow: hidden; + pointer-events: none; + z-index: -1; +} +.os-resize-observer-host { + padding: inherit; + border: inherit; + border-color: transparent; + border-style: solid; + box-sizing: border-box; +} +.os-resize-observer-host > .os-resize-observer { + height: 200%; + width: 200%; + padding: inherit; + border: inherit; + margin: 0px; + display: block; + box-sizing: content-box; +} +.os-resize-observer-host.observed { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; +} +.os-resize-observer-host.observed > .os-resize-observer { + position: relative; + flex-grow: 1; + flex-shrink: 0; + flex-basis: auto; +} +.os-size-auto-observer { + box-sizing: inherit !important; + height: 100%; + width: inherit; + max-width: 1px; + position: relative; + float: left; + max-height: 1px; + overflow: hidden; + z-index: -1; + padding: 0; + margin: 0; + pointer-events: none; + -webkit-box-flex: inherit; + -ms-flex-positive: inherit; + flex-grow: inherit; + -ms-flex-negative: 0; + flex-shrink: 0; + -ms-flex-preferred-size: 0; + flex-basis: 0; +} +.os-size-auto-observer > .os-resize-observer { + width: 1000%; + height: 1000%; + min-height: 1px; + min-width: 1px; +} +.os-resize-observer-item { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + z-index: -1; + opacity: 0; + direction: ltr !important; + -webkit-box-flex: 0 !important; + -ms-flex: none !important; + flex: none !important; +} +.os-resize-observer-item-final { + position: absolute; + left: 0; + top: 0; + -webkit-transition: none !important; + transition: none !important; + -webkit-box-flex: 0 !important; + -ms-flex: none !important; + flex: none !important; +} +.os-resize-observer { + -webkit-animation-duration: 0.001s; + animation-duration: 0.001s; + -webkit-animation-name: os-resize-observer-dummy-animation; + animation-name: os-resize-observer-dummy-animation; +} +object.os-resize-observer { + box-sizing: border-box !important; +} +@-webkit-keyframes os-resize-observer-dummy-animation { + from { + z-index: 0; + } + to { + z-index: -1; + } +} +@keyframes os-resize-observer-dummy-animation { + from { + z-index: 0; + } + to { + z-index: -1; + } +} + +/* +CUSTOM SCROLLBARS AND CORNER CORE: +*/ + +.os-host-transition > .os-scrollbar, +.os-host-transition > .os-scrollbar-corner { + -webkit-transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s; + transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s; +} +html.os-html > .os-host > .os-scrollbar { + position: absolute; /* could be position: fixed; but it causes issues on iOS (-webkit-overflow-scrolling: touch) */ + z-index: 999999; /* highest z-index of the page */ +} +.os-scrollbar, +.os-scrollbar-corner { + position: absolute; + opacity: 1; + -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)'; + z-index: 1; +} +.os-scrollbar-corner { + bottom: 0; + right: 0; +} +.os-scrollbar { + pointer-events: none; +} +.os-scrollbar-track { + pointer-events: auto; + position: relative; + height: 100%; + width: 100%; + padding: 0 !important; + border: none !important; +} +.os-scrollbar-handle { + pointer-events: auto; + position: absolute; + width: 100%; + height: 100%; +} +.os-scrollbar-handle-off, +.os-scrollbar-track-off { + pointer-events: none; +} +.os-scrollbar.os-scrollbar-unusable, +.os-scrollbar.os-scrollbar-unusable * { + pointer-events: none !important; +} +.os-scrollbar.os-scrollbar-unusable .os-scrollbar-handle { + opacity: 0 !important; +} +.os-scrollbar-horizontal { + bottom: 0; + left: 0; +} +.os-scrollbar-vertical { + top: 0; + right: 0; +} +.os-host-rtl > .os-scrollbar-horizontal { + right: 0; +} +.os-host-rtl > .os-scrollbar-vertical { + right: auto; + left: 0; +} +.os-host-rtl > .os-scrollbar-corner { + right: auto; + left: 0; +} +.os-scrollbar-auto-hidden, +.os-padding + .os-scrollbar-corner, +.os-host-resize-disabled.os-host-scrollbar-horizontal-hidden > .os-scrollbar-corner, +.os-host-scrollbar-horizontal-hidden > .os-scrollbar-horizontal, +.os-host-resize-disabled.os-host-scrollbar-vertical-hidden > .os-scrollbar-corner, +.os-host-scrollbar-vertical-hidden > .os-scrollbar-vertical, +.os-scrollbar-horizontal.os-scrollbar-auto-hidden + .os-scrollbar-vertical + .os-scrollbar-corner, +.os-scrollbar-horizontal + .os-scrollbar-vertical.os-scrollbar-auto-hidden + .os-scrollbar-corner, +.os-scrollbar-horizontal.os-scrollbar-auto-hidden + .os-scrollbar-vertical.os-scrollbar-auto-hidden + .os-scrollbar-corner { + opacity: 0; + visibility: hidden; + pointer-events: none; +} +.os-scrollbar-corner-resize-both { + cursor: nwse-resize; +} +.os-host-rtl > .os-scrollbar-corner-resize-both { + cursor: nesw-resize; +} +.os-scrollbar-corner-resize-horizontal { + cursor: ew-resize; +} +.os-scrollbar-corner-resize-vertical { + cursor: ns-resize; +} +.os-dragging .os-scrollbar-corner.os-scrollbar-corner-resize { + cursor: default; +} +.os-host-resize-disabled.os-host-scrollbar-horizontal-hidden > .os-scrollbar-vertical { + top: 0; + bottom: 0; +} +.os-host-resize-disabled.os-host-scrollbar-vertical-hidden > .os-scrollbar-horizontal, +.os-host-rtl.os-host-resize-disabled.os-host-scrollbar-vertical-hidden > .os-scrollbar-horizontal { + right: 0; + left: 0; +} +.os-scrollbar:hover, +.os-scrollbar-corner.os-scrollbar-corner-resize { + opacity: 1 !important; + visibility: visible !important; +} +.os-scrollbar-corner.os-scrollbar-corner-resize { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB3aWR0aD0iMTAiICAgaGVpZ2h0PSIxMCIgICB2ZXJzaW9uPSIxLjEiPiAgPGcgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTEwNDIuMzYyMikiICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmUiPiAgICA8cGF0aCAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eTowLjQ5NDExNzY1O2ZpbGwtcnVsZTpldmVub2RkO3N0cm9rZTpub25lIiAgICAgICBkPSJtIDcuNDI0MjE4NywxMDQyLjM2MjIgYyAtMC43MjM1NzkyLDAgLTEuMzEwMTU2MiwwLjU4NjYgLTEuMzEwMTU2MiwxLjMxMDIgMCwwLjI5OSAwLjEwNDM0MTksMC41NzEgMC4yNzI5NDkyLDAuNzkxNSAwLjIwOTEwMjQsMC4xNDEzIDAuNDY1NjIwNiwwLjIxODQgMC43MzY5NjI5LDAuMjE4NCAwLjcyMzU3OTMsMCAxLjMxMDE1NjMsLTAuNTg2NiAxLjMxMDE1NjMsLTEuMzEwMiAwLC0wLjI3MTMgLTAuMDc3MDkzLC0wLjUyNzggLTAuMjE4MzU5NCwtMC43MzcgLTAuMjIwNDk0MSwtMC4xNjg2IC0wLjQ5MjU0NDMsLTAuMjcyOSAtMC43OTE1NTI4LC0wLjI3MjkgeiBtIDAsMy4wODQzIGMgLTAuNzIzNTc5MiwwIC0xLjMxMDE1NjIsMC41ODY2IC0xLjMxMDE1NjIsMS4zMTAyIDAsMC4yOTkgMC4xMDQzNDE5LDAuNTcxIDAuMjcyOTQ5MiwwLjc5MTUgMC4yMDkxMDI0LDAuMTQxMyAwLjQ2NTYyMDYsMC4yMTg0IDAuNzM2OTYyOSwwLjIxODQgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjYgMS4zMTAxNTYzLC0xLjMxMDIgMCwtMC4yNzEzIC0wLjA3NzA5MywtMC41Mjc4IC0wLjIxODM1OTQsLTAuNzM2OSAtMC4yMjA0OTQxLC0wLjE2ODYgLTAuNDkyNTQ0MywtMC4yNzMgLTAuNzkxNTUyOCwtMC4yNzMgeiBtIC0zLjA4NDMyNjEsMCBjIC0wLjcyMzU3OTMsMCAtMS4zMTAxNTYzLDAuNTg2NiAtMS4zMTAxNTYzLDEuMzEwMiAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MSAwLjI3Mjk0OTIsMC43OTE1IDAuMjA5MTAyNCwwLjE0MTMgMC40NjU2MjA3LDAuMjE4NCAwLjczNjk2MjksMC4yMTg0IDAuNzIzNTc5MywwIDEuMzEwMTU2MywtMC41ODY2IDEuMzEwMTU2MywtMS4zMTAyIDAsLTAuMjcxMyAtMC4wNzcwOTMsLTAuNTI3OCAtMC4yMTgzNTk0LC0wLjczNjkgLTAuMjIwNDk0LC0wLjE2ODYgLTAuNDkyNTQ0MiwtMC4yNzMgLTAuNzkxNTUyNywtMC4yNzMgeiBtIC0zLjAyOTczNjQsMy4wMjk4IEMgMC41ODY1NzY5MywxMDQ4LjQ3NjMgMCwxMDQ5LjA2MjggMCwxMDQ5Ljc4NjQgYyAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MTEgMC4yNzI5NDkyMiwwLjc5MTYgMC4yMDkxMDIyOSwwLjE0MTIgMC40NjU2MjA2NSwwLjIxODMgMC43MzY5NjI4OCwwLjIxODMgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjUgMS4zMTAxNTYzLC0xLjMxMDEgMCwtMC4yNzE0IC0wLjA3NzA5MywtMC41Mjc5IC0wLjIxODM1OTQsLTAuNzM3IC0wLjIyMDQ5NDEsLTAuMTY4NiAtMC40OTI1NDQzLC0wLjI3MjkgLTAuNzkxNTUyOCwtMC4yNzI5IHogbSAzLjAyOTczNjQsMCBjIC0wLjcyMzU3OTMsMCAtMS4zMTAxNTYzLDAuNTg2NSAtMS4zMTAxNTYzLDEuMzEwMSAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MTEgMC4yNzI5NDkyLDAuNzkxNiAwLjIwOTEwMjQsMC4xNDEyIDAuNDY1NjIwNywwLjIxODMgMC43MzY5NjI5LDAuMjE4MyAwLjcyMzU3OTMsMCAxLjMxMDE1NjMsLTAuNTg2NSAxLjMxMDE1NjMsLTEuMzEwMSAwLC0wLjI3MTQgLTAuMDc3MDkzLC0wLjUyNzkgLTAuMjE4MzU5NCwtMC43MzcgLTAuMjIwNDk0LC0wLjE2ODYgLTAuNDkyNTQ0MiwtMC4yNzI5IC0wLjc5MTU1MjcsLTAuMjcyOSB6IG0gMy4wODQzMjYxLDAgYyAtMC43MjM1NzkyLDAgLTEuMzEwMTU2MiwwLjU4NjUgLTEuMzEwMTU2MiwxLjMxMDEgMCwwLjI5OSAwLjEwNDM0MTksMC41NzExIDAuMjcyOTQ5MiwwLjc5MTYgMC4yMDkxMDI0LDAuMTQxMiAwLjQ2NTYyMDYsMC4yMTgzIDAuNzM2OTYyOSwwLjIxODMgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjUgMS4zMTAxNTYzLC0xLjMxMDEgMCwtMC4yNzE0IC0wLjA3NzA5MywtMC41Mjc5IC0wLjIxODM1OTQsLTAuNzM3IC0wLjIyMDQ5NDEsLTAuMTY4NiAtMC40OTI1NDQzLC0wLjI3MjkgLTAuNzkxNTUyOCwtMC4yNzI5IHoiLz4gIDwvZz4gIDxnICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmUiPiAgICA8cGF0aCAgICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpldmVub2RkO3N0cm9rZTpub25lIiAgICAgICBkPSJtIDguMjE1NzcxNSwwLjI3Mjk0OTIyIGMgMC4xNDEyNjY3LDAuMjA5MTAyMjkgMC4yMTgzNTk0LDAuNDY1NjIwNjUgMC4yMTgzNTk0LDAuNzM2OTYyODggMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MyAtMS4zMTAxNTYzLDEuMzEwMTU2MyAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTk0IDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDc2IC0wLjIwNTUxNzYsLTAuNzk3Nzk2NTkgLTAuNTE4NjAzNSwtMS4wMzcyMDY5OCB6IG0gMCwzLjA4NDMyNjE4IGMgMC4xNDEyNjY3LDAuMjA5MTAyMyAwLjIxODM1OTQsMC40NjU2MjA2IDAuMjE4MzU5NCwwLjczNjk2MjkgMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MiAtMS4zMTAxNTYzLDEuMzEwMTU2MiAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTkzIDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY3IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogbSAtMy4wODQzMjYyLDAgYyAwLjE0MTI2NjcsMC4yMDkxMDIzIDAuMjE4MzU5NCwwLjQ2NTYyMDYgMC4yMTgzNTk0LDAuNzM2OTYyOSAwLDAuNzIzNTc5MyAtMC41ODY1NzcsMS4zMTAxNTYyIC0xLjMxMDE1NjMsMS4zMTAxNTYyIC0wLjI3MTM0MjIsMCAtMC41Mjc4NjA1LC0wLjA3NzA5MyAtMC43MzY5NjI5LC0wLjIxODM1OTMgMC4yMzk0MTA0LDAuMzEzMDg1OSAwLjYxMjYzNjMsMC41MTg2MDM1IDEuMDM3MjA3MSwwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYyLC0wLjU4NjU3NyAxLjMxMDE1NjIsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NSwtMC43OTc3OTY3IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogTSAyLjEwMTcwOSw2LjM4NzAxMTcgYyAwLjE0MTI2NjcsMC4yMDkxMDI0IDAuMjE4MzU5NCwwLjQ2NTYyMDYgMC4yMTgzNTk0LDAuNzM2OTYyOSAwLDAuNzIzNTc5MyAtMC41ODY1NzcsMS4zMTAxNTYzIC0xLjMxMDE1NjMsMS4zMTAxNTYzIC0wLjI3MTM0MjIzLDAgLTAuNTI3ODYwNTksLTAuMDc3MDkzIC0wLjczNjk2Mjg4LC0wLjIxODM1OTQgMC4yMzk0MTAzOSwwLjMxMzA4NTkgMC42MTI2MzYyMiwwLjUxODYwMzUgMS4wMzcyMDY5OCwwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY2IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogbSAzLjAyOTczNjMsMCBjIDAuMTQxMjY2NywwLjIwOTEwMjQgMC4yMTgzNTk0LDAuNDY1NjIwNiAwLjIxODM1OTQsMC43MzY5NjI5IDAsMC43MjM1NzkzIC0wLjU4NjU3NywxLjMxMDE1NjMgLTEuMzEwMTU2MywxLjMxMDE1NjMgLTAuMjcxMzQyMiwwIC0wLjUyNzg2MDUsLTAuMDc3MDkzIC0wLjczNjk2MjksLTAuMjE4MzU5NCAwLjIzOTQxMDQsMC4zMTMwODU5IDAuNjEyNjM2MywwLjUxODYwMzUgMS4wMzcyMDcxLDAuNTE4NjAzNSAwLjcyMzU3OTMsMCAxLjMxMDE1NjIsLTAuNTg2NTc3IDEuMzEwMTU2MiwtMS4zMTAxNTYzIDAsLTAuNDI0NTcwOCAtMC4yMDU1MTc1LC0wLjc5Nzc5NjYgLTAuNTE4NjAzNSwtMS4wMzcyMDcgeiBtIDMuMDg0MzI2MiwwIGMgMC4xNDEyNjY3LDAuMjA5MTAyNCAwLjIxODM1OTQsMC40NjU2MjA2IDAuMjE4MzU5NCwwLjczNjk2MjkgMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MyAtMS4zMTAxNTYzLDEuMzEwMTU2MyAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTk0IDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY2IC0wLjUxODYwMzUsLTEuMDM3MjA3IHoiIC8+ICA8L2c+PC9zdmc+); + background-repeat: no-repeat; + background-position: 100% 100%; + pointer-events: auto !important; +} +.os-host-rtl > .os-scrollbar-corner.os-scrollbar-corner-resize { + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.os-host-overflow { + overflow: hidden !important; +} +.os-host-overflow-x { +} +.os-host-overflow-y { +} + +/* +THEMES: +*/ + +/* NONE THEME: */ +.os-theme-none > .os-scrollbar-horizontal, +.os-theme-none > .os-scrollbar-vertical, +.os-theme-none > .os-scrollbar-corner { + display: none !important; +} +.os-theme-none > .os-scrollbar-corner-resize { + display: block !important; + min-width: 10px; + min-height: 10px; +} +/* DARK & LIGHT THEME: */ +.os-theme-dark > .os-scrollbar-horizontal, +.os-theme-light > .os-scrollbar-horizontal { + right: 10px; + height: 10px; +} +.os-theme-dark > .os-scrollbar-vertical, +.os-theme-light > .os-scrollbar-vertical { + bottom: 10px; + width: 10px; +} +.os-theme-dark.os-host-rtl > .os-scrollbar-horizontal, +.os-theme-light.os-host-rtl > .os-scrollbar-horizontal { + left: 10px; + right: 0; +} +.os-theme-dark > .os-scrollbar-corner, +.os-theme-light > .os-scrollbar-corner { + height: 10px; + width: 10px; +} +.os-theme-dark > .os-scrollbar-corner, +.os-theme-light > .os-scrollbar-corner { + background-color: transparent; +} +.os-theme-dark > .os-scrollbar, +.os-theme-light > .os-scrollbar { + padding: 2px; + box-sizing: border-box; + background: transparent; +} +.os-theme-dark > .os-scrollbar.os-scrollbar-unusable, +.os-theme-light > .os-scrollbar.os-scrollbar-unusable { + background: transparent; +} +.os-theme-dark > .os-scrollbar > .os-scrollbar-track, +.os-theme-light > .os-scrollbar > .os-scrollbar-track { + background: transparent; +} +.os-theme-dark > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle, +.os-theme-light > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle { + min-width: 30px; +} +.os-theme-dark > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle, +.os-theme-light > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle { + min-height: 30px; +} +.os-theme-dark.os-host-transition > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, +.os-theme-light.os-host-transition > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { + -webkit-transition: background-color 0.3s; + transition: background-color 0.3s; +} +.os-theme-dark > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, +.os-theme-light > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, +.os-theme-dark > .os-scrollbar > .os-scrollbar-track, +.os-theme-light > .os-scrollbar > .os-scrollbar-track { + border-radius: 10px; +} +.os-theme-dark > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { + background: rgba(0, 0, 0, 0.4); +} +.os-theme-light > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { + background: rgba(255, 255, 255, 0.4); +} +.os-theme-dark > .os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { + background: rgba(0, 0, 0, .55); +} +.os-theme-light > .os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { + background: rgba(255, 255, 255, .55); +} +.os-theme-dark > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { + background: rgba(0, 0, 0, .7); +} +.os-theme-light > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { + background: rgba(255, 255, 255, .7); +} +.os-theme-dark > .os-scrollbar-horizontal .os-scrollbar-handle:before, +.os-theme-dark > .os-scrollbar-vertical .os-scrollbar-handle:before, +.os-theme-light > .os-scrollbar-horizontal .os-scrollbar-handle:before, +.os-theme-light > .os-scrollbar-vertical .os-scrollbar-handle:before { + content: ''; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + display: block; +} +.os-theme-dark.os-host-scrollbar-horizontal-hidden > .os-scrollbar-horizontal .os-scrollbar-handle:before, +.os-theme-dark.os-host-scrollbar-vertical-hidden > .os-scrollbar-vertical .os-scrollbar-handle:before, +.os-theme-light.os-host-scrollbar-horizontal-hidden > .os-scrollbar-horizontal .os-scrollbar-handle:before, +.os-theme-light.os-host-scrollbar-vertical-hidden > .os-scrollbar-vertical .os-scrollbar-handle:before { + display: none; +} +.os-theme-dark > .os-scrollbar-horizontal .os-scrollbar-handle:before, +.os-theme-light > .os-scrollbar-horizontal .os-scrollbar-handle:before { + top: -6px; + bottom: -2px; +} +.os-theme-dark > .os-scrollbar-vertical .os-scrollbar-handle:before, +.os-theme-light > .os-scrollbar-vertical .os-scrollbar-handle:before { + left: -6px; + right: -2px; +} +.os-host-rtl.os-theme-dark > .os-scrollbar-vertical .os-scrollbar-handle:before, +.os-host-rtl.os-theme-light > .os-scrollbar-vertical .os-scrollbar-handle:before { + right: -6px; + left: -2px; +} diff --git a/plugins/overlayScrollbars/css/OverlayScrollbars.min.css b/plugins/overlayScrollbars/css/OverlayScrollbars.min.css index face8d797..04ca457c0 100644 --- a/plugins/overlayScrollbars/css/OverlayScrollbars.min.css +++ b/plugins/overlayScrollbars/css/OverlayScrollbars.min.css @@ -1,13 +1,13 @@ -/*! - * OverlayScrollbars - * https://github.com/KingSora/OverlayScrollbars - * - * Version: 1.11.0 - * - * Copyright KingSora | Rene Haas. - * https://github.com/KingSora - * - * Released under the MIT license. - * Date: 29.02.2020 +/*! + * OverlayScrollbars + * https://github.com/KingSora/OverlayScrollbars + * + * Version: 1.11.0 + * + * Copyright KingSora | Rene Haas. + * https://github.com/KingSora + * + * Released under the MIT license. + * Date: 29.02.2020 */ html.os-html,html.os-html>.os-host{display:block;overflow:hidden;box-sizing:border-box;height:100%!important;width:100%!important;min-width:100%!important;min-height:100%!important;margin:0!important;position:absolute!important}html.os-html>.os-host>.os-padding{position:absolute}body.os-dragging,body.os-dragging *{cursor:default}.os-host,.os-host-textarea{position:relative;overflow:visible!important;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-ms-flex-line-pack:start;align-content:flex-start;-webkit-box-align:start;-ms-flex-align:start;-ms-grid-row-align:flex-start;align-items:flex-start}.os-host-flexbox{overflow:hidden!important;display:-webkit-box;display:-ms-flexbox;display:flex}.os-host-flexbox>.os-size-auto-observer{height:inherit!important}.os-host-flexbox>.os-content-glue{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:0;flex-shrink:0}.os-host-flexbox>.os-size-auto-observer,.os-host-flexbox>.os-content-glue{min-height:0;min-width:0;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:1;flex-shrink:1;-ms-flex-preferred-size:auto;flex-basis:auto}#os-dummy-scrollbar-size{position:fixed;opacity:0;-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=0)';visibility:hidden;overflow:scroll;height:500px;width:500px}#os-dummy-scrollbar-size>div{width:200%;height:200%;margin:10px 0}#os-dummy-scrollbar-size:before,#os-dummy-scrollbar-size:after,.os-content:before,.os-content:after{content:'';display:table;width:.01px;height:.01px;line-height:0;font-size:0;flex-grow:0;flex-shrink:0;visibility:hidden}#os-dummy-scrollbar-size,.os-viewport{-ms-overflow-style:scrollbar!important}.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size,.os-viewport-native-scrollbars-invisible.os-viewport{scrollbar-width:none!important}.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size::-webkit-scrollbar,.os-viewport-native-scrollbars-invisible.os-viewport::-webkit-scrollbar,.os-viewport-native-scrollbars-invisible#os-dummy-scrollbar-size::-webkit-scrollbar-corner,.os-viewport-native-scrollbars-invisible.os-viewport::-webkit-scrollbar-corner{display:none!important;width:0!important;height:0!important;visibility:hidden!important;background:0 0!important}.os-content-glue{box-sizing:inherit;max-height:100%;max-width:100%;width:100%;pointer-events:none}.os-padding{box-sizing:inherit;direction:inherit;position:absolute;overflow:visible;padding:0;margin:0;left:0;top:0;bottom:0;right:0;width:auto!important;height:auto!important;z-index:1}.os-host-overflow>.os-padding{overflow:hidden}.os-viewport{direction:inherit!important;box-sizing:inherit!important;resize:none!important;outline:0!important;position:absolute;overflow:hidden;top:0;left:0;bottom:0;right:0;padding:0;margin:0;-webkit-overflow-scrolling:touch}.os-content-arrange{position:absolute;z-index:-1;min-height:1px;min-width:1px;pointer-events:none}.os-content{direction:inherit;box-sizing:border-box!important;position:relative;display:block;height:100%;width:100%;height:100%;width:100%;visibility:visible}.os-content>.os-textarea{box-sizing:border-box!important;direction:inherit!important;background:0 0!important;outline:0 transparent!important;overflow:hidden!important;position:absolute!important;display:block!important;top:0!important;left:0!important;margin:0!important;border-radius:0!important;float:none!important;-webkit-filter:none!important;filter:none!important;border:0!important;resize:none!important;-webkit-transform:none!important;transform:none!important;max-width:none!important;max-height:none!important;box-shadow:none!important;-webkit-perspective:none!important;perspective:none!important;opacity:1!important;z-index:1!important;clip:auto!important;vertical-align:baseline!important;padding:0}.os-host-rtl>.os-padding>.os-viewport>.os-content>.os-textarea{right:0!important}.os-content>.os-textarea-cover{z-index:-1;pointer-events:none}.os-content>.os-textarea[wrap=off]{white-space:pre!important;margin:0!important}.os-text-inherit{font-family:inherit;font-size:inherit;font-weight:inherit;font-style:inherit;font-variant:inherit;text-transform:inherit;text-decoration:inherit;text-indent:inherit;text-align:inherit;text-shadow:inherit;text-overflow:inherit;letter-spacing:inherit;word-spacing:inherit;line-height:inherit;unicode-bidi:inherit;direction:inherit;color:inherit;cursor:text}.os-resize-observer,.os-resize-observer-host{box-sizing:inherit;display:block;visibility:hidden;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.os-resize-observer-host{padding:inherit;border:inherit;border-color:transparent;border-style:solid;box-sizing:border-box}.os-resize-observer-host>.os-resize-observer{height:200%;width:200%;padding:inherit;border:inherit;margin:0;display:block;box-sizing:content-box}.os-resize-observer-host.observed{display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start}.os-resize-observer-host.observed>.os-resize-observer{position:relative;flex-grow:1;flex-shrink:0;flex-basis:auto}.os-size-auto-observer{box-sizing:inherit!important;height:100%;width:inherit;max-width:1px;position:relative;float:left;max-height:1px;overflow:hidden;z-index:-1;padding:0;margin:0;pointer-events:none;-webkit-box-flex:inherit;-ms-flex-positive:inherit;flex-grow:inherit;-ms-flex-negative:0;flex-shrink:0;-ms-flex-preferred-size:0;flex-basis:0}.os-size-auto-observer>.os-resize-observer{width:1000%;height:1000%;min-height:1px;min-width:1px}.os-resize-observer-item{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;z-index:-1;opacity:0;direction:ltr!important;-webkit-box-flex:0!important;-ms-flex:none!important;flex:none!important}.os-resize-observer-item-final{position:absolute;left:0;top:0;-webkit-transition:none!important;transition:none!important;-webkit-box-flex:0!important;-ms-flex:none!important;flex:none!important}.os-resize-observer{-webkit-animation-duration:.001s;animation-duration:.001s;-webkit-animation-name:os-resize-observer-dummy-animation;animation-name:os-resize-observer-dummy-animation}object.os-resize-observer{box-sizing:border-box!important}@-webkit-keyframes os-resize-observer-dummy-animation{0%{z-index:0}to{z-index:-1}}@keyframes os-resize-observer-dummy-animation{0%{z-index:0}to{z-index:-1}}.os-host-transition>.os-scrollbar,.os-host-transition>.os-scrollbar-corner{-webkit-transition:opacity .3s,visibility .3s,top .3s,right .3s,bottom .3s,left .3s;transition:opacity .3s,visibility .3s,top .3s,right .3s,bottom .3s,left .3s}html.os-html>.os-host>.os-scrollbar{position:absolute;z-index:999999}.os-scrollbar,.os-scrollbar-corner{position:absolute;opacity:1;-ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)';z-index:1}.os-scrollbar-corner{bottom:0;right:0}.os-scrollbar{pointer-events:none}.os-scrollbar-track{pointer-events:auto;position:relative;height:100%;width:100%;padding:0!important;border:0!important}.os-scrollbar-handle{pointer-events:auto;position:absolute;width:100%;height:100%}.os-scrollbar-handle-off,.os-scrollbar-track-off{pointer-events:none}.os-scrollbar.os-scrollbar-unusable,.os-scrollbar.os-scrollbar-unusable *{pointer-events:none!important}.os-scrollbar.os-scrollbar-unusable .os-scrollbar-handle{opacity:0!important}.os-scrollbar-horizontal{bottom:0;left:0}.os-scrollbar-vertical{top:0;right:0}.os-host-rtl>.os-scrollbar-horizontal{right:0}.os-host-rtl>.os-scrollbar-vertical{right:auto;left:0}.os-host-rtl>.os-scrollbar-corner{right:auto;left:0}.os-scrollbar-auto-hidden,.os-padding+.os-scrollbar-corner,.os-host-resize-disabled.os-host-scrollbar-horizontal-hidden>.os-scrollbar-corner,.os-host-scrollbar-horizontal-hidden>.os-scrollbar-horizontal,.os-host-resize-disabled.os-host-scrollbar-vertical-hidden>.os-scrollbar-corner,.os-host-scrollbar-vertical-hidden>.os-scrollbar-vertical,.os-scrollbar-horizontal.os-scrollbar-auto-hidden+.os-scrollbar-vertical+.os-scrollbar-corner,.os-scrollbar-horizontal+.os-scrollbar-vertical.os-scrollbar-auto-hidden+.os-scrollbar-corner,.os-scrollbar-horizontal.os-scrollbar-auto-hidden+.os-scrollbar-vertical.os-scrollbar-auto-hidden+.os-scrollbar-corner{opacity:0;visibility:hidden;pointer-events:none}.os-scrollbar-corner-resize-both{cursor:nwse-resize}.os-host-rtl>.os-scrollbar-corner-resize-both{cursor:nesw-resize}.os-scrollbar-corner-resize-horizontal{cursor:ew-resize}.os-scrollbar-corner-resize-vertical{cursor:ns-resize}.os-dragging .os-scrollbar-corner.os-scrollbar-corner-resize{cursor:default}.os-host-resize-disabled.os-host-scrollbar-horizontal-hidden>.os-scrollbar-vertical{top:0;bottom:0}.os-host-resize-disabled.os-host-scrollbar-vertical-hidden>.os-scrollbar-horizontal,.os-host-rtl.os-host-resize-disabled.os-host-scrollbar-vertical-hidden>.os-scrollbar-horizontal{right:0;left:0}.os-scrollbar:hover,.os-scrollbar-corner.os-scrollbar-corner-resize{opacity:1!important;visibility:visible!important}.os-scrollbar-corner.os-scrollbar-corner-resize{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB3aWR0aD0iMTAiICAgaGVpZ2h0PSIxMCIgICB2ZXJzaW9uPSIxLjEiPiAgPGcgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTEwNDIuMzYyMikiICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmUiPiAgICA8cGF0aCAgICAgICBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eTowLjQ5NDExNzY1O2ZpbGwtcnVsZTpldmVub2RkO3N0cm9rZTpub25lIiAgICAgICBkPSJtIDcuNDI0MjE4NywxMDQyLjM2MjIgYyAtMC43MjM1NzkyLDAgLTEuMzEwMTU2MiwwLjU4NjYgLTEuMzEwMTU2MiwxLjMxMDIgMCwwLjI5OSAwLjEwNDM0MTksMC41NzEgMC4yNzI5NDkyLDAuNzkxNSAwLjIwOTEwMjQsMC4xNDEzIDAuNDY1NjIwNiwwLjIxODQgMC43MzY5NjI5LDAuMjE4NCAwLjcyMzU3OTMsMCAxLjMxMDE1NjMsLTAuNTg2NiAxLjMxMDE1NjMsLTEuMzEwMiAwLC0wLjI3MTMgLTAuMDc3MDkzLC0wLjUyNzggLTAuMjE4MzU5NCwtMC43MzcgLTAuMjIwNDk0MSwtMC4xNjg2IC0wLjQ5MjU0NDMsLTAuMjcyOSAtMC43OTE1NTI4LC0wLjI3MjkgeiBtIDAsMy4wODQzIGMgLTAuNzIzNTc5MiwwIC0xLjMxMDE1NjIsMC41ODY2IC0xLjMxMDE1NjIsMS4zMTAyIDAsMC4yOTkgMC4xMDQzNDE5LDAuNTcxIDAuMjcyOTQ5MiwwLjc5MTUgMC4yMDkxMDI0LDAuMTQxMyAwLjQ2NTYyMDYsMC4yMTg0IDAuNzM2OTYyOSwwLjIxODQgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjYgMS4zMTAxNTYzLC0xLjMxMDIgMCwtMC4yNzEzIC0wLjA3NzA5MywtMC41Mjc4IC0wLjIxODM1OTQsLTAuNzM2OSAtMC4yMjA0OTQxLC0wLjE2ODYgLTAuNDkyNTQ0MywtMC4yNzMgLTAuNzkxNTUyOCwtMC4yNzMgeiBtIC0zLjA4NDMyNjEsMCBjIC0wLjcyMzU3OTMsMCAtMS4zMTAxNTYzLDAuNTg2NiAtMS4zMTAxNTYzLDEuMzEwMiAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MSAwLjI3Mjk0OTIsMC43OTE1IDAuMjA5MTAyNCwwLjE0MTMgMC40NjU2MjA3LDAuMjE4NCAwLjczNjk2MjksMC4yMTg0IDAuNzIzNTc5MywwIDEuMzEwMTU2MywtMC41ODY2IDEuMzEwMTU2MywtMS4zMTAyIDAsLTAuMjcxMyAtMC4wNzcwOTMsLTAuNTI3OCAtMC4yMTgzNTk0LC0wLjczNjkgLTAuMjIwNDk0LC0wLjE2ODYgLTAuNDkyNTQ0MiwtMC4yNzMgLTAuNzkxNTUyNywtMC4yNzMgeiBtIC0zLjAyOTczNjQsMy4wMjk4IEMgMC41ODY1NzY5MywxMDQ4LjQ3NjMgMCwxMDQ5LjA2MjggMCwxMDQ5Ljc4NjQgYyAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MTEgMC4yNzI5NDkyMiwwLjc5MTYgMC4yMDkxMDIyOSwwLjE0MTIgMC40NjU2MjA2NSwwLjIxODMgMC43MzY5NjI4OCwwLjIxODMgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjUgMS4zMTAxNTYzLC0xLjMxMDEgMCwtMC4yNzE0IC0wLjA3NzA5MywtMC41Mjc5IC0wLjIxODM1OTQsLTAuNzM3IC0wLjIyMDQ5NDEsLTAuMTY4NiAtMC40OTI1NDQzLC0wLjI3MjkgLTAuNzkxNTUyOCwtMC4yNzI5IHogbSAzLjAyOTczNjQsMCBjIC0wLjcyMzU3OTMsMCAtMS4zMTAxNTYzLDAuNTg2NSAtMS4zMTAxNTYzLDEuMzEwMSAwLDAuMjk5IDAuMTA0MzQxOSwwLjU3MTEgMC4yNzI5NDkyLDAuNzkxNiAwLjIwOTEwMjQsMC4xNDEyIDAuNDY1NjIwNywwLjIxODMgMC43MzY5NjI5LDAuMjE4MyAwLjcyMzU3OTMsMCAxLjMxMDE1NjMsLTAuNTg2NSAxLjMxMDE1NjMsLTEuMzEwMSAwLC0wLjI3MTQgLTAuMDc3MDkzLC0wLjUyNzkgLTAuMjE4MzU5NCwtMC43MzcgLTAuMjIwNDk0LC0wLjE2ODYgLTAuNDkyNTQ0MiwtMC4yNzI5IC0wLjc5MTU1MjcsLTAuMjcyOSB6IG0gMy4wODQzMjYxLDAgYyAtMC43MjM1NzkyLDAgLTEuMzEwMTU2MiwwLjU4NjUgLTEuMzEwMTU2MiwxLjMxMDEgMCwwLjI5OSAwLjEwNDM0MTksMC41NzExIDAuMjcyOTQ5MiwwLjc5MTYgMC4yMDkxMDI0LDAuMTQxMiAwLjQ2NTYyMDYsMC4yMTgzIDAuNzM2OTYyOSwwLjIxODMgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjUgMS4zMTAxNTYzLC0xLjMxMDEgMCwtMC4yNzE0IC0wLjA3NzA5MywtMC41Mjc5IC0wLjIxODM1OTQsLTAuNzM3IC0wLjIyMDQ5NDEsLTAuMTY4NiAtMC40OTI1NDQzLC0wLjI3MjkgLTAuNzkxNTUyOCwtMC4yNzI5IHoiLz4gIDwvZz4gIDxnICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmUiPiAgICA8cGF0aCAgICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpldmVub2RkO3N0cm9rZTpub25lIiAgICAgICBkPSJtIDguMjE1NzcxNSwwLjI3Mjk0OTIyIGMgMC4xNDEyNjY3LDAuMjA5MTAyMjkgMC4yMTgzNTk0LDAuNDY1NjIwNjUgMC4yMTgzNTk0LDAuNzM2OTYyODggMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MyAtMS4zMTAxNTYzLDEuMzEwMTU2MyAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTk0IDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDc2IC0wLjIwNTUxNzYsLTAuNzk3Nzk2NTkgLTAuNTE4NjAzNSwtMS4wMzcyMDY5OCB6IG0gMCwzLjA4NDMyNjE4IGMgMC4xNDEyNjY3LDAuMjA5MTAyMyAwLjIxODM1OTQsMC40NjU2MjA2IDAuMjE4MzU5NCwwLjczNjk2MjkgMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MiAtMS4zMTAxNTYzLDEuMzEwMTU2MiAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTkzIDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY3IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogbSAtMy4wODQzMjYyLDAgYyAwLjE0MTI2NjcsMC4yMDkxMDIzIDAuMjE4MzU5NCwwLjQ2NTYyMDYgMC4yMTgzNTk0LDAuNzM2OTYyOSAwLDAuNzIzNTc5MyAtMC41ODY1NzcsMS4zMTAxNTYyIC0xLjMxMDE1NjMsMS4zMTAxNTYyIC0wLjI3MTM0MjIsMCAtMC41Mjc4NjA1LC0wLjA3NzA5MyAtMC43MzY5NjI5LC0wLjIxODM1OTMgMC4yMzk0MTA0LDAuMzEzMDg1OSAwLjYxMjYzNjMsMC41MTg2MDM1IDEuMDM3MjA3MSwwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYyLC0wLjU4NjU3NyAxLjMxMDE1NjIsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NSwtMC43OTc3OTY3IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogTSAyLjEwMTcwOSw2LjM4NzAxMTcgYyAwLjE0MTI2NjcsMC4yMDkxMDI0IDAuMjE4MzU5NCwwLjQ2NTYyMDYgMC4yMTgzNTk0LDAuNzM2OTYyOSAwLDAuNzIzNTc5MyAtMC41ODY1NzcsMS4zMTAxNTYzIC0xLjMxMDE1NjMsMS4zMTAxNTYzIC0wLjI3MTM0MjIzLDAgLTAuNTI3ODYwNTksLTAuMDc3MDkzIC0wLjczNjk2Mjg4LC0wLjIxODM1OTQgMC4yMzk0MTAzOSwwLjMxMzA4NTkgMC42MTI2MzYyMiwwLjUxODYwMzUgMS4wMzcyMDY5OCwwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY2IC0wLjUxODYwMzUsLTEuMDM3MjA3IHogbSAzLjAyOTczNjMsMCBjIDAuMTQxMjY2NywwLjIwOTEwMjQgMC4yMTgzNTk0LDAuNDY1NjIwNiAwLjIxODM1OTQsMC43MzY5NjI5IDAsMC43MjM1NzkzIC0wLjU4NjU3NywxLjMxMDE1NjMgLTEuMzEwMTU2MywxLjMxMDE1NjMgLTAuMjcxMzQyMiwwIC0wLjUyNzg2MDUsLTAuMDc3MDkzIC0wLjczNjk2MjksLTAuMjE4MzU5NCAwLjIzOTQxMDQsMC4zMTMwODU5IDAuNjEyNjM2MywwLjUxODYwMzUgMS4wMzcyMDcxLDAuNTE4NjAzNSAwLjcyMzU3OTMsMCAxLjMxMDE1NjIsLTAuNTg2NTc3IDEuMzEwMTU2MiwtMS4zMTAxNTYzIDAsLTAuNDI0NTcwOCAtMC4yMDU1MTc1LC0wLjc5Nzc5NjYgLTAuNTE4NjAzNSwtMS4wMzcyMDcgeiBtIDMuMDg0MzI2MiwwIGMgMC4xNDEyNjY3LDAuMjA5MTAyNCAwLjIxODM1OTQsMC40NjU2MjA2IDAuMjE4MzU5NCwwLjczNjk2MjkgMCwwLjcyMzU3OTMgLTAuNTg2NTc3LDEuMzEwMTU2MyAtMS4zMTAxNTYzLDEuMzEwMTU2MyAtMC4yNzEzNDIzLDAgLTAuNTI3ODYwNSwtMC4wNzcwOTMgLTAuNzM2OTYyOSwtMC4yMTgzNTk0IDAuMjM5NDEwNCwwLjMxMzA4NTkgMC42MTI2MzYyLDAuNTE4NjAzNSAxLjAzNzIwNywwLjUxODYwMzUgMC43MjM1NzkzLDAgMS4zMTAxNTYzLC0wLjU4NjU3NyAxLjMxMDE1NjMsLTEuMzEwMTU2MyAwLC0wLjQyNDU3MDggLTAuMjA1NTE3NiwtMC43OTc3OTY2IC0wLjUxODYwMzUsLTEuMDM3MjA3IHoiIC8+ICA8L2c+PC9zdmc+);background-repeat:no-repeat;background-position:100% 100%;pointer-events:auto!important}.os-host-rtl>.os-scrollbar-corner.os-scrollbar-corner-resize{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.os-host-overflow{overflow:hidden!important}.os-theme-none>.os-scrollbar-horizontal,.os-theme-none>.os-scrollbar-vertical,.os-theme-none>.os-scrollbar-corner{display:none!important}.os-theme-none>.os-scrollbar-corner-resize{display:block!important;min-width:10px;min-height:10px}.os-theme-dark>.os-scrollbar-horizontal,.os-theme-light>.os-scrollbar-horizontal{right:10px;height:10px}.os-theme-dark>.os-scrollbar-vertical,.os-theme-light>.os-scrollbar-vertical{bottom:10px;width:10px}.os-theme-dark.os-host-rtl>.os-scrollbar-horizontal,.os-theme-light.os-host-rtl>.os-scrollbar-horizontal{left:10px;right:0}.os-theme-dark>.os-scrollbar-corner,.os-theme-light>.os-scrollbar-corner{height:10px;width:10px}.os-theme-dark>.os-scrollbar-corner,.os-theme-light>.os-scrollbar-corner{background-color:transparent}.os-theme-dark>.os-scrollbar,.os-theme-light>.os-scrollbar{padding:2px;box-sizing:border-box;background:0 0}.os-theme-dark>.os-scrollbar.os-scrollbar-unusable,.os-theme-light>.os-scrollbar.os-scrollbar-unusable{background:0 0}.os-theme-dark>.os-scrollbar>.os-scrollbar-track,.os-theme-light>.os-scrollbar>.os-scrollbar-track{background:0 0}.os-theme-dark>.os-scrollbar-horizontal>.os-scrollbar-track>.os-scrollbar-handle,.os-theme-light>.os-scrollbar-horizontal>.os-scrollbar-track>.os-scrollbar-handle{min-width:30px}.os-theme-dark>.os-scrollbar-vertical>.os-scrollbar-track>.os-scrollbar-handle,.os-theme-light>.os-scrollbar-vertical>.os-scrollbar-track>.os-scrollbar-handle{min-height:30px}.os-theme-dark.os-host-transition>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle,.os-theme-light.os-host-transition>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle{-webkit-transition:background-color .3s;transition:background-color .3s}.os-theme-dark>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle,.os-theme-light>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle,.os-theme-dark>.os-scrollbar>.os-scrollbar-track,.os-theme-light>.os-scrollbar>.os-scrollbar-track{border-radius:10px}.os-theme-dark>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle{background:rgba(0,0,0,.4)}.os-theme-light>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle{background:rgba(255,255,255,.4)}.os-theme-dark>.os-scrollbar:hover>.os-scrollbar-track>.os-scrollbar-handle{background:rgba(0,0,0,.55)}.os-theme-light>.os-scrollbar:hover>.os-scrollbar-track>.os-scrollbar-handle{background:rgba(255,255,255,.55)}.os-theme-dark>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle.active{background:rgba(0,0,0,.7)}.os-theme-light>.os-scrollbar>.os-scrollbar-track>.os-scrollbar-handle.active{background:rgba(255,255,255,.7)}.os-theme-dark>.os-scrollbar-horizontal .os-scrollbar-handle:before,.os-theme-dark>.os-scrollbar-vertical .os-scrollbar-handle:before,.os-theme-light>.os-scrollbar-horizontal .os-scrollbar-handle:before,.os-theme-light>.os-scrollbar-vertical .os-scrollbar-handle:before{content:'';position:absolute;left:0;right:0;top:0;bottom:0;display:block}.os-theme-dark.os-host-scrollbar-horizontal-hidden>.os-scrollbar-horizontal .os-scrollbar-handle:before,.os-theme-dark.os-host-scrollbar-vertical-hidden>.os-scrollbar-vertical .os-scrollbar-handle:before,.os-theme-light.os-host-scrollbar-horizontal-hidden>.os-scrollbar-horizontal .os-scrollbar-handle:before,.os-theme-light.os-host-scrollbar-vertical-hidden>.os-scrollbar-vertical .os-scrollbar-handle:before{display:none}.os-theme-dark>.os-scrollbar-horizontal .os-scrollbar-handle:before,.os-theme-light>.os-scrollbar-horizontal .os-scrollbar-handle:before{top:-6px;bottom:-2px}.os-theme-dark>.os-scrollbar-vertical .os-scrollbar-handle:before,.os-theme-light>.os-scrollbar-vertical .os-scrollbar-handle:before{left:-6px;right:-2px}.os-host-rtl.os-theme-dark>.os-scrollbar-vertical .os-scrollbar-handle:before,.os-host-rtl.os-theme-light>.os-scrollbar-vertical .os-scrollbar-handle:before{right:-6px;left:-2px} \ No newline at end of file diff --git a/plugins/overlayScrollbars/js/OverlayScrollbars.js b/plugins/overlayScrollbars/js/OverlayScrollbars.js index 6a71816cf..bf7c1f456 100644 --- a/plugins/overlayScrollbars/js/OverlayScrollbars.js +++ b/plugins/overlayScrollbars/js/OverlayScrollbars.js @@ -1,6653 +1,6653 @@ -/*! - * OverlayScrollbars - * https://github.com/KingSora/OverlayScrollbars - * - * Version: 1.11.0 - * - * Copyright KingSora | Rene Haas. - * https://github.com/KingSora - * - * Released under the MIT license. - * Date: 29.02.2020 - */ - -(function (global, factory) { - if (typeof define === 'function' && define.amd) - define(function () { return factory(global, global.document, undefined); }); - else if (typeof module === 'object' && typeof module.exports === 'object') - module.exports = factory(global, global.document, undefined); - else - factory(global, global.document, undefined); -}(typeof window !== 'undefined' ? window : this, - function (window, document, undefined) { - 'use strict'; - var PLUGINNAME = 'OverlayScrollbars'; - var TYPES = { - o: 'object', - f: 'function', - a: 'array', - s: 'string', - b: 'boolean', - n: 'number', - u: 'undefined', - z: 'null' - //d : 'date', - //e : 'error', - //r : 'regexp', - //y : 'symbol' - }; - var LEXICON = { - c: 'class', - s: 'style', - i: 'id', - l: 'length', - p: 'prototype', - ti: 'tabindex', - oH: 'offsetHeight', - cH: 'clientHeight', - sH: 'scrollHeight', - oW: 'offsetWidth', - cW: 'clientWidth', - sW: 'scrollWidth', - hOP: 'hasOwnProperty', - bCR: 'getBoundingClientRect' - }; - var VENDORS = (function () { - //https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix - var jsCache = {}; - var cssCache = {}; - var cssPrefixes = ['-webkit-', '-moz-', '-o-', '-ms-']; - var jsPrefixes = ['WebKit', 'Moz', 'O', 'MS']; - function firstLetterToUpper(str) { - return str.charAt(0).toUpperCase() + str.slice(1); - } - - return { - _cssPrefixes: cssPrefixes, - _jsPrefixes: jsPrefixes, - _cssProperty: function (name) { - var result = cssCache[name]; - - if (cssCache[LEXICON.hOP](name)) - return result; - - var uppercasedName = firstLetterToUpper(name); - var elmStyle = document.createElement('div')[LEXICON.s]; - var resultPossibilities; - var i = 0; - var v; - var currVendorWithoutDashes; - - for (; i < cssPrefixes.length; i++) { - currVendorWithoutDashes = cssPrefixes[i].replace(/-/g, ''); - resultPossibilities = [ - name, //transition - cssPrefixes[i] + name, //-webkit-transition - currVendorWithoutDashes + uppercasedName, //webkitTransition - firstLetterToUpper(currVendorWithoutDashes) + uppercasedName //WebkitTransition - ]; - for (v = 0; v < resultPossibilities[LEXICON.l]; v++) { - if (elmStyle[resultPossibilities[v]] !== undefined) { - result = resultPossibilities[v]; - break; - } - } - } - - cssCache[name] = result; - return result; - }, - _jsAPI: function (name, isInterface, fallback) { - var i = 0; - var result = jsCache[name]; - - if (!jsCache[LEXICON.hOP](name)) { - result = window[name]; - for (; i < jsPrefixes[LEXICON.l]; i++) - result = result || window[(isInterface ? jsPrefixes[i] : jsPrefixes[i].toLowerCase()) + firstLetterToUpper(name)]; - jsCache[name] = result; - } - return result || fallback; - } - - } - })(); - var COMPATIBILITY = (function () { - function windowSize(x) { - return x ? window.innerWidth || document.documentElement[LEXICON.cW] || document.body[LEXICON.cW] : window.innerHeight || document.documentElement[LEXICON.cH] || document.body[LEXICON.cH]; - } - function bind(func, thisObj) { - if (typeof func != TYPES.f) { - throw "Can't bind function!"; - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - //throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - var proto = LEXICON.p; - var aArgs = Array[proto].slice.call(arguments, 2); - var fNOP = function () { }; - var fBound = function () { return func.apply(this instanceof fNOP ? this : thisObj, aArgs.concat(Array[proto].slice.call(arguments))); }; - - if (func[proto]) - fNOP[proto] = func[proto]; // Function.prototype doesn't have a prototype property - fBound[proto] = new fNOP(); - - return fBound; - } - - return { - /** - * Gets the current window width. - * @returns {Number|number} The current window width in pixel. - */ - wW: bind(windowSize, 0, true), - - /** - * Gets the current window height. - * @returns {Number|number} The current window height in pixel. - */ - wH: bind(windowSize, 0), - - /** - * Gets the MutationObserver Object or undefined if not supported. - * @returns {MutationObserver|*|undefined} The MutationsObserver Object or undefined. - */ - mO: bind(VENDORS._jsAPI, 0, 'MutationObserver', true), - - /** - * Gets the ResizeObserver Object or undefined if not supported. - * @returns {MutationObserver|*|undefined} The ResizeObserver Object or undefined. - */ - rO: bind(VENDORS._jsAPI, 0, 'ResizeObserver', true), - - /** - * Gets the RequestAnimationFrame method or it's corresponding polyfill. - * @returns {*|Function} The RequestAnimationFrame method or it's corresponding polyfill. - */ - rAF: bind(VENDORS._jsAPI, 0, 'requestAnimationFrame', false, function (func) { return window.setTimeout(func, 1000 / 60); }), - - /** - * Gets the CancelAnimationFrame method or it's corresponding polyfill. - * @returns {*|Function} The CancelAnimationFrame method or it's corresponding polyfill. - */ - cAF: bind(VENDORS._jsAPI, 0, 'cancelAnimationFrame', false, function (id) { return window.clearTimeout(id); }), - - /** - * Gets the current time. - * @returns {number} The current time. - */ - now: function () { - return Date.now && Date.now() || new Date().getTime(); - }, - - /** - * Stops the propagation of the given event. - * @param event The event of which the propagation shall be stoped. - */ - stpP: function (event) { - if (event.stopPropagation) - event.stopPropagation(); - else - event.cancelBubble = true; - }, - - /** - * Prevents the default action of the given event. - * @param event The event of which the default action shall be prevented. - */ - prvD: function (event) { - if (event.preventDefault && event.cancelable) - event.preventDefault(); - else - event.returnValue = false; - }, - - /** - * Gets the pageX and pageY values of the given mouse event. - * @param event The mouse event of which the pageX and pageX shall be got. - * @returns {{x: number, y: number}} x = pageX value, y = pageY value. - */ - page: function (event) { - event = event.originalEvent || event; - - var strPage = 'page'; - var strClient = 'client'; - var strX = 'X'; - var strY = 'Y'; - var target = event.target || event.srcElement || document; - var eventDoc = target.ownerDocument || document; - var doc = eventDoc.documentElement; - var body = eventDoc.body; - - //if touch event return return pageX/Y of it - if (event.touches !== undefined) { - var touch = event.touches[0]; - return { - x: touch[strPage + strX], - y: touch[strPage + strY] - } - } - - // Calculate pageX/Y if not native supported - if (!event[strPage + strX] && event[strClient + strX] && event[strClient + strX] != null) { - - return { - x: event[strClient + strX] + - (doc && doc.scrollLeft || body && body.scrollLeft || 0) - - (doc && doc.clientLeft || body && body.clientLeft || 0), - y: event[strClient + strY] + - (doc && doc.scrollTop || body && body.scrollTop || 0) - - (doc && doc.clientTop || body && body.clientTop || 0) - } - } - return { - x: event[strPage + strX], - y: event[strPage + strY] - }; - }, - - /** - * Gets the clicked mouse button of the given mouse event. - * @param event The mouse event of which the clicked button shal be got. - * @returns {number} The number of the clicked mouse button. (0 : none | 1 : leftButton | 2 : middleButton | 3 : rightButton) - */ - mBtn: function (event) { - var button = event.button; - if (!event.which && button !== undefined) - return (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); - else - return event.which; - }, - - /** - * Checks whether a item is in the given array and returns its index. - * @param item The item of which the position in the array shall be determined. - * @param arr The array. - * @returns {number} The zero based index of the item or -1 if the item isn't in the array. - */ - inA: function (item, arr) { - for (var i = 0; i < arr[LEXICON.l]; i++) - //Sometiems in IE a "SCRIPT70" Permission denied error occurs if HTML elements in a iFrame are compared - try { - if (arr[i] === item) - return i; - } - catch (e) { } - return -1; - }, - - /** - * Returns true if the given value is a array. - * @param arr The potential array. - * @returns {boolean} True if the given value is a array, false otherwise. - */ - isA: function (arr) { - var def = Array.isArray; - return def ? def(arr) : this.type(arr) == TYPES.a; - }, - - /** - * Determine the internal JavaScript [[Class]] of the given object. - * @param obj The object of which the type shall be determined. - * @returns {string} The type of the given object. - */ - type: function (obj) { - if (obj === undefined) - return obj + ''; - if (obj === null) - return obj + ''; - return Object[LEXICON.p].toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase(); - }, - - - bind: bind - - /** - * Gets the vendor-prefixed CSS property by the given name. - * For example the given name is "transform" and you're using a old Firefox browser then the returned value would be "-moz-transform". - * If the browser doesn't need a vendor-prefix, then the returned string is the given name. - * If the browser doesn't support the given property name at all (not even with a vendor-prefix) the returned value is null. - * @param propName The unprefixed CSS property name. - * @returns {string|null} The vendor-prefixed CSS property or null if the browser doesn't support the given CSS property. - - cssProp: function(propName) { - return VENDORS._cssProperty(propName); - } - */ - } - })(); - - var MATH = Math; - var JQUERY = window.jQuery; - var EASING = (function () { - var _easingsMath = { - p: MATH.PI, - c: MATH.cos, - s: MATH.sin, - w: MATH.pow, - t: MATH.sqrt, - n: MATH.asin, - a: MATH.abs, - o: 1.70158 - }; - - /* - x : current percent (0 - 1), - t : current time (duration * percent), - b : start value (from), - c : end value (to), - d : duration - - easingName : function(x, t, b, c, d) { return easedValue; } - */ - - return { - swing: function (x, t, b, c, d) { - return 0.5 - _easingsMath.c(x * _easingsMath.p) / 2; - }, - linear: function (x, t, b, c, d) { - return x; - }, - easeInQuad: function (x, t, b, c, d) { - return c * (t /= d) * t + b; - }, - easeOutQuad: function (x, t, b, c, d) { - return -c * (t /= d) * (t - 2) + b; - }, - easeInOutQuad: function (x, t, b, c, d) { - return ((t /= d / 2) < 1) ? c / 2 * t * t + b : -c / 2 * ((--t) * (t - 2) - 1) + b; - }, - easeInCubic: function (x, t, b, c, d) { - return c * (t /= d) * t * t + b; - }, - easeOutCubic: function (x, t, b, c, d) { - return c * ((t = t / d - 1) * t * t + 1) + b; - }, - easeInOutCubic: function (x, t, b, c, d) { - return ((t /= d / 2) < 1) ? c / 2 * t * t * t + b : c / 2 * ((t -= 2) * t * t + 2) + b; - }, - easeInQuart: function (x, t, b, c, d) { - return c * (t /= d) * t * t * t + b; - }, - easeOutQuart: function (x, t, b, c, d) { - return -c * ((t = t / d - 1) * t * t * t - 1) + b; - }, - easeInOutQuart: function (x, t, b, c, d) { - return ((t /= d / 2) < 1) ? c / 2 * t * t * t * t + b : -c / 2 * ((t -= 2) * t * t * t - 2) + b; - }, - easeInQuint: function (x, t, b, c, d) { - return c * (t /= d) * t * t * t * t + b; - }, - easeOutQuint: function (x, t, b, c, d) { - return c * ((t = t / d - 1) * t * t * t * t + 1) + b; - }, - easeInOutQuint: function (x, t, b, c, d) { - return ((t /= d / 2) < 1) ? c / 2 * t * t * t * t * t + b : c / 2 * ((t -= 2) * t * t * t * t + 2) + b; - }, - easeInSine: function (x, t, b, c, d) { - return -c * _easingsMath.c(t / d * (_easingsMath.p / 2)) + c + b; - }, - easeOutSine: function (x, t, b, c, d) { - return c * _easingsMath.s(t / d * (_easingsMath.p / 2)) + b; - }, - easeInOutSine: function (x, t, b, c, d) { - return -c / 2 * (_easingsMath.c(_easingsMath.p * t / d) - 1) + b; - }, - easeInExpo: function (x, t, b, c, d) { - return (t == 0) ? b : c * _easingsMath.w(2, 10 * (t / d - 1)) + b; - }, - easeOutExpo: function (x, t, b, c, d) { - return (t == d) ? b + c : c * (-_easingsMath.w(2, -10 * t / d) + 1) + b; - }, - easeInOutExpo: function (x, t, b, c, d) { - if (t == 0) return b; - if (t == d) return b + c; - if ((t /= d / 2) < 1) return c / 2 * _easingsMath.w(2, 10 * (t - 1)) + b; - return c / 2 * (-_easingsMath.w(2, -10 * --t) + 2) + b; - }, - easeInCirc: function (x, t, b, c, d) { - return -c * (_easingsMath.t(1 - (t /= d) * t) - 1) + b; - }, - easeOutCirc: function (x, t, b, c, d) { - return c * _easingsMath.t(1 - (t = t / d - 1) * t) + b; - }, - easeInOutCirc: function (x, t, b, c, d) { - return ((t /= d / 2) < 1) ? -c / 2 * (_easingsMath.t(1 - t * t) - 1) + b : c / 2 * (_easingsMath.t(1 - (t -= 2) * t) + 1) + b; - }, - easeInElastic: function (x, t, b, c, d) { - var s = _easingsMath.o; var p = 0; var a = c; - if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; - if (a < _easingsMath.a(c)) { a = c; s = p / 4; } - else s = p / (2 * _easingsMath.p) * _easingsMath.n(c / a); - return -(a * _easingsMath.w(2, 10 * (t -= 1)) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p)) + b; - }, - easeOutElastic: function (x, t, b, c, d) { - var s = _easingsMath.o; var p = 0; var a = c; - if (t == 0) return b; - if ((t /= d) == 1) return b + c; - if (!p) p = d * .3; - if (a < _easingsMath.a(c)) { a = c; s = p / 4; } - else s = p / (2 * _easingsMath.p) * _easingsMath.n(c / a); - return a * _easingsMath.w(2, -10 * t) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p) + c + b; - }, - easeInOutElastic: function (x, t, b, c, d) { - var s = _easingsMath.o; var p = 0; var a = c; - if (t == 0) return b; - if ((t /= d / 2) == 2) return b + c; - if (!p) p = d * (.3 * 1.5); - if (a < _easingsMath.a(c)) { a = c; s = p / 4; } - else s = p / (2 * _easingsMath.p) * _easingsMath.n(c / a); - if (t < 1) return -.5 * (a * _easingsMath.w(2, 10 * (t -= 1)) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p)) + b; - return a * _easingsMath.w(2, -10 * (t -= 1)) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p) * .5 + c + b; - }, - easeInBack: function (x, t, b, c, d, s) { - s = s || _easingsMath.o; - return c * (t /= d) * t * ((s + 1) * t - s) + b; - }, - easeOutBack: function (x, t, b, c, d, s) { - s = s || _easingsMath.o; - return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; - }, - easeInOutBack: function (x, t, b, c, d, s) { - s = s || _easingsMath.o; - return ((t /= d / 2) < 1) ? c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b : c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; - }, - easeInBounce: function (x, t, b, c, d) { - return c - this.easeOutBounce(x, d - t, 0, c, d) + b; - }, - easeOutBounce: function (x, t, b, c, d) { - var o = 7.5625; - if ((t /= d) < (1 / 2.75)) { - return c * (o * t * t) + b; - } else if (t < (2 / 2.75)) { - return c * (o * (t -= (1.5 / 2.75)) * t + .75) + b; - } else if (t < (2.5 / 2.75)) { - return c * (o * (t -= (2.25 / 2.75)) * t + .9375) + b; - } else { - return c * (o * (t -= (2.625 / 2.75)) * t + .984375) + b; - } - }, - easeInOutBounce: function (x, t, b, c, d) { - return (t < d / 2) ? this.easeInBounce(x, t * 2, 0, c, d) * .5 + b : this.easeOutBounce(x, t * 2 - d, 0, c, d) * .5 + c * .5 + b; - } - }; - /* - * - * TERMS OF USE - EASING EQUATIONS - * - * Open source under the BSD License. - * - * Copyright © 2001 Robert Penner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * Neither the name of the author nor the names of contributors may be used to endorse - * or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - })(); - var FRAMEWORK = (function () { - var _rnothtmlwhite = (/[^\x20\t\r\n\f]+/g); - var _strSpace = ' '; - var _strEmpty = ''; - var _strScrollLeft = 'scrollLeft'; - var _strScrollTop = 'scrollTop'; - var _animations = []; - var _type = COMPATIBILITY.type; - var _cssNumber = { - animationIterationCount: true, - columnCount: true, - fillOpacity: true, - flexGrow: true, - flexShrink: true, - fontWeight: true, - lineHeight: true, - opacity: true, - order: true, - orphans: true, - widows: true, - zIndex: true, - zoom: true - }; - - function extend() { - var src, copyIsArray, copy, name, options, clone, target = arguments[0] || {}, - i = 1, - length = arguments[LEXICON.l], - deep = false; - - // Handle a deep copy situation - if (_type(target) == TYPES.b) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if (_type(target) != TYPES.o && !_type(target) == TYPES.f) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if (length === i) { - target = FakejQuery; - --i; - } - - for (; i < length; i++) { - // Only deal with non-null/undefined values - if ((options = arguments[i]) != null) { - // Extend the base object - for (name in options) { - src = target[name]; - copy = options[name]; - - // Prevent never-ending loop - if (target === copy) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if (deep && copy && (isPlainObject(copy) || (copyIsArray = COMPATIBILITY.isA(copy)))) { - if (copyIsArray) { - copyIsArray = false; - clone = src && COMPATIBILITY.isA(src) ? src : []; - - } else { - clone = src && isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[name] = extend(deep, clone, copy); - - // Don't bring in undefined values - } else if (copy !== undefined) { - target[name] = copy; - } - } - } - } - - // Return the modified object - return target; - }; - - function inArray(item, arr, fromIndex) { - for (var i = fromIndex || 0; i < arr[LEXICON.l]; i++) - if (arr[i] === item) - return i; - return -1; - } - - function isFunction(obj) { - return _type(obj) == TYPES.f; - }; - - function isEmptyObject(obj) { - for (var name in obj) - return false; - return true; - }; - - function isPlainObject(obj) { - if (!obj || _type(obj) != TYPES.o) - return false; - - var key; - var proto = LEXICON.p; - var hasOwnProperty = Object[proto].hasOwnProperty; - var hasOwnConstructor = hasOwnProperty.call(obj, 'constructor'); - var hasIsPrototypeOf = obj.constructor && obj.constructor[proto] && hasOwnProperty.call(obj.constructor[proto], 'isPrototypeOf'); - - if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { - return false; - } - - - for (key in obj) { /**/ } - - return _type(key) == TYPES.u || hasOwnProperty.call(obj, key); - }; - - function each(obj, callback) { - var i = 0; - - if (isArrayLike(obj)) { - for (; i < obj[LEXICON.l]; i++) { - if (callback.call(obj[i], i, obj[i]) === false) - break; - } - } - else { - for (i in obj) { - if (callback.call(obj[i], i, obj[i]) === false) - break; - } - } - - return obj; - }; - - function isArrayLike(obj) { - var length = !!obj && [LEXICON.l] in obj && obj[LEXICON.l]; - var t = _type(obj); - return isFunction(t) ? false : (t == TYPES.a || length === 0 || _type(length) == TYPES.n && length > 0 && (length - 1) in obj); - } - - function stripAndCollapse(value) { - var tokens = value.match(_rnothtmlwhite) || []; - return tokens.join(_strSpace); - } - - function matches(elem, selector) { - var nodeList = (elem.parentNode || document).querySelectorAll(selector) || []; - var i = nodeList[LEXICON.l]; - - while (i--) - if (nodeList[i] == elem) - return true; - - return false; - } - - function insertAdjacentElement(el, strategy, child) { - if (_type(child) == TYPES.a) { - for (var i = 0; i < child[LEXICON.l]; i++) - insertAdjacentElement(el, strategy, child[i]); - } - else if (_type(child) == TYPES.s) - el.insertAdjacentHTML(strategy, child); - else - el.insertAdjacentElement(strategy, child.nodeType ? child : child[0]); - } - - function setCSSVal(el, prop, val) { - try { - if (el[LEXICON.s][prop] !== undefined) - el[LEXICON.s][prop] = parseCSSVal(prop, val); - } catch (e) { } - } - - function parseCSSVal(prop, val) { - if (!_cssNumber[prop.toLowerCase()] && _type(val) == TYPES.n) - val += 'px'; - return val; - } - - function startNextAnimationInQ(animObj, removeFromQ) { - var index; - var nextAnim; - if (removeFromQ !== false) - animObj.q.splice(0, 1); - if (animObj.q[LEXICON.l] > 0) { - nextAnim = animObj.q[0]; - animate(animObj.el, nextAnim.props, nextAnim.duration, nextAnim.easing, nextAnim.complete, true); - } - else { - index = inArray(animObj, _animations); - if (index > -1) - _animations.splice(index, 1); - } - } - - function setAnimationValue(el, prop, value) { - if (prop === _strScrollLeft || prop === _strScrollTop) - el[prop] = value; - else - setCSSVal(el, prop, value); - } - - function animate(el, props, options, easing, complete, guaranteedNext) { - var hasOptions = isPlainObject(options); - var from = {}; - var to = {}; - var i = 0; - var key; - var animObj; - var start; - var progress; - var step; - var specialEasing; - var duration; - if (hasOptions) { - easing = options.easing; - start = options.start; - progress = options.progress; - step = options.step; - specialEasing = options.specialEasing; - complete = options.complete; - duration = options.duration; - } - else - duration = options; - specialEasing = specialEasing || {}; - duration = duration || 400; - easing = easing || 'swing'; - guaranteedNext = guaranteedNext || false; - - for (; i < _animations[LEXICON.l]; i++) { - if (_animations[i].el === el) { - animObj = _animations[i]; - break; - } - } - - if (!animObj) { - animObj = { - el: el, - q: [] - }; - _animations.push(animObj); - } - - for (key in props) { - if (key === _strScrollLeft || key === _strScrollTop) - from[key] = el[key]; - else - from[key] = FakejQuery(el).css(key); - } - - for (key in from) { - if (from[key] !== props[key] && props[key] !== undefined) - to[key] = props[key]; - } - - if (!isEmptyObject(to)) { - var timeNow; - var end; - var percent; - var fromVal; - var toVal; - var easedVal; - var timeStart; - var frame; - var elapsed; - var qPos = guaranteedNext ? 0 : inArray(qObj, animObj.q); - var qObj = { - props: to, - duration: hasOptions ? options : duration, - easing: easing, - complete: complete - }; - if (qPos === -1) { - qPos = animObj.q[LEXICON.l]; - animObj.q.push(qObj); - } - - if (qPos === 0) { - if (duration > 0) { - timeStart = COMPATIBILITY.now(); - frame = function () { - timeNow = COMPATIBILITY.now(); - elapsed = (timeNow - timeStart); - end = qObj.stop || elapsed >= duration; - percent = 1 - ((MATH.max(0, timeStart + duration - timeNow) / duration) || 0); - - for (key in to) { - fromVal = parseFloat(from[key]); - toVal = parseFloat(to[key]); - easedVal = (toVal - fromVal) * EASING[specialEasing[key] || easing](percent, percent * duration, 0, 1, duration) + fromVal; - setAnimationValue(el, key, easedVal); - if (isFunction(step)) { - step(easedVal, { - elem: el, - prop: key, - start: fromVal, - now: easedVal, - end: toVal, - pos: percent, - options: { - easing: easing, - speacialEasing: specialEasing, - duration: duration, - complete: complete, - step: step - }, - startTime: timeStart - }); - } - } - - if (isFunction(progress)) - progress({}, percent, MATH.max(0, duration - elapsed)); - - if (end) { - startNextAnimationInQ(animObj); - if (isFunction(complete)) - complete(); - } - else - qObj.frame = COMPATIBILITY.rAF()(frame); - }; - qObj.frame = COMPATIBILITY.rAF()(frame); - } - else { - for (key in to) - setAnimationValue(el, key, to[key]); - startNextAnimationInQ(animObj); - } - } - } - else if (guaranteedNext) - startNextAnimationInQ(animObj); - } - - function stop(el, clearQ, jumpToEnd) { - var animObj; - var qObj; - var key; - var i = 0; - for (; i < _animations[LEXICON.l]; i++) { - animObj = _animations[i]; - if (animObj.el === el) { - if (animObj.q[LEXICON.l] > 0) { - qObj = animObj.q[0]; - qObj.stop = true; - COMPATIBILITY.cAF()(qObj.frame); - animObj.q.splice(0, 1); - - if (jumpToEnd) - for (key in qObj.props) - setAnimationValue(el, key, qObj.props[key]); - - if (clearQ) - animObj.q = []; - else - startNextAnimationInQ(animObj, false); - } - break; - } - } - } - - function elementIsVisible(el) { - return !!(el[LEXICON.oW] || el[LEXICON.oH] || el.getClientRects()[LEXICON.l]); - } - - function FakejQuery(selector) { - if (arguments[LEXICON.l] === 0) - return this; - - var base = new FakejQuery(); - var elements = selector; - var i = 0; - var elms; - var el; - - if (_type(selector) == TYPES.s) { - elements = []; - if (selector.charAt(0) === '<') { - el = document.createElement('div'); - el.innerHTML = selector; - elms = el.children; - } - else { - elms = document.querySelectorAll(selector); - } - - for (; i < elms[LEXICON.l]; i++) - elements.push(elms[i]); - } - - if (elements) { - if (_type(elements) != TYPES.s && (!isArrayLike(elements) || elements === window || elements === elements.self)) - elements = [elements]; - - for (i = 0; i < elements[LEXICON.l]; i++) - base[i] = elements[i]; - - base[LEXICON.l] = elements[LEXICON.l]; - } - - return base; - }; - - FakejQuery[LEXICON.p] = { - - //EVENTS: - - on: function (eventName, handler) { - eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [_strEmpty]; - - var eventNameLength = eventName[LEXICON.l]; - var i = 0; - var el; - return this.each(function () { - el = this; - try { - if (el.addEventListener) { - for (; i < eventNameLength; i++) - el.addEventListener(eventName[i], handler); - } - else if (el.detachEvent) { - for (; i < eventNameLength; i++) - el.attachEvent('on' + eventName[i], handler); - } - } catch (e) { } - }); - }, - - off: function (eventName, handler) { - eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [_strEmpty]; - - var eventNameLength = eventName[LEXICON.l]; - var i = 0; - var el; - return this.each(function () { - el = this; - try { - if (el.removeEventListener) { - for (; i < eventNameLength; i++) - el.removeEventListener(eventName[i], handler); - } - else if (el.detachEvent) { - for (; i < eventNameLength; i++) - el.detachEvent('on' + eventName[i], handler); - } - } catch (e) { } - }); - }, - - one: function (eventName, handler) { - eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [_strEmpty]; - return this.each(function () { - var el = FakejQuery(this); - FakejQuery.each(eventName, function (i, oneEventName) { - var oneHandler = function (e) { - handler.call(this, e); - el.off(oneEventName, oneHandler); - }; - el.on(oneEventName, oneHandler); - }); - }); - }, - - trigger: function (eventName) { - var el; - var event; - return this.each(function () { - el = this; - if (document.createEvent) { - event = document.createEvent('HTMLEvents'); - event.initEvent(eventName, true, false); - el.dispatchEvent(event); - } - else { - el.fireEvent('on' + eventName); - } - }); - }, - - //DOM NODE INSERTING / REMOVING: - - append: function (child) { - return this.each(function () { insertAdjacentElement(this, 'beforeend', child); }); - }, - - prepend: function (child) { - return this.each(function () { insertAdjacentElement(this, 'afterbegin', child); }); - }, - - before: function (child) { - return this.each(function () { insertAdjacentElement(this, 'beforebegin', child); }); - }, - - after: function (child) { - return this.each(function () { insertAdjacentElement(this, 'afterend', child); }); - }, - - remove: function () { - return this.each(function () { - var el = this; - var parentNode = el.parentNode; - if (parentNode != null) - parentNode.removeChild(el); - }); - }, - - unwrap: function () { - var parents = []; - var i; - var el; - var parent; - - this.each(function () { - parent = this.parentNode; - if (inArray(parent, parents) === - 1) - parents.push(parent); - }); - - for (i = 0; i < parents[LEXICON.l]; i++) { - el = parents[i]; - parent = el.parentNode; - while (el.firstChild) - parent.insertBefore(el.firstChild, el); - parent.removeChild(el); - } - - return this; - }, - - wrapAll: function (wrapperHTML) { - var i; - var nodes = this; - var wrapper = FakejQuery(wrapperHTML)[0]; - var deepest = wrapper; - var parent = nodes[0].parentNode; - var previousSibling = nodes[0].previousSibling; - while (deepest.childNodes[LEXICON.l] > 0) - deepest = deepest.childNodes[0]; - - for (i = 0; nodes[LEXICON.l] - i; deepest.firstChild === nodes[0] && i++) - deepest.appendChild(nodes[i]); - - var nextSibling = previousSibling ? previousSibling.nextSibling : parent.firstChild; - parent.insertBefore(wrapper, nextSibling); - - return this; - }, - - wrapInner: function (wrapperHTML) { - return this.each(function () { - var el = FakejQuery(this); - var contents = el.contents(); - - if (contents[LEXICON.l]) - contents.wrapAll(wrapperHTML); - else - el.append(wrapperHTML); - }); - }, - - wrap: function (wrapperHTML) { - return this.each(function () { FakejQuery(this).wrapAll(wrapperHTML); }); - }, - - - //DOM NODE MANIPULATION / INFORMATION: - - css: function (styles, val) { - var el; - var key; - var cptStyle; - var getCptStyle = window.getComputedStyle; - if (_type(styles) == TYPES.s) { - if (val === undefined) { - el = this[0]; - cptStyle = getCptStyle ? getCptStyle(el, null) : el.currentStyle[styles]; - - //https://bugzilla.mozilla.org/show_bug.cgi?id=548397 can be null sometimes if iframe with display: none (firefox only!) - return getCptStyle ? cptStyle != null ? cptStyle.getPropertyValue(styles) : el[LEXICON.s][styles] : cptStyle; - } - else { - return this.each(function () { - setCSSVal(this, styles, val); - }); - } - } - else { - return this.each(function () { - for (key in styles) - setCSSVal(this, key, styles[key]); - }); - } - }, - - hasClass: function (className) { - var elem, i = 0; - var classNamePrepared = _strSpace + className + _strSpace; - var classList; - - while ((elem = this[i++])) { - classList = elem.classList; - if (classList && classList.contains(className)) - return true; - else if (elem.nodeType === 1 && (_strSpace + stripAndCollapse(elem.className + _strEmpty) + _strSpace).indexOf(classNamePrepared) > -1) - return true; - } - - return false; - }, - - addClass: function (className) { - var classes; - var elem; - var cur; - var curValue; - var clazz; - var finalValue; - var supportClassList; - var elmClassList; - var i = 0; - var v = 0; - - if (className) { - classes = className.match(_rnothtmlwhite) || []; - - while ((elem = this[i++])) { - elmClassList = elem.classList; - if (supportClassList === undefined) - supportClassList = elmClassList !== undefined; - - if (supportClassList) { - while ((clazz = classes[v++])) - elmClassList.add(clazz); - } - else { - curValue = elem.className + _strEmpty; - cur = elem.nodeType === 1 && (_strSpace + stripAndCollapse(curValue) + _strSpace); - - if (cur) { - while ((clazz = classes[v++])) - if (cur.indexOf(_strSpace + clazz + _strSpace) < 0) - cur += clazz + _strSpace; - - finalValue = stripAndCollapse(cur); - if (curValue !== finalValue) - elem.className = finalValue; - } - } - } - } - - return this; - }, - - removeClass: function (className) { - var classes; - var elem; - var cur; - var curValue; - var clazz; - var finalValue; - var supportClassList; - var elmClassList; - var i = 0; - var v = 0; - - if (className) { - classes = className.match(_rnothtmlwhite) || []; - - while ((elem = this[i++])) { - elmClassList = elem.classList; - if (supportClassList === undefined) - supportClassList = elmClassList !== undefined; - - if (supportClassList) { - while ((clazz = classes[v++])) - elmClassList.remove(clazz); - } - else { - curValue = elem.className + _strEmpty; - cur = elem.nodeType === 1 && (_strSpace + stripAndCollapse(curValue) + _strSpace); - - if (cur) { - while ((clazz = classes[v++])) - while (cur.indexOf(_strSpace + clazz + _strSpace) > -1) - cur = cur.replace(_strSpace + clazz + _strSpace, _strSpace); - - finalValue = stripAndCollapse(cur); - if (curValue !== finalValue) - elem.className = finalValue; - } - } - } - } - - return this; - }, - - hide: function () { - return this.each(function () { this[LEXICON.s].display = 'none'; }); - }, - - show: function () { - return this.each(function () { this[LEXICON.s].display = 'block'; }); - }, - - attr: function (attrName, value) { - var i = 0; - var el; - while (el = this[i++]) { - if (value === undefined) - return el.getAttribute(attrName); - el.setAttribute(attrName, value); - } - return this; - }, - - removeAttr: function (attrName) { - return this.each(function () { this.removeAttribute(attrName); }); - }, - - offset: function () { - var el = this[0]; - var rect = el[LEXICON.bCR](); - var scrollLeft = window.pageXOffset || document.documentElement[_strScrollLeft]; - var scrollTop = window.pageYOffset || document.documentElement[_strScrollTop]; - return { - top: rect.top + scrollTop, - left: rect.left + scrollLeft - }; - }, - - position: function () { - var el = this[0]; - return { - top: el.offsetTop, - left: el.offsetLeft - }; - }, - - scrollLeft: function (value) { - var i = 0; - var el; - while (el = this[i++]) { - if (value === undefined) - return el[_strScrollLeft]; - el[_strScrollLeft] = value; - } - return this; - }, - - scrollTop: function (value) { - var i = 0; - var el; - while (el = this[i++]) { - if (value === undefined) - return el[_strScrollTop]; - el[_strScrollTop] = value; - } - return this; - }, - - val: function (value) { - var el = this[0]; - if (!value) - return el.value; - el.value = value; - return this; - }, - - - //DOM TRAVERSAL / FILTERING: - - first: function () { - return this.eq(0); - }, - - last: function () { - return this.eq(-1); - }, - - eq: function (index) { - return FakejQuery(this[index >= 0 ? index : this[LEXICON.l] + index]); - }, - - find: function (selector) { - var children = []; - var i; - this.each(function () { - var el = this; - var ch = el.querySelectorAll(selector); - for (i = 0; i < ch[LEXICON.l]; i++) - children.push(ch[i]); - }); - return FakejQuery(children); - }, - - children: function (selector) { - var children = []; - var el; - var ch; - var i; - - this.each(function () { - ch = this.children; - for (i = 0; i < ch[LEXICON.l]; i++) { - el = ch[i]; - if (selector) { - if ((el.matches && el.matches(selector)) || matches(el, selector)) - children.push(el); - } - else - children.push(el); - } - }); - return FakejQuery(children); - }, - - parent: function (selector) { - var parents = []; - var parent; - this.each(function () { - parent = this.parentNode; - if (selector ? FakejQuery(parent).is(selector) : true) - parents.push(parent); - }); - return FakejQuery(parents); - }, - - is: function (selector) { - - var el; - var i; - for (i = 0; i < this[LEXICON.l]; i++) { - el = this[i]; - if (selector === ':visible') - return elementIsVisible(el); - if (selector === ':hidden') - return !elementIsVisible(el); - if ((el.matches && el.matches(selector)) || matches(el, selector)) - return true; - } - return false; - }, - - contents: function () { - var contents = []; - var childs; - var i; - - this.each(function () { - childs = this.childNodes; - for (i = 0; i < childs[LEXICON.l]; i++) - contents.push(childs[i]); - }); - - return FakejQuery(contents); - }, - - each: function (callback) { - return each(this, callback); - }, - - - //ANIMATION: - - animate: function (props, duration, easing, complete) { - return this.each(function () { animate(this, props, duration, easing, complete); }); - }, - - stop: function (clearQ, jump) { - return this.each(function () { stop(this, clearQ, jump); }); - } - }; - - extend(FakejQuery, { - extend: extend, - inArray: inArray, - isEmptyObject: isEmptyObject, - isPlainObject: isPlainObject, - each: each - }); - - return FakejQuery; - })(); - var INSTANCES = (function () { - var _targets = []; - var _instancePropertyString = '__overlayScrollbars__'; - - /** - * Register, unregister or get a certain (or all) instances. - * Register: Pass the target and the instance. - * Unregister: Pass the target and null. - * Get Instance: Pass the target from which the instance shall be got. - * Get Targets: Pass no arguments. - * @param target The target to which the instance shall be registered / from which the instance shall be unregistered / the instance shall be got - * @param instance The instance. - * @returns {*|void} Returns the instance from the given target. - */ - return function (target, instance) { - var argLen = arguments[LEXICON.l]; - if (argLen < 1) { - //return all targets - return _targets; - } - else { - if (instance) { - //register instance - target[_instancePropertyString] = instance; - _targets.push(target); - } - else { - var index = COMPATIBILITY.inA(target, _targets); - if (index > -1) { - if (argLen > 1) { - //unregister instance - delete target[_instancePropertyString]; - _targets.splice(index, 1); - } - else { - //get instance from target - return _targets[index][_instancePropertyString]; - } - } - } - } - } - })(); - var PLUGIN = (function () { - var _plugin; - var _pluginsGlobals; - var _pluginsAutoUpdateLoop; - var _pluginsExtensions = []; - var _pluginsOptions = (function () { - var type = COMPATIBILITY.type; - var possibleTemplateTypes = [ - TYPES.b, //boolean - TYPES.n, //number - TYPES.s, //string - TYPES.a, //array - TYPES.o, //object - TYPES.f, //function - TYPES.z //null - ]; - var restrictedStringsSplit = ' '; - var restrictedStringsPossibilitiesSplit = ':'; - var classNameAllowedValues = [TYPES.z, TYPES.s]; - var numberAllowedValues = TYPES.n; - var booleanNullAllowedValues = [TYPES.z, TYPES.b]; - var booleanTrueTemplate = [true, TYPES.b]; - var booleanFalseTemplate = [false, TYPES.b]; - var callbackTemplate = [null, [TYPES.z, TYPES.f]]; - var inheritedAttrsTemplate = [['style', 'class'], [TYPES.s, TYPES.a, TYPES.z]]; - var resizeAllowedValues = 'n:none b:both h:horizontal v:vertical'; - var overflowBehaviorAllowedValues = 'v-h:visible-hidden v-s:visible-scroll s:scroll h:hidden'; - var scrollbarsVisibilityAllowedValues = 'v:visible h:hidden a:auto'; - var scrollbarsAutoHideAllowedValues = 'n:never s:scroll l:leave m:move'; - var optionsDefaultsAndTemplate = { - className: ['os-theme-dark', classNameAllowedValues], //null || string - resize: ['none', resizeAllowedValues], //none || both || horizontal || vertical || n || b || h || v - sizeAutoCapable: booleanTrueTemplate, //true || false - clipAlways: booleanTrueTemplate, //true || false - normalizeRTL: booleanTrueTemplate, //true || false - paddingAbsolute: booleanFalseTemplate, //true || false - autoUpdate: [null, booleanNullAllowedValues], //true || false || null - autoUpdateInterval: [33, numberAllowedValues], //number - nativeScrollbarsOverlaid: { - showNativeScrollbars: booleanFalseTemplate, //true || false - initialize: booleanTrueTemplate //true || false - }, - overflowBehavior: { - x: ['scroll', overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s - y: ['scroll', overflowBehaviorAllowedValues] //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s - }, - scrollbars: { - visibility: ['auto', scrollbarsVisibilityAllowedValues], //visible || hidden || auto || v || h || a - autoHide: ['never', scrollbarsAutoHideAllowedValues], //never || scroll || leave || move || n || s || l || m - autoHideDelay: [800, numberAllowedValues], //number - dragScrolling: booleanTrueTemplate, //true || false - clickScrolling: booleanFalseTemplate, //true || false - touchSupport: booleanTrueTemplate, //true || false - snapHandle: booleanFalseTemplate //true || false - }, - textarea: { - dynWidth: booleanFalseTemplate, //true || false - dynHeight: booleanFalseTemplate, //true || false - inheritedAttrs: inheritedAttrsTemplate //string || array || null - }, - callbacks: { - onInitialized: callbackTemplate, //null || function - onInitializationWithdrawn: callbackTemplate, //null || function - onDestroyed: callbackTemplate, //null || function - onScrollStart: callbackTemplate, //null || function - onScroll: callbackTemplate, //null || function - onScrollStop: callbackTemplate, //null || function - onOverflowChanged: callbackTemplate, //null || function - onOverflowAmountChanged: callbackTemplate, //null || function - onDirectionChanged: callbackTemplate, //null || function - onContentSizeChanged: callbackTemplate, //null || function - onHostSizeChanged: callbackTemplate, //null || function - onUpdated: callbackTemplate //null || function - } - }; - var convert = function (template) { - var recursive = function (obj) { - var key; - var val; - var valType; - for (key in obj) { - if (!obj[LEXICON.hOP](key)) - continue; - val = obj[key]; - valType = type(val); - if (valType == TYPES.a) - obj[key] = val[template ? 1 : 0]; - else if (valType == TYPES.o) - obj[key] = recursive(val); - } - return obj; - }; - return recursive(FRAMEWORK.extend(true, {}, optionsDefaultsAndTemplate)); - }; - - return { - _defaults: convert(), - - _template: convert(true), - - /** - * Validates the passed object by the passed template. - * @param obj The object which shall be validated. - * @param template The template which defines the allowed values and types. - * @param writeErrors True if errors shall be logged to the console. - * @param diffObj If a object is passed then only valid differences to this object will be returned. - * @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. - */ - _validate: function (obj, template, writeErrors, diffObj) { - var validatedOptions = {}; - var validatedOptionsPrepared = {}; - var objectCopy = FRAMEWORK.extend(true, {}, obj); - var inArray = FRAMEWORK.inArray; - var isEmptyObj = FRAMEWORK.isEmptyObject; - var checkObjectProps = function (data, template, diffData, validatedOptions, validatedOptionsPrepared, prevPropName) { - for (var prop in template) { - if (template[LEXICON.hOP](prop) && data[LEXICON.hOP](prop)) { - var isValid = false; - var isDiff = false; - var templateValue = template[prop]; - var templateValueType = type(templateValue); - var templateIsComplex = templateValueType == TYPES.o; - var templateTypes = type(templateValue) != TYPES.a ? [templateValue] : templateValue; - var dataDiffValue = diffData[prop]; - var dataValue = data[prop]; - var dataValueType = type(dataValue); - var propPrefix = prevPropName ? prevPropName + '.' : ''; - var error = "The option \"" + propPrefix + prop + "\" wasn't set, because"; - var errorPossibleTypes = []; - var errorRestrictedStrings = []; - var restrictedStringValuesSplit; - var restrictedStringValuesPossibilitiesSplit; - var isRestrictedValue; - var mainPossibility; - var currType; - var i; - var v; - var j; - - dataDiffValue = dataDiffValue === undefined ? {} : dataDiffValue; - - //if the template has a object as value, it means that the options are complex (verschachtelt) - if (templateIsComplex && dataValueType == TYPES.o) { - validatedOptions[prop] = {}; - validatedOptionsPrepared[prop] = {}; - checkObjectProps(dataValue, templateValue, dataDiffValue, validatedOptions[prop], validatedOptionsPrepared[prop], propPrefix + prop); - FRAMEWORK.each([data, validatedOptions, validatedOptionsPrepared], function (index, value) { - if (isEmptyObj(value[prop])) { - delete value[prop]; - } - }); - } - else if (!templateIsComplex) { - for (i = 0; i < templateTypes[LEXICON.l]; i++) { - currType = templateTypes[i]; - templateValueType = type(currType); - //if currtype is string and starts with restrictedStringPrefix and end with restrictedStringSuffix - isRestrictedValue = templateValueType == TYPES.s && inArray(currType, possibleTemplateTypes) === -1; - if (isRestrictedValue) { - errorPossibleTypes.push(TYPES.s); - - //split it into a array which contains all possible values for example: ["y:yes", "n:no", "m:maybe"] - restrictedStringValuesSplit = currType.split(restrictedStringsSplit); - errorRestrictedStrings = errorRestrictedStrings.concat(restrictedStringValuesSplit); - for (v = 0; v < restrictedStringValuesSplit[LEXICON.l]; v++) { - //split the possible values into their possibiliteis for example: ["y", "yes"] -> the first is always the mainPossibility - restrictedStringValuesPossibilitiesSplit = restrictedStringValuesSplit[v].split(restrictedStringsPossibilitiesSplit); - mainPossibility = restrictedStringValuesPossibilitiesSplit[0]; - for (j = 0; j < restrictedStringValuesPossibilitiesSplit[LEXICON.l]; j++) { - //if any possibility matches with the dataValue, its valid - if (dataValue === restrictedStringValuesPossibilitiesSplit[j]) { - isValid = true; - break; - } - } - if (isValid) - break; - } - } - else { - errorPossibleTypes.push(currType); - - if (dataValueType === currType) { - isValid = true; - break; - } - } - } - - if (isValid) { - isDiff = dataValue !== dataDiffValue; - - if (isDiff) - validatedOptions[prop] = dataValue; - - if (isRestrictedValue ? inArray(dataDiffValue, restrictedStringValuesPossibilitiesSplit) < 0 : isDiff) - validatedOptionsPrepared[prop] = isRestrictedValue ? mainPossibility : dataValue; - } - else if (writeErrors) { - console.warn(error + " it doesn't accept the type [ " + dataValueType.toUpperCase() + " ] with the value of \"" + dataValue + "\".\r\n" + - "Accepted types are: [ " + errorPossibleTypes.join(', ').toUpperCase() + " ]." + - (errorRestrictedStrings[length] > 0 ? "\r\nValid strings are: [ " + errorRestrictedStrings.join(', ').split(restrictedStringsPossibilitiesSplit).join(', ') + " ]." : '')); - } - delete data[prop]; - } - } - } - }; - checkObjectProps(objectCopy, template, diffObj || {}, validatedOptions, validatedOptionsPrepared); - - //add values which aren't specified in the template to the finished validated object to prevent them from being discarded - /* - if(keepForeignProps) { - FRAMEWORK.extend(true, validatedOptions, objectCopy); - FRAMEWORK.extend(true, validatedOptionsPrepared, objectCopy); - } - */ - - if (!isEmptyObj(objectCopy) && writeErrors) - console.warn('The following options are discarded due to invalidity:\r\n' + window.JSON.stringify(objectCopy, null, 2)); - - return { - _default: validatedOptions, - _prepared: validatedOptionsPrepared - }; - } - } - }()); - - /** - * Initializes the object which contains global information about the plugin and each instance of it. - */ - function initOverlayScrollbarsStatics() { - if (!_pluginsGlobals) - _pluginsGlobals = new OverlayScrollbarsGlobals(_pluginsOptions._defaults); - if (!_pluginsAutoUpdateLoop) - _pluginsAutoUpdateLoop = new OverlayScrollbarsAutoUpdateLoop(_pluginsGlobals); - } - - /** - * 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. - * @param defaultOptions - * @constructor - */ - function OverlayScrollbarsGlobals(defaultOptions) { - var _base = this; - var strOverflow = 'overflow'; - var strHidden = 'hidden'; - var strScroll = 'scroll'; - var bodyElement = FRAMEWORK('body'); - var scrollbarDummyElement = FRAMEWORK('
'); - var scrollbarDummyElement0 = scrollbarDummyElement[0]; - var dummyContainerChild = FRAMEWORK(scrollbarDummyElement.children('div').eq(0)); - - bodyElement.append(scrollbarDummyElement); - scrollbarDummyElement.hide().show(); //fix IE8 bug (incorrect measuring) - - var nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement0); - var nativeScrollbarIsOverlaid = { - x: nativeScrollbarSize.x === 0, - y: nativeScrollbarSize.y === 0 - }; - var msie = (function () { - var ua = window.navigator.userAgent; - var strIndexOf = 'indexOf'; - var strSubString = 'substring'; - var msie = ua[strIndexOf]('MSIE '); - var trident = ua[strIndexOf]('Trident/'); - var edge = ua[strIndexOf]('Edge/'); - var rv = ua[strIndexOf]('rv:'); - var result; - var parseIntFunc = parseInt; - - // IE 10 or older => return version number - if (msie > 0) - result = parseIntFunc(ua[strSubString](msie + 5, ua[strIndexOf]('.', msie)), 10); - - // IE 11 => return version number - else if (trident > 0) - result = parseIntFunc(ua[strSubString](rv + 3, ua[strIndexOf]('.', rv)), 10); - - // Edge (IE 12+) => return version number - else if (edge > 0) - result = parseIntFunc(ua[strSubString](edge + 5, ua[strIndexOf]('.', edge)), 10); - - // other browser - return result; - })(); - - FRAMEWORK.extend(_base, { - defaultOptions: defaultOptions, - msie: msie, - autoUpdateLoop: false, - autoUpdateRecommended: !COMPATIBILITY.mO(), - nativeScrollbarSize: nativeScrollbarSize, - nativeScrollbarIsOverlaid: nativeScrollbarIsOverlaid, - nativeScrollbarStyling: (function () { - var result = false; - scrollbarDummyElement.addClass('os-viewport-native-scrollbars-invisible'); - try { - result = (scrollbarDummyElement.css('scrollbar-width') === 'none' && (msie > 9 || !msie)) || window.getComputedStyle(scrollbarDummyElement0, '::-webkit-scrollbar').getPropertyValue('display') === 'none'; - } catch (ex) { } - - //fix opera bug: scrollbar styles will only appear if overflow value is scroll or auto during the activation of the style. - //and set overflow to scroll - //scrollbarDummyElement.css(strOverflow, strHidden).hide().css(strOverflow, strScroll).show(); - //return (scrollbarDummyElement0[LEXICON.oH] - scrollbarDummyElement0[LEXICON.cH]) === 0 && (scrollbarDummyElement0[LEXICON.oW] - scrollbarDummyElement0[LEXICON.cW]) === 0; - - return result; - })(), - overlayScrollbarDummySize: { x: 30, y: 30 }, - cssCalc: (function () { - var dummyStyle = document.createElement('div')[LEXICON.s]; - var strCalc = 'calc'; - var i = -1; - var prop; - - for (; i < VENDORS._cssPrefixes[LEXICON.l]; i++) { - prop = i < 0 ? strCalc : VENDORS._cssPrefixes[i] + strCalc; - dummyStyle.cssText = 'width:' + prop + '(1px);'; - if (dummyStyle[LEXICON.l]) - return prop; - } - return null; - })(), - restrictedMeasuring: (function () { - //https://bugzilla.mozilla.org/show_bug.cgi?id=1439305 - //since 1.11.0 always false -> fixed via CSS (hopefully) - scrollbarDummyElement.css(strOverflow, strHidden); - var scrollSize = { - w: scrollbarDummyElement0[LEXICON.sW], - h: scrollbarDummyElement0[LEXICON.sH] - }; - scrollbarDummyElement.css(strOverflow, 'visible'); - var scrollSize2 = { - w: scrollbarDummyElement0[LEXICON.sW], - h: scrollbarDummyElement0[LEXICON.sH] - }; - return (scrollSize.w - scrollSize2.w) !== 0 || (scrollSize.h - scrollSize2.h) !== 0; - })(), - rtlScrollBehavior: (function () { - scrollbarDummyElement.css({ 'overflow-y': strHidden, 'overflow-x': strScroll, 'direction': 'rtl' }).scrollLeft(0); - var dummyContainerOffset = scrollbarDummyElement.offset(); - var dummyContainerChildOffset = dummyContainerChild.offset(); - //https://github.com/KingSora/OverlayScrollbars/issues/187 - scrollbarDummyElement.scrollLeft(-999); - var dummyContainerChildOffsetAfterScroll = dummyContainerChild.offset(); - return { - //origin direction = determines if the zero scroll position is on the left or right side - //'i' means 'invert' (i === true means that the axis must be inverted to be correct) - //true = on the left side - //false = on the right side - i: dummyContainerOffset.left === dummyContainerChildOffset.left, - //negative = determines if the maximum scroll is positive or negative - //'n' means 'negate' (n === true means that the axis must be negated to be correct) - //true = negative - //false = positive - n: dummyContainerChildOffset.left !== dummyContainerChildOffsetAfterScroll.left - }; - })(), - supportTransform: VENDORS._cssProperty('transform') !== undefined, - supportTransition: VENDORS._cssProperty('transition') !== undefined, - supportPassiveEvents: (function () { - var supportsPassive = false; - try { - window.addEventListener('test', null, Object.defineProperty({}, 'passive', { - get: function () { - supportsPassive = true; - } - })); - } catch (e) { } - return supportsPassive; - })(), - supportResizeObserver: !!COMPATIBILITY.rO(), - supportMutationObserver: !!COMPATIBILITY.mO() - }); - - scrollbarDummyElement.removeAttr(LEXICON.s).remove(); - - //Catch zoom event: - (function () { - if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) - return; - - var abs = MATH.abs; - var windowWidth = COMPATIBILITY.wW(); - var windowHeight = COMPATIBILITY.wH(); - var windowDpr = getWindowDPR(); - var onResize = function () { - if (INSTANCES().length > 0) { - var newW = COMPATIBILITY.wW(); - var newH = COMPATIBILITY.wH(); - var deltaW = newW - windowWidth; - var deltaH = newH - windowHeight; - - if (deltaW === 0 && deltaH === 0) - return; - - var deltaWRatio = MATH.round(newW / (windowWidth / 100.0)); - var deltaHRatio = MATH.round(newH / (windowHeight / 100.0)); - var absDeltaW = abs(deltaW); - var absDeltaH = abs(deltaH); - var absDeltaWRatio = abs(deltaWRatio); - var absDeltaHRatio = abs(deltaHRatio); - var newDPR = getWindowDPR(); - - var deltaIsBigger = absDeltaW > 2 && absDeltaH > 2; - var difference = !differenceIsBiggerThanOne(absDeltaWRatio, absDeltaHRatio); - var dprChanged = newDPR !== windowDpr && windowDpr > 0; - var isZoom = deltaIsBigger && difference && dprChanged; - var oldScrollbarSize = _base.nativeScrollbarSize; - var newScrollbarSize; - - if (isZoom) { - bodyElement.append(scrollbarDummyElement); - newScrollbarSize = _base.nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement[0]); - scrollbarDummyElement.remove(); - if (oldScrollbarSize.x !== newScrollbarSize.x || oldScrollbarSize.y !== newScrollbarSize.y) { - FRAMEWORK.each(INSTANCES(), function () { - if (INSTANCES(this)) - INSTANCES(this).update('zoom'); - }); - } - } - - windowWidth = newW; - windowHeight = newH; - windowDpr = newDPR; - } - }; - - function differenceIsBiggerThanOne(valOne, valTwo) { - var absValOne = abs(valOne); - var absValTwo = abs(valTwo); - return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo); - } - - function getWindowDPR() { - var dDPI = window.screen.deviceXDPI || 0; - var sDPI = window.screen.logicalXDPI || 1; - return window.devicePixelRatio || (dDPI / sDPI); - } - - FRAMEWORK(window).on('resize', onResize); - })(); - - function calcNativeScrollbarSize(measureElement) { - return { - x: measureElement[LEXICON.oH] - measureElement[LEXICON.cH], - y: measureElement[LEXICON.oW] - measureElement[LEXICON.cW] - }; - } - } - - /** - * 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. - * @constructor - */ - function OverlayScrollbarsAutoUpdateLoop(globals) { - var _base = this; - var _inArray = FRAMEWORK.inArray; - var _getNow = COMPATIBILITY.now; - var _strAutoUpdate = 'autoUpdate'; - var _strAutoUpdateInterval = _strAutoUpdate + 'Interval'; - var _strLength = LEXICON.l; - var _loopingInstances = []; - var _loopingInstancesIntervalCache = []; - var _loopIsActive = false; - var _loopIntervalDefault = 33; - var _loopInterval = _loopIntervalDefault; - var _loopTimeOld = _getNow(); - var _loopID; - - - /** - * The auto update loop which will run every 50 milliseconds or less if the update interval of a instance is lower than 50 milliseconds. - */ - var loop = function () { - if (_loopingInstances[_strLength] > 0 && _loopIsActive) { - _loopID = COMPATIBILITY.rAF()(function () { - loop(); - }); - var timeNew = _getNow(); - var timeDelta = timeNew - _loopTimeOld; - var lowestInterval; - var instance; - var instanceOptions; - var instanceAutoUpdateAllowed; - var instanceAutoUpdateInterval; - var now; - - if (timeDelta > _loopInterval) { - _loopTimeOld = timeNew - (timeDelta % _loopInterval); - lowestInterval = _loopIntervalDefault; - for (var i = 0; i < _loopingInstances[_strLength]; i++) { - instance = _loopingInstances[i]; - if (instance !== undefined) { - instanceOptions = instance.options(); - instanceAutoUpdateAllowed = instanceOptions[_strAutoUpdate]; - instanceAutoUpdateInterval = MATH.max(1, instanceOptions[_strAutoUpdateInterval]); - now = _getNow(); - - if ((instanceAutoUpdateAllowed === true || instanceAutoUpdateAllowed === null) && (now - _loopingInstancesIntervalCache[i]) > instanceAutoUpdateInterval) { - instance.update('auto'); - _loopingInstancesIntervalCache[i] = new Date(now += instanceAutoUpdateInterval); - } - - lowestInterval = MATH.max(1, MATH.min(lowestInterval, instanceAutoUpdateInterval)); - } - } - _loopInterval = lowestInterval; - } - } else { - _loopInterval = _loopIntervalDefault; - } - }; - - /** - * Add OverlayScrollbars instance to the auto update loop. Only successful if the instance isn't already added. - * @param instance The instance which shall be updated in a loop automatically. - */ - _base.add = function (instance) { - if (_inArray(instance, _loopingInstances) === -1) { - _loopingInstances.push(instance); - _loopingInstancesIntervalCache.push(_getNow()); - if (_loopingInstances[_strLength] > 0 && !_loopIsActive) { - _loopIsActive = true; - globals.autoUpdateLoop = _loopIsActive; - loop(); - } - } - }; - - /** - * Remove OverlayScrollbars instance from the auto update loop. Only successful if the instance was added before. - * @param instance The instance which shall be updated in a loop automatically. - */ - _base.remove = function (instance) { - var index = _inArray(instance, _loopingInstances); - if (index > -1) { - //remove from loopingInstances list - _loopingInstancesIntervalCache.splice(index, 1); - _loopingInstances.splice(index, 1); - - //correct update loop behavior - if (_loopingInstances[_strLength] === 0 && _loopIsActive) { - _loopIsActive = false; - globals.autoUpdateLoop = _loopIsActive; - if (_loopID !== undefined) { - COMPATIBILITY.cAF()(_loopID); - _loopID = -1; - } - } - } - }; - } - - /** - * A object which manages the scrollbars visibility of the target element. - * @param pluginTargetElement The element from which the scrollbars shall be hidden. - * @param options The custom options. - * @param extensions The custom extensions. - * @param globals - * @param autoUpdateLoop - * @returns {*} - * @constructor - */ - function OverlayScrollbarsInstance(pluginTargetElement, options, extensions, globals, autoUpdateLoop) { - //shortcuts - var type = COMPATIBILITY.type; - var inArray = FRAMEWORK.inArray; - var each = FRAMEWORK.each; - - //make correct instanceof - var _base = new _plugin(); - var _frameworkProto = FRAMEWORK[LEXICON.p]; - - //if passed element is no HTML element: skip and return - if (!isHTMLElement(pluginTargetElement)) - return; - - //if passed element is already initialized: set passed options if there are any and return its instance - if (INSTANCES(pluginTargetElement)) { - var inst = INSTANCES(pluginTargetElement); - inst.options(options); - return inst; - } - - //globals: - var _nativeScrollbarIsOverlaid; - var _overlayScrollbarDummySize; - var _rtlScrollBehavior; - var _autoUpdateRecommended; - var _msieVersion; - var _nativeScrollbarStyling; - var _cssCalc; - var _nativeScrollbarSize; - var _supportTransition; - var _supportTransform; - var _supportPassiveEvents; - var _supportResizeObserver; - var _supportMutationObserver; - var _restrictedMeasuring; - - //general readonly: - var _initialized; - var _destroyed; - var _isTextarea; - var _isBody; - var _documentMixed; - var _domExists; - - //general: - var _isBorderBox; - var _sizeAutoObserverAdded; - var _paddingX; - var _paddingY; - var _borderX; - var _borderY; - var _marginX; - var _marginY; - var _isRTL; - var _sleeping; - var _contentBorderSize = {}; - var _scrollHorizontalInfo = {}; - var _scrollVerticalInfo = {}; - var _viewportSize = {}; - var _nativeScrollbarMinSize = {}; - - //naming: - var _strMinusHidden = '-hidden'; - var _strMarginMinus = 'margin-'; - var _strPaddingMinus = 'padding-'; - var _strBorderMinus = 'border-'; - var _strTop = 'top'; - var _strRight = 'right'; - var _strBottom = 'bottom'; - var _strLeft = 'left'; - var _strMinMinus = 'min-'; - var _strMaxMinus = 'max-'; - var _strWidth = 'width'; - var _strHeight = 'height'; - var _strFloat = 'float'; - var _strEmpty = ''; - var _strAuto = 'auto'; - var _strSync = 'sync'; - var _strScroll = 'scroll'; - var _strHundredPercent = '100%'; - var _strX = 'x'; - var _strY = 'y'; - var _strDot = '.'; - var _strSpace = ' '; - var _strScrollbar = 'scrollbar'; - var _strMinusHorizontal = '-horizontal'; - var _strMinusVertical = '-vertical'; - var _strScrollLeft = _strScroll + 'Left'; - var _strScrollTop = _strScroll + 'Top'; - var _strMouseTouchDownEvent = 'mousedown touchstart'; - var _strMouseTouchUpEvent = 'mouseup touchend touchcancel'; - var _strMouseTouchMoveEvent = 'mousemove touchmove'; - var _strMouseTouchEnter = 'mouseenter'; - var _strMouseTouchLeave = 'mouseleave'; - var _strKeyDownEvent = 'keydown'; - var _strKeyUpEvent = 'keyup'; - var _strSelectStartEvent = 'selectstart'; - var _strTransitionEndEvent = 'transitionend webkitTransitionEnd oTransitionEnd'; - var _strResizeObserverProperty = '__overlayScrollbarsRO__'; - - //class names: - var _cassNamesPrefix = 'os-'; - var _classNameHTMLElement = _cassNamesPrefix + 'html'; - var _classNameHostElement = _cassNamesPrefix + 'host'; - var _classNameHostTextareaElement = _classNameHostElement + '-textarea'; - var _classNameHostScrollbarHorizontalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusHorizontal + _strMinusHidden; - var _classNameHostScrollbarVerticalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusVertical + _strMinusHidden; - var _classNameHostTransition = _classNameHostElement + '-transition'; - var _classNameHostRTL = _classNameHostElement + '-rtl'; - var _classNameHostResizeDisabled = _classNameHostElement + '-resize-disabled'; - var _classNameHostScrolling = _classNameHostElement + '-scrolling'; - var _classNameHostOverflow = _classNameHostElement + '-overflow'; - var _classNameHostOverflowX = _classNameHostOverflow + '-x'; - var _classNameHostOverflowY = _classNameHostOverflow + '-y'; - var _classNameTextareaElement = _cassNamesPrefix + 'textarea'; - var _classNameTextareaCoverElement = _classNameTextareaElement + '-cover'; - var _classNamePaddingElement = _cassNamesPrefix + 'padding'; - var _classNameViewportElement = _cassNamesPrefix + 'viewport'; - var _classNameViewportNativeScrollbarsInvisible = _classNameViewportElement + '-native-scrollbars-invisible'; - var _classNameViewportNativeScrollbarsOverlaid = _classNameViewportElement + '-native-scrollbars-overlaid'; - var _classNameContentElement = _cassNamesPrefix + 'content'; - var _classNameContentArrangeElement = _cassNamesPrefix + 'content-arrange'; - var _classNameContentGlueElement = _cassNamesPrefix + 'content-glue'; - var _classNameSizeAutoObserverElement = _cassNamesPrefix + 'size-auto-observer'; - var _classNameResizeObserverElement = _cassNamesPrefix + 'resize-observer'; - var _classNameResizeObserverItemElement = _cassNamesPrefix + 'resize-observer-item'; - var _classNameResizeObserverItemFinalElement = _classNameResizeObserverItemElement + '-final'; - var _classNameTextInherit = _cassNamesPrefix + 'text-inherit'; - var _classNameScrollbar = _cassNamesPrefix + _strScrollbar; - var _classNameScrollbarTrack = _classNameScrollbar + '-track'; - var _classNameScrollbarTrackOff = _classNameScrollbarTrack + '-off'; - var _classNameScrollbarHandle = _classNameScrollbar + '-handle'; - var _classNameScrollbarHandleOff = _classNameScrollbarHandle + '-off'; - var _classNameScrollbarUnusable = _classNameScrollbar + '-unusable'; - var _classNameScrollbarAutoHidden = _classNameScrollbar + '-' + _strAuto + _strMinusHidden; - var _classNameScrollbarCorner = _classNameScrollbar + '-corner'; - var _classNameScrollbarCornerResize = _classNameScrollbarCorner + '-resize'; - var _classNameScrollbarCornerResizeB = _classNameScrollbarCornerResize + '-both'; - var _classNameScrollbarCornerResizeH = _classNameScrollbarCornerResize + _strMinusHorizontal; - var _classNameScrollbarCornerResizeV = _classNameScrollbarCornerResize + _strMinusVertical; - var _classNameScrollbarHorizontal = _classNameScrollbar + _strMinusHorizontal; - var _classNameScrollbarVertical = _classNameScrollbar + _strMinusVertical; - var _classNameDragging = _cassNamesPrefix + 'dragging'; - var _classNameThemeNone = _cassNamesPrefix + 'theme-none'; - var _classNamesDynamicDestroy = [ - _classNameViewportNativeScrollbarsInvisible, - _classNameViewportNativeScrollbarsOverlaid, - _classNameScrollbarTrackOff, - _classNameScrollbarHandleOff, - _classNameScrollbarUnusable, - _classNameScrollbarAutoHidden, - _classNameScrollbarCornerResize, - _classNameScrollbarCornerResizeB, - _classNameScrollbarCornerResizeH, - _classNameScrollbarCornerResizeV, - _classNameDragging].join(_strSpace); - - //callbacks: - var _callbacksInitQeueue = []; - - //attrs viewport shall inherit from target - var _viewportAttrsFromTarget = [LEXICON.ti]; - - //options: - var _defaultOptions; - var _currentOptions; - var _currentPreparedOptions; - - //extensions: - var _extensions = {}; - var _extensionsPrivateMethods = 'added removed on contract'; - - //update - var _lastUpdateTime; - var _swallowedUpdateHints = {}; - var _swallowedUpdateTimeout; - var _swallowUpdateLag = 42; - var _imgs = []; - - //DOM elements: - var _windowElement; - var _documentElement; - var _htmlElement; - var _bodyElement; - var _targetElement; //the target element of this OverlayScrollbars object - var _hostElement; //the host element of this OverlayScrollbars object -> may be the same as targetElement - var _sizeAutoObserverElement; //observes size auto changes - var _sizeObserverElement; //observes size and padding changes - var _paddingElement; //manages the padding - var _viewportElement; //is the viewport of our scrollbar model - var _contentElement; //the element which holds the content - var _contentArrangeElement; //is needed for correct sizing of the content element (only if native scrollbars are overlays) - var _contentGlueElement; //has always the size of the content element - var _textareaCoverElement; //only applied if target is a textarea element. Used for correct size calculation and for prevention of uncontrolled scrolling - var _scrollbarCornerElement; - var _scrollbarHorizontalElement; - var _scrollbarHorizontalTrackElement; - var _scrollbarHorizontalHandleElement; - var _scrollbarVerticalElement; - var _scrollbarVerticalTrackElement; - var _scrollbarVerticalHandleElement; - var _windowElementNative; - var _documentElementNative; - var _targetElementNative; - var _hostElementNative; - var _sizeAutoObserverElementNative; - var _sizeObserverElementNative; - var _paddingElementNative; - var _viewportElementNative; - var _contentElementNative; - - //Cache: - var _hostSizeCache; - var _contentScrollSizeCache; - var _arrangeContentSizeCache; - var _hasOverflowCache; - var _hideOverflowCache; - var _widthAutoCache; - var _heightAutoCache; - var _cssMaxValueCache; - var _cssBoxSizingCache; - var _cssPaddingCache; - var _cssBorderCache; - var _cssMarginCache; - var _cssDirectionCache; - var _cssDirectionDetectedCache; - var _paddingAbsoluteCache; - var _clipAlwaysCache; - var _contentGlueSizeCache; - var _overflowBehaviorCache; - var _overflowAmountCache; - var _ignoreOverlayScrollbarHidingCache; - var _autoUpdateCache; - var _sizeAutoCapableCache; - var _contentElementScrollSizeChangeDetectedCache; - var _hostElementSizeChangeDetectedCache; - var _scrollbarsVisibilityCache; - var _scrollbarsAutoHideCache; - var _scrollbarsClickScrollingCache; - var _scrollbarsDragScrollingCache; - var _resizeCache; - var _normalizeRTLCache; - var _classNameCache; - var _oldClassName; - var _textareaAutoWrappingCache; - var _textareaInfoCache; - var _textareaSizeCache; - var _textareaDynHeightCache; - var _textareaDynWidthCache; - var _bodyMinSizeCache; - var _displayIsHiddenCache; - var _updateAutoCache = {}; - - //MutationObserver: - var _mutationObserverHost; - var _mutationObserverContent; - var _mutationObserverHostCallback; - var _mutationObserverContentCallback; - var _mutationObserversConnected; - var _mutationObserverAttrsTextarea = ['wrap', 'cols', 'rows']; - var _mutationObserverAttrsHost = [LEXICON.i, LEXICON.c, LEXICON.s, 'open'].concat(_viewportAttrsFromTarget); - - //events: - var _destroyEvents = []; - - //textarea: - var _textareaHasFocus; - - //scrollbars: - var _scrollbarsAutoHideTimeoutId; - var _scrollbarsAutoHideMoveTimeoutId; - var _scrollbarsAutoHideDelay; - var _scrollbarsAutoHideNever; - var _scrollbarsAutoHideScroll; - var _scrollbarsAutoHideMove; - var _scrollbarsAutoHideLeave; - var _scrollbarsHandleHovered; - var _scrollbarsHandlesDefineScrollPos; - - //resize - var _resizeNone; - var _resizeBoth; - var _resizeHorizontal; - var _resizeVertical; - - - //==== Event Listener ====// - - /** - * Adds or removes a event listener from the given element. - * @param element The element to which the event listener shall be applied or removed. - * @param eventNames The name(s) of the events. - * @param listener The method which shall be called. - * @param remove True if the handler shall be removed, false or undefined if the handler shall be added. - */ - function setupResponsiveEventListener(element, eventNames, listener, remove, passive) { - var collected = type(eventNames) == TYPES.a && type(listener) == TYPES.a; - var method = remove ? 'removeEventListener' : 'addEventListener'; - var onOff = remove ? 'off' : 'on'; - var events = collected ? false : eventNames.split(_strSpace) - var i = 0; - - if (collected) { - for (; i < eventNames[LEXICON.l]; i++) - setupResponsiveEventListener(element, eventNames[i], listener[i], remove); - } - else { - for (; i < events[LEXICON.l]; i++) { - if (_supportPassiveEvents) - element[0][method](events[i], listener, { passive: passive || false }); - else - element[onOff](events[i], listener); - } - } - } - - - function addDestroyEventListener(element, eventNames, listener, passive) { - setupResponsiveEventListener(element, eventNames, listener, false, passive); - _destroyEvents.push(COMPATIBILITY.bind(setupResponsiveEventListener, 0, element, eventNames, listener, true, passive)); - } - - //==== Resize Observer ====// - - /** - * Adds or removes a resize observer from the given element. - * @param targetElement The element to which the resize observer shall be added or removed. - * @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. - */ - function setupResizeObserver(targetElement, onElementResizedCallback) { - if (targetElement) { - var resizeObserver = COMPATIBILITY.rO(); - var strAnimationStartEvent = 'animationstart mozAnimationStart webkitAnimationStart MSAnimationStart'; - var strChildNodes = 'childNodes'; - var constScroll = 3333333; - var callback = function () { - targetElement[_strScrollTop](constScroll)[_strScrollLeft](_isRTL ? _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll : constScroll); - onElementResizedCallback(); - }; - //add resize observer: - if (onElementResizedCallback) { - if (_supportResizeObserver) { - var element = targetElement.addClass('observed').append(generateDiv(_classNameResizeObserverElement)).contents()[0]; - var observer = element[_strResizeObserverProperty] = new resizeObserver(callback); - observer.observe(element); - } - else { - if (_msieVersion > 9 || !_autoUpdateRecommended) { - targetElement.prepend( - generateDiv(_classNameResizeObserverElement, - generateDiv({ c: _classNameResizeObserverItemElement, dir: 'ltr' }, - generateDiv(_classNameResizeObserverItemElement, - generateDiv(_classNameResizeObserverItemFinalElement) - ) + - generateDiv(_classNameResizeObserverItemElement, - generateDiv({ c: _classNameResizeObserverItemFinalElement, style: 'width: 200%; height: 200%' }) - ) - ) - ) - ); - - var observerElement = targetElement[0][strChildNodes][0][strChildNodes][0]; - var shrinkElement = FRAMEWORK(observerElement[strChildNodes][1]); - var expandElement = FRAMEWORK(observerElement[strChildNodes][0]); - var expandElementChild = FRAMEWORK(expandElement[0][strChildNodes][0]); - var widthCache = observerElement[LEXICON.oW]; - var heightCache = observerElement[LEXICON.oH]; - var isDirty; - var rAFId; - var currWidth; - var currHeight; - var factor = 2; - var nativeScrollbarSize = globals.nativeScrollbarSize; //care don't make changes to this object!!! - var reset = function () { - /* - var sizeResetWidth = observerElement[LEXICON.oW] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; - var sizeResetHeight = observerElement[LEXICON.oH] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; - var expandChildCSS = {}; - expandChildCSS[_strWidth] = sizeResetWidth; - expandChildCSS[_strHeight] = sizeResetHeight; - expandElementChild.css(expandChildCSS); - - - expandElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); - shrinkElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); - */ - expandElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); - shrinkElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); - }; - var onResized = function () { - rAFId = 0; - if (!isDirty) - return; - - widthCache = currWidth; - heightCache = currHeight; - callback(); - }; - var onScroll = function (event) { - currWidth = observerElement[LEXICON.oW]; - currHeight = observerElement[LEXICON.oH]; - isDirty = currWidth != widthCache || currHeight != heightCache; - - if (event && isDirty && !rAFId) { - COMPATIBILITY.cAF()(rAFId); - rAFId = COMPATIBILITY.rAF()(onResized); - } - else if (!event) - onResized(); - - reset(); - if (event) { - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - return false; - }; - var expandChildCSS = {}; - var observerElementCSS = {}; - - setTopRightBottomLeft(observerElementCSS, _strEmpty, [ - -((nativeScrollbarSize.y + 1) * factor), - nativeScrollbarSize.x * -factor, - nativeScrollbarSize.y * -factor, - -((nativeScrollbarSize.x + 1) * factor) - ]); - - FRAMEWORK(observerElement).css(observerElementCSS); - expandElement.on(_strScroll, onScroll); - shrinkElement.on(_strScroll, onScroll); - targetElement.on(strAnimationStartEvent, function () { - onScroll(false); - }); - //lets assume that the divs will never be that large and a constant value is enough - expandChildCSS[_strWidth] = constScroll; - expandChildCSS[_strHeight] = constScroll; - expandElementChild.css(expandChildCSS); - - reset(); - } - else { - var attachEvent = _documentElementNative.attachEvent; - var isIE = _msieVersion !== undefined; - if (attachEvent) { - targetElement.prepend(generateDiv(_classNameResizeObserverElement)); - findFirst(targetElement, _strDot + _classNameResizeObserverElement)[0].attachEvent('onresize', callback); - } - else { - var obj = _documentElementNative.createElement(TYPES.o); - obj.setAttribute(LEXICON.ti, '-1'); - obj.setAttribute(LEXICON.c, _classNameResizeObserverElement); - obj.onload = function () { - var wnd = this.contentDocument.defaultView; - wnd.addEventListener('resize', callback); - wnd.document.documentElement.style.display = 'none'; - }; - obj.type = 'text/html'; - if (isIE) - targetElement.prepend(obj); - obj.data = 'about:blank'; - if (!isIE) - targetElement.prepend(obj); - targetElement.on(strAnimationStartEvent, callback); - } - } - } - - if (targetElement[0] === _sizeObserverElementNative) { - var directionChanged = function () { - var dir = _hostElement.css('direction'); - var css = {}; - var scrollLeftValue = 0; - var result = false; - if (dir !== _cssDirectionDetectedCache) { - if (dir === 'ltr') { - css[_strLeft] = 0; - css[_strRight] = _strAuto; - scrollLeftValue = constScroll; - } - else { - css[_strLeft] = _strAuto; - css[_strRight] = 0; - scrollLeftValue = _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll; - } - //execution order is important for IE!!! - _sizeObserverElement.children().eq(0).css(css); - _sizeObserverElement[_strScrollLeft](scrollLeftValue)[_strScrollTop](constScroll); - _cssDirectionDetectedCache = dir; - result = true; - } - return result; - }; - directionChanged(); - addDestroyEventListener(targetElement, _strScroll, function (event) { - if (directionChanged()) - update(); - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - return false; - }); - } - } - //remove resize observer: - else { - if (_supportResizeObserver) { - var element = targetElement.contents()[0]; - var resizeObserverObj = element[_strResizeObserverProperty]; - if (resizeObserverObj) { - resizeObserverObj.disconnect(); - delete element[_strResizeObserverProperty]; - } - } - else { - remove(targetElement.children(_strDot + _classNameResizeObserverElement).eq(0)); - } - } - } - } - - /** - * Freezes or unfreezes the given resize observer. - * @param targetElement The element to which the target resize observer is applied. - * @param freeze True if the resize observer shall be frozen, false otherwise. - - function freezeResizeObserver(targetElement, freeze) { - if (targetElement !== undefined) { - if(freeze) { - if (_supportResizeObserver) { - var element = targetElement.contents()[0]; - element[_strResizeObserverProperty].unobserve(element); - } - else { - targetElement = targetElement.children(_strDot + _classNameResizeObserverElement).eq(0); - var w = targetElement.css(_strWidth); - var h = targetElement.css(_strHeight); - var css = {}; - css[_strWidth] = w; - css[_strHeight] = h; - targetElement.css(css); - } - } - else { - if (_supportResizeObserver) { - var element = targetElement.contents()[0]; - element[_strResizeObserverProperty].observe(element); - } - else { - var css = { }; - css[_strHeight] = _strEmpty; - css[_strWidth] = _strEmpty; - targetElement.children(_strDot + _classNameResizeObserverElement).eq(0).css(css); - } - } - } - } - */ - - - //==== Mutation Observers ====// - - /** - * Creates MutationObservers for the host and content Element if they are supported. - */ - function createMutationObservers() { - if (_supportMutationObserver) { - var mutationObserverContentLag = 11; - var mutationObserver = COMPATIBILITY.mO(); - var contentLastUpdate = COMPATIBILITY.now(); - var mutationTarget; - var mutationAttrName; - var contentTimeout; - var now; - var sizeAuto; - var action; - - _mutationObserverHostCallback = function (mutations) { - var doUpdate = false; - var mutation; - var mutatedAttrs = []; - - if (_initialized && !_sleeping) { - each(mutations, function () { - mutation = this; - mutationTarget = mutation.target; - mutationAttrName = mutation.attributeName; - - if(!doUpdate) { - if (mutationAttrName === LEXICON.c) - doUpdate = hostClassNamesChanged(mutation.oldValue, mutationTarget.className); - else if (mutationAttrName === LEXICON.s) - doUpdate = mutation.oldValue !== mutationTarget[LEXICON.s].cssText; - else - doUpdate = true; - } - - mutatedAttrs.push(mutationAttrName); - }); - - updateViewportAttrsFromTarget(mutatedAttrs); - - if (doUpdate) - _base.update(_strAuto); - } - return doUpdate; - }; - _mutationObserverContentCallback = function (mutations) { - var doUpdate = false; - var mutation; - - if (_initialized && !_sleeping) { - each(mutations, function () { - mutation = this; - doUpdate = isUnknownMutation(mutation); - return !doUpdate; - }); - - if (doUpdate) { - now = COMPATIBILITY.now(); - sizeAuto = (_heightAutoCache || _widthAutoCache); - action = function () { - if (!_destroyed) { - contentLastUpdate = now; - - //if cols, rows or wrap attr was changed - if (_isTextarea) - textareaUpdate(); - - if (sizeAuto) - update(); - else - _base.update(_strAuto); - } - }; - clearTimeout(contentTimeout); - if (mutationObserverContentLag <= 0 || now - contentLastUpdate > mutationObserverContentLag || !sizeAuto) - action(); - else - contentTimeout = setTimeout(action, mutationObserverContentLag); - } - } - return doUpdate; - } - - _mutationObserverHost = new mutationObserver(_mutationObserverHostCallback); - _mutationObserverContent = new mutationObserver(_mutationObserverContentCallback); - } - } - - /** - * Connects the MutationObservers if they are supported. - */ - function connectMutationObservers() { - if (_supportMutationObserver && !_mutationObserversConnected) { - _mutationObserverHost.observe(_hostElementNative, { - attributes: true, - attributeOldValue: true, - attributeFilter: _mutationObserverAttrsHost - }); - - _mutationObserverContent.observe(_isTextarea ? _targetElementNative : _contentElementNative, { - attributes: true, - attributeOldValue: true, - subtree: !_isTextarea, - childList: !_isTextarea, - characterData: !_isTextarea, - attributeFilter: _isTextarea ? _mutationObserverAttrsTextarea : _mutationObserverAttrsHost - }); - - _mutationObserversConnected = true; - } - } - - /** - * Disconnects the MutationObservers if they are supported. - */ - function disconnectMutationObservers() { - if (_supportMutationObserver && _mutationObserversConnected) { - _mutationObserverHost.disconnect(); - _mutationObserverContent.disconnect(); - - _mutationObserversConnected = false; - } - } - - - //==== Events of elements ====// - - /** - * This method gets called every time the host element gets resized. IMPORTANT: Padding changes are detected too!! - * It refreshes the hostResizedEventArgs and the hostSizeResizeCache. - * If there are any size changes, the update method gets called. - */ - function hostOnResized() { - if (!_sleeping) { - var changed; - var hostSize = { - w: _sizeObserverElementNative[LEXICON.sW], - h: _sizeObserverElementNative[LEXICON.sH] - }; - - changed = checkCache(hostSize, _hostElementSizeChangeDetectedCache); - _hostElementSizeChangeDetectedCache = hostSize; - if (changed) - update({ _hostSizeChanged: true }); - } - } - - /** - * The mouse enter event of the host element. This event is only needed for the autoHide feature. - */ - function hostOnMouseEnter() { - if (_scrollbarsAutoHideLeave) - refreshScrollbarsAutoHide(true); - } - - /** - * The mouse leave event of the host element. This event is only needed for the autoHide feature. - */ - function hostOnMouseLeave() { - if (_scrollbarsAutoHideLeave && !_bodyElement.hasClass(_classNameDragging)) - refreshScrollbarsAutoHide(false); - } - - /** - * The mouse move event of the host element. This event is only needed for the autoHide "move" feature. - */ - function hostOnMouseMove() { - if (_scrollbarsAutoHideMove) { - refreshScrollbarsAutoHide(true); - clearTimeout(_scrollbarsAutoHideMoveTimeoutId); - _scrollbarsAutoHideMoveTimeoutId = setTimeout(function () { - if (_scrollbarsAutoHideMove && !_destroyed) - refreshScrollbarsAutoHide(false); - }, 100); - } - } - - /** - * Prevents text from deselection if attached to the document element on the mousedown event of a DOM element. - * @param event The select start event. - */ - function documentOnSelectStart(event) { - COMPATIBILITY.prvD(event); - return false; - } - - /** - * A callback which will be called after a img element has downloaded its src asynchronous. - */ - function imgOnLoad() { - update({ _contentSizeChanged: true }); - } - - /** - * Adds or removes mouse & touch events of the host element. (for handling auto-hiding of the scrollbars) - * @param destroy Indicates whether the events shall be added or removed. - */ - function setupHostMouseTouchEvents(destroy) { - setupResponsiveEventListener(_hostElement, - _strMouseTouchMoveEvent, - hostOnMouseMove, - (_scrollbarsAutoHideMove ? destroy : true), true); - setupResponsiveEventListener(_hostElement, - [_strMouseTouchEnter, _strMouseTouchLeave], - [hostOnMouseEnter, hostOnMouseLeave], - (_scrollbarsAutoHideMove ? true : destroy), true); - - //if the plugin is initialized and the mouse is over the host element, make the scrollbars visible - if (!_initialized && !destroy) - _hostElement.one('mouseover', hostOnMouseEnter); - } - - - //==== Update Detection ====// - - /** - * Measures the min width and min height of the body element and refreshes the related cache. - * @returns {boolean} True if the min width or min height has changed, false otherwise. - */ - function bodyMinSizeChanged() { - var bodyMinSize = {}; - if (_isBody && _contentArrangeElement) { - bodyMinSize.w = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strWidth)); - bodyMinSize.h = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strHeight)); - bodyMinSize.c = checkCache(bodyMinSize, _bodyMinSizeCache); - bodyMinSize.f = true; //flag for "measured at least once" - } - _bodyMinSizeCache = bodyMinSize; - return !!bodyMinSize.c; - } - - /** - * Returns true if the class names really changed (new class without plugin host prefix) - * @param oldCassNames The old ClassName string. - * @param newClassNames The new ClassName string. - * @returns {boolean} True if the class names has really changed, false otherwise. - */ - function hostClassNamesChanged(oldCassNames, newClassNames) { - var currClasses = (newClassNames !== undefined && newClassNames !== null) ? newClassNames.split(_strSpace) : _strEmpty; - var oldClasses = (oldCassNames !== undefined && oldCassNames !== null) ? oldCassNames.split(_strSpace) : _strEmpty; - if (currClasses === _strEmpty && oldClasses === _strEmpty) - return false; - var diff = getArrayDifferences(oldClasses, currClasses); - var changed = false; - var oldClassNames = _oldClassName !== undefined && _oldClassName !== null ? _oldClassName.split(_strSpace) : [_strEmpty]; - var currClassNames = _classNameCache !== undefined && _classNameCache !== null ? _classNameCache.split(_strSpace) : [_strEmpty]; - - //remove none theme from diff list to prevent update - var idx = inArray(_classNameThemeNone, diff); - var curr; - var i; - var v; - var o; - var c; - - if (idx > -1) - diff.splice(idx, 1); - - for (i = 0; i < diff.length; i++) { - curr = diff[i]; - if (curr.indexOf(_classNameHostElement) !== 0) { - o = true; - c = true; - for (v = 0; v < oldClassNames.length; v++) { - if (curr === oldClassNames[v]) { - o = false; - break; - } - } - for (v = 0; v < currClassNames.length; v++) { - if (curr === currClassNames[v]) { - c = false; - break; - } - } - if (o && c) { - changed = true; - break; - } - } - - } - return changed; - } - - /** - * 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. - * @param mutation The mutation which shall be checked. - * @returns {boolean} True if the mutation is from a unknown element, false otherwise. - */ - function isUnknownMutation(mutation) { - var attributeName = mutation.attributeName; - var mutationTarget = mutation.target; - var mutationType = mutation.type; - var strClosest = 'closest'; - - if (mutationTarget === _contentElementNative) - return attributeName === null; - if (mutationType === 'attributes' && (attributeName === LEXICON.c || attributeName === LEXICON.s) && !_isTextarea) { - //ignore className changes by the plugin - if (attributeName === LEXICON.c && FRAMEWORK(mutationTarget).hasClass(_classNameHostElement)) - return hostClassNamesChanged(mutation.oldValue, mutationTarget.getAttribute(LEXICON.c)); - - //only do it of browser support it natively - if (typeof mutationTarget[strClosest] != TYPES.f) - return true; - if (mutationTarget[strClosest](_strDot + _classNameResizeObserverElement) !== null || - mutationTarget[strClosest](_strDot + _classNameScrollbar) !== null || - mutationTarget[strClosest](_strDot + _classNameScrollbarCorner) !== null) - return false; - } - return true; - } - - /** - * Returns true if the content size was changed since the last time this method was called. - * @returns {boolean} True if the content size was changed, false otherwise. - */ - function updateAutoContentSizeChanged() { - if (_sleeping) - return false; - - var contentMeasureElement = getContentMeasureElement(); - var textareaValueLength = _isTextarea && _widthAutoCache && !_textareaAutoWrappingCache ? _targetElement.val().length : 0; - var setCSS = !_mutationObserversConnected && _widthAutoCache && !_isTextarea; - var css = {}; - var float; - var bodyMinSizeC; - var changed; - var contentElementScrollSize; - - if (setCSS) { - float = _contentElement.css(_strFloat); - css[_strFloat] = _isRTL ? _strRight : _strLeft; - css[_strWidth] = _strAuto; - _contentElement.css(css); - } - contentElementScrollSize = { - w: contentMeasureElement[LEXICON.sW] + textareaValueLength, - h: contentMeasureElement[LEXICON.sH] + textareaValueLength - }; - if (setCSS) { - css[_strFloat] = float; - css[_strWidth] = _strHundredPercent; - _contentElement.css(css); - } - - bodyMinSizeC = bodyMinSizeChanged(); - changed = checkCache(contentElementScrollSize, _contentElementScrollSizeChangeDetectedCache); - - _contentElementScrollSizeChangeDetectedCache = contentElementScrollSize; - - return changed || bodyMinSizeC; - } - - /** - * Returns true when a attribute which the MutationObserver would observe has changed. - * @returns {boolean} True if one of the attributes which a MutationObserver would observe has changed, false or undefined otherwise. - */ - function meaningfulAttrsChanged() { - if (_sleeping || _mutationObserversConnected) - return; - - var elem; - var curr; - var cache; - var changedAttrs = []; - var checks = [ - { - _elem: _hostElement, - _attrs: _mutationObserverAttrsHost.concat(':visible') - }, - { - _elem: _isTextarea ? _targetElement : undefined, - _attrs: _mutationObserverAttrsTextarea - } - ]; - - each(checks, function (index, check) { - elem = check._elem; - if (elem) { - each(check._attrs, function (index, attr) { - curr = attr.charAt(0) === ':' ? elem.is(attr) : elem.attr(attr); - cache = _updateAutoCache[attr]; - - if(checkCache(curr, cache)) { - changedAttrs.push(attr); - } - - _updateAutoCache[attr] = curr; - }); - } - }); - - updateViewportAttrsFromTarget(changedAttrs); - - return changedAttrs[LEXICON.l] > 0; - } - - /** - * Checks is a CSS Property of a child element is affecting the scroll size of the content. - * @param propertyName The CSS property name. - * @returns {boolean} True if the property is affecting the content scroll size, false otherwise. - */ - function isSizeAffectingCSSProperty(propertyName) { - if (!_initialized) - return true; - var flexGrow = 'flex-grow'; - var flexShrink = 'flex-shrink'; - var flexBasis = 'flex-basis'; - var affectingPropsX = [ - _strWidth, - _strMinMinus + _strWidth, - _strMaxMinus + _strWidth, - _strMarginMinus + _strLeft, - _strMarginMinus + _strRight, - _strLeft, - _strRight, - 'font-weight', - 'word-spacing', - flexGrow, - flexShrink, - flexBasis - ]; - var affectingPropsXContentBox = [ - _strPaddingMinus + _strLeft, - _strPaddingMinus + _strRight, - _strBorderMinus + _strLeft + _strWidth, - _strBorderMinus + _strRight + _strWidth - ]; - var affectingPropsY = [ - _strHeight, - _strMinMinus + _strHeight, - _strMaxMinus + _strHeight, - _strMarginMinus + _strTop, - _strMarginMinus + _strBottom, - _strTop, - _strBottom, - 'line-height', - flexGrow, - flexShrink, - flexBasis - ]; - var affectingPropsYContentBox = [ - _strPaddingMinus + _strTop, - _strPaddingMinus + _strBottom, - _strBorderMinus + _strTop + _strWidth, - _strBorderMinus + _strBottom + _strWidth - ]; - var _strS = 's'; - var _strVS = 'v-s'; - var checkX = _overflowBehaviorCache.x === _strS || _overflowBehaviorCache.x === _strVS; - var checkY = _overflowBehaviorCache.y === _strS || _overflowBehaviorCache.y === _strVS; - var sizeIsAffected = false; - var checkPropertyName = function (arr, name) { - for (var i = 0; i < arr[LEXICON.l]; i++) { - if (arr[i] === name) - return true; - } - return false; - }; - - if (checkY) { - sizeIsAffected = checkPropertyName(affectingPropsY, propertyName); - if (!sizeIsAffected && !_isBorderBox) - sizeIsAffected = checkPropertyName(affectingPropsYContentBox, propertyName); - } - if (checkX && !sizeIsAffected) { - sizeIsAffected = checkPropertyName(affectingPropsX, propertyName); - if (!sizeIsAffected && !_isBorderBox) - sizeIsAffected = checkPropertyName(affectingPropsXContentBox, propertyName); - } - return sizeIsAffected; - } - - - //==== Update ====// - - /** - * Sets the attribute values of the viewport element to the values from the target element. - * The value of a attribute is only set if the attribute is whitelisted. - * @attrs attrs The array of attributes which shall be set or undefined if all whitelisted shall be set. - */ - function updateViewportAttrsFromTarget(attrs) { - attrs = attrs || _viewportAttrsFromTarget; - each(attrs, function (index, attr) { - if (COMPATIBILITY.inA(attr, _viewportAttrsFromTarget) > -1) { - var targetAttr = _targetElement.attr(attr); - if(type(targetAttr) == TYPES.s) { - _viewportElement.attr(attr, targetAttr); - } - else { - _viewportElement.removeAttr(attr); - } - } - }); - } - - /** - * Updates the variables and size of the textarea element, and manages the scroll on new line or new character. - */ - function textareaUpdate() { - if (!_sleeping) { - var wrapAttrOff = !_textareaAutoWrappingCache; - var minWidth = _viewportSize.w; - var minHeight = _viewportSize.h; - var css = {}; - var doMeasure = _widthAutoCache || wrapAttrOff; - var origWidth; - var width; - var origHeight; - var height; - - //reset min size - css[_strMinMinus + _strWidth] = _strEmpty; - css[_strMinMinus + _strHeight] = _strEmpty; - - //set width auto - css[_strWidth] = _strAuto; - _targetElement.css(css); - - //measure width - origWidth = _targetElementNative[LEXICON.oW]; - width = doMeasure ? MATH.max(origWidth, _targetElementNative[LEXICON.sW] - 1) : 1; - /*width += (_widthAutoCache ? _marginX + (!_isBorderBox ? wrapAttrOff ? 0 : _paddingX + _borderX : 0) : 0);*/ - - //set measured width - css[_strWidth] = _widthAutoCache ? _strAuto /*width*/ : _strHundredPercent; - css[_strMinMinus + _strWidth] = _strHundredPercent; - - //set height auto - css[_strHeight] = _strAuto; - _targetElement.css(css); - - //measure height - origHeight = _targetElementNative[LEXICON.oH]; - height = MATH.max(origHeight, _targetElementNative[LEXICON.sH] - 1); - - //append correct size values - css[_strWidth] = width; - css[_strHeight] = height; - _textareaCoverElement.css(css); - - //apply min width / min height to prevent textarea collapsing - css[_strMinMinus + _strWidth] = minWidth /*+ (!_isBorderBox && _widthAutoCache ? _paddingX + _borderX : 0)*/; - css[_strMinMinus + _strHeight] = minHeight /*+ (!_isBorderBox && _heightAutoCache ? _paddingY + _borderY : 0)*/; - _targetElement.css(css); - - return { - _originalWidth: origWidth, - _originalHeight: origHeight, - _dynamicWidth: width, - _dynamicHeight: height - }; - } - } - - /** - * Updates the plugin and DOM to the current options. - * This method should only be called if a update is 100% required. - * @param updateHints A objects which contains hints for this update: - * { - * _hostSizeChanged : boolean, - * _contentSizeChanged : boolean, - * _force : boolean, == preventSwallowing - * _changedOptions : { }, == preventSwallowing && preventSleep - * } - */ - function update(updateHints) { - clearTimeout(_swallowedUpdateTimeout); - updateHints = updateHints || {}; - _swallowedUpdateHints._hostSizeChanged |= updateHints._hostSizeChanged; - _swallowedUpdateHints._contentSizeChanged |= updateHints._contentSizeChanged; - _swallowedUpdateHints._force |= updateHints._force; - - var now = COMPATIBILITY.now(); - var hostSizeChanged = !!_swallowedUpdateHints._hostSizeChanged; - var contentSizeChanged = !!_swallowedUpdateHints._contentSizeChanged; - var force = !!_swallowedUpdateHints._force; - var changedOptions = updateHints._changedOptions; - var swallow = _swallowUpdateLag > 0 && _initialized && !_destroyed && !force && !changedOptions && (now - _lastUpdateTime) < _swallowUpdateLag && (!_heightAutoCache && !_widthAutoCache); - var displayIsHidden; - - if (swallow) - _swallowedUpdateTimeout = setTimeout(update, _swallowUpdateLag); - - //abort update due to: - //destroyed - //swallowing - //sleeping - //host is hidden or has false display - if (_destroyed || swallow || (_sleeping && !changedOptions) || (_initialized && !force && (displayIsHidden = _hostElement.is(':hidden'))) || _hostElement.css('display') === 'inline') - return; - - _lastUpdateTime = now; - _swallowedUpdateHints = {}; - - //if scrollbar styling is possible and native scrollbars aren't overlaid the scrollbar styling will be applied which hides the native scrollbars completely. - if (_nativeScrollbarStyling && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { - //native scrollbars are hidden, so change the values to zero - _nativeScrollbarSize.x = 0; - _nativeScrollbarSize.y = 0; - } - else { - //refresh native scrollbar size (in case of zoom) - _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); - } - - // Scrollbar padding is needed for firefox, because firefox hides scrollbar automatically if the size of the div is too small. - // The calculation: [scrollbar size +3 *3] - // (+3 because of possible decoration e.g. borders, margins etc., but only if native scrollbar is NOT a overlaid scrollbar) - // (*3 because (1)increase / (2)decrease -button and (3)resize handle) - _nativeScrollbarMinSize = { - x: (_nativeScrollbarSize.x + (_nativeScrollbarIsOverlaid.x ? 0 : 3)) * 3, - y: (_nativeScrollbarSize.y + (_nativeScrollbarIsOverlaid.y ? 0 : 3)) * 3 - }; - - //changedOptions = changedOptions || { }; - //freezeResizeObserver(_sizeObserverElement, true); - //freezeResizeObserver(_sizeAutoObserverElement, true); - - var checkCacheAutoForce = function () { - return checkCache.apply(this, [].slice.call(arguments).concat([force])); - }; - - //save current scroll offset - var currScroll = { - x: _viewportElement[_strScrollLeft](), - y: _viewportElement[_strScrollTop]() - }; - - var currentPreparedOptionsScrollbars = _currentPreparedOptions.scrollbars; - var currentPreparedOptionsTextarea = _currentPreparedOptions.textarea; - - //scrollbars visibility: - var scrollbarsVisibility = currentPreparedOptionsScrollbars.visibility; - var scrollbarsVisibilityChanged = checkCacheAutoForce(scrollbarsVisibility, _scrollbarsVisibilityCache); - - //scrollbars autoHide: - var scrollbarsAutoHide = currentPreparedOptionsScrollbars.autoHide; - var scrollbarsAutoHideChanged = checkCacheAutoForce(scrollbarsAutoHide, _scrollbarsAutoHideCache); - - //scrollbars click scrolling - var scrollbarsClickScrolling = currentPreparedOptionsScrollbars.clickScrolling; - var scrollbarsClickScrollingChanged = checkCacheAutoForce(scrollbarsClickScrolling, _scrollbarsClickScrollingCache); - - //scrollbars drag scrolling - var scrollbarsDragScrolling = currentPreparedOptionsScrollbars.dragScrolling; - var scrollbarsDragScrollingChanged = checkCacheAutoForce(scrollbarsDragScrolling, _scrollbarsDragScrollingCache); - - //className - var className = _currentPreparedOptions.className; - var classNameChanged = checkCacheAutoForce(className, _classNameCache); - - //resize - var resize = _currentPreparedOptions.resize; - var resizeChanged = checkCacheAutoForce(resize, _resizeCache) && !_isBody; //body can't be resized since the window itself acts as resize possibility. - - //paddingAbsolute - var paddingAbsolute = _currentPreparedOptions.paddingAbsolute; - var paddingAbsoluteChanged = checkCacheAutoForce(paddingAbsolute, _paddingAbsoluteCache); - - //clipAlways - var clipAlways = _currentPreparedOptions.clipAlways; - var clipAlwaysChanged = checkCacheAutoForce(clipAlways, _clipAlwaysCache); - - //sizeAutoCapable - var sizeAutoCapable = _currentPreparedOptions.sizeAutoCapable && !_isBody; //body can never be size auto, because it shall be always as big as the viewport. - var sizeAutoCapableChanged = checkCacheAutoForce(sizeAutoCapable, _sizeAutoCapableCache); - - //showNativeScrollbars - var ignoreOverlayScrollbarHiding = _currentPreparedOptions.nativeScrollbarsOverlaid.showNativeScrollbars; - var ignoreOverlayScrollbarHidingChanged = checkCacheAutoForce(ignoreOverlayScrollbarHiding, _ignoreOverlayScrollbarHidingCache); - - //autoUpdate - var autoUpdate = _currentPreparedOptions.autoUpdate; - var autoUpdateChanged = checkCacheAutoForce(autoUpdate, _autoUpdateCache); - - //overflowBehavior - var overflowBehavior = _currentPreparedOptions.overflowBehavior; - var overflowBehaviorChanged = checkCacheAutoForce(overflowBehavior, _overflowBehaviorCache, force); - - //dynWidth: - var textareaDynWidth = currentPreparedOptionsTextarea.dynWidth; - var textareaDynWidthChanged = checkCacheAutoForce(_textareaDynWidthCache, textareaDynWidth); - - //dynHeight: - var textareaDynHeight = currentPreparedOptionsTextarea.dynHeight; - var textareaDynHeightChanged = checkCacheAutoForce(_textareaDynHeightCache, textareaDynHeight); - - //scrollbars visibility - _scrollbarsAutoHideNever = scrollbarsAutoHide === 'n'; - _scrollbarsAutoHideScroll = scrollbarsAutoHide === 's'; - _scrollbarsAutoHideMove = scrollbarsAutoHide === 'm'; - _scrollbarsAutoHideLeave = scrollbarsAutoHide === 'l'; - - //scrollbars autoHideDelay - _scrollbarsAutoHideDelay = currentPreparedOptionsScrollbars.autoHideDelay; - - //old className - _oldClassName = _classNameCache; - - //resize - _resizeNone = resize === 'n'; - _resizeBoth = resize === 'b'; - _resizeHorizontal = resize === 'h'; - _resizeVertical = resize === 'v'; - - //normalizeRTL - _normalizeRTLCache = _currentPreparedOptions.normalizeRTL; - - //ignore overlay scrollbar hiding - ignoreOverlayScrollbarHiding = ignoreOverlayScrollbarHiding && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y); - - //refresh options cache - _scrollbarsVisibilityCache = scrollbarsVisibility; - _scrollbarsAutoHideCache = scrollbarsAutoHide; - _scrollbarsClickScrollingCache = scrollbarsClickScrolling; - _scrollbarsDragScrollingCache = scrollbarsDragScrolling; - _classNameCache = className; - _resizeCache = resize; - _paddingAbsoluteCache = paddingAbsolute; - _clipAlwaysCache = clipAlways; - _sizeAutoCapableCache = sizeAutoCapable; - _ignoreOverlayScrollbarHidingCache = ignoreOverlayScrollbarHiding; - _autoUpdateCache = autoUpdate; - _overflowBehaviorCache = extendDeep({}, overflowBehavior); - _textareaDynWidthCache = textareaDynWidth; - _textareaDynHeightCache = textareaDynHeight; - _hasOverflowCache = _hasOverflowCache || { x: false, y: false }; - - //set correct class name to the host element - if (classNameChanged) { - removeClass(_hostElement, _oldClassName + _strSpace + _classNameThemeNone); - addClass(_hostElement, className !== undefined && className !== null && className.length > 0 ? className : _classNameThemeNone); - } - - //set correct auto Update - if (autoUpdateChanged) { - if (autoUpdate === true) { - disconnectMutationObservers(); - autoUpdateLoop.add(_base); - } - else if (autoUpdate === null) { - if (_autoUpdateRecommended) { - disconnectMutationObservers(); - autoUpdateLoop.add(_base); - } - else { - autoUpdateLoop.remove(_base); - connectMutationObservers(); - } - } - else { - autoUpdateLoop.remove(_base); - connectMutationObservers(); - } - } - - //activate or deactivate size auto capability - if (sizeAutoCapableChanged) { - if (sizeAutoCapable) { - if (!_contentGlueElement) { - _contentGlueElement = FRAMEWORK(generateDiv(_classNameContentGlueElement)); - _paddingElement.before(_contentGlueElement); - } - else { - _contentGlueElement.show(); - } - if (_sizeAutoObserverAdded) { - _sizeAutoObserverElement.show(); - } - else { - _sizeAutoObserverElement = FRAMEWORK(generateDiv(_classNameSizeAutoObserverElement)); - _sizeAutoObserverElementNative = _sizeAutoObserverElement[0]; - - _contentGlueElement.before(_sizeAutoObserverElement); - var oldSize = { w: -1, h: -1 }; - setupResizeObserver(_sizeAutoObserverElement, function () { - var newSize = { - w: _sizeAutoObserverElementNative[LEXICON.oW], - h: _sizeAutoObserverElementNative[LEXICON.oH] - }; - if (checkCache(newSize, oldSize)) { - if (_initialized && (_heightAutoCache && newSize.h > 0) || (_widthAutoCache && newSize.w > 0)) { - update(); - } - else if (_initialized && (!_heightAutoCache && newSize.h === 0) || (!_widthAutoCache && newSize.w === 0)) { - update(); - } - } - oldSize = newSize; - }); - _sizeAutoObserverAdded = true; - //fix heightAuto detector bug if height is fixed but contentHeight is 0. - //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. - if (_cssCalc !== null) - _sizeAutoObserverElement.css(_strHeight, _cssCalc + '(100% + 1px)'); - } - } - else { - if (_sizeAutoObserverAdded) - _sizeAutoObserverElement.hide(); - if (_contentGlueElement) - _contentGlueElement.hide(); - } - } - - //if force, update all resizeObservers too - if (force) { - _sizeObserverElement.find('*').trigger(_strScroll); - if (_sizeAutoObserverAdded) - _sizeAutoObserverElement.find('*').trigger(_strScroll); - } - - //display hidden: - displayIsHidden = displayIsHidden === undefined ? _hostElement.is(':hidden') : displayIsHidden; - var displayIsHiddenChanged = checkCacheAutoForce(displayIsHidden, _displayIsHiddenCache); - - //textarea AutoWrapping: - var textareaAutoWrapping = _isTextarea ? _targetElement.attr('wrap') !== 'off' : false; - var textareaAutoWrappingChanged = checkCacheAutoForce(textareaAutoWrapping, _textareaAutoWrappingCache); - - //detect direction: - var cssDirection = _hostElement.css('direction'); - var cssDirectionChanged = checkCacheAutoForce(cssDirection, _cssDirectionCache); - - //detect box-sizing: - var boxSizing = _hostElement.css('box-sizing'); - var boxSizingChanged = checkCacheAutoForce(boxSizing, _cssBoxSizingCache); - - //detect padding: - var padding = { - c: force, - t: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strTop)), - r: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strRight)), - b: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strBottom)), - l: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strLeft)) - }; - - //width + height auto detecting var: - var sizeAutoObserverElementBCRect; - //exception occurs in IE8 sometimes (unknown exception) - try { - sizeAutoObserverElementBCRect = _sizeAutoObserverAdded ? _sizeAutoObserverElementNative[LEXICON.bCR]() : null; - } catch (ex) { - return; - } - - _isRTL = cssDirection === 'rtl'; - _isBorderBox = (boxSizing === 'border-box'); - var isRTLLeft = _isRTL ? _strLeft : _strRight; - var isRTLRight = _isRTL ? _strRight : _strLeft; - - //detect width auto: - var widthAutoResizeDetection = false; - var widthAutoObserverDetection = (_sizeAutoObserverAdded && (_hostElement.css(_strFloat) !== 'none' /*|| _isTextarea */)) ? (MATH.round(sizeAutoObserverElementBCRect.right - sizeAutoObserverElementBCRect.left) === 0) && (!paddingAbsolute ? (_hostElementNative[LEXICON.cW] - _paddingX) > 0 : true) : false; - if (sizeAutoCapable && !widthAutoObserverDetection) { - var tmpCurrHostWidth = _hostElementNative[LEXICON.oW]; - var tmpCurrContentGlueWidth = _contentGlueElement.css(_strWidth); - _contentGlueElement.css(_strWidth, _strAuto); - - var tmpNewHostWidth = _hostElementNative[LEXICON.oW]; - _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); - widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; - if (!widthAutoResizeDetection) { - _contentGlueElement.css(_strWidth, tmpCurrHostWidth + 1); - tmpNewHostWidth = _hostElementNative[LEXICON.oW]; - _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); - widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; - } - } - var widthAuto = (widthAutoObserverDetection || widthAutoResizeDetection) && sizeAutoCapable && !displayIsHidden; - var widthAutoChanged = checkCacheAutoForce(widthAuto, _widthAutoCache); - var wasWidthAuto = !widthAuto && _widthAutoCache; - - //detect height auto: - var heightAuto = _sizeAutoObserverAdded && sizeAutoCapable && !displayIsHidden ? (MATH.round(sizeAutoObserverElementBCRect.bottom - sizeAutoObserverElementBCRect.top) === 0) /* && (!paddingAbsolute && (_msieVersion > 9 || !_msieVersion) ? true : true) */ : false; - var heightAutoChanged = checkCacheAutoForce(heightAuto, _heightAutoCache); - var wasHeightAuto = !heightAuto && _heightAutoCache; - - //detect border: - //we need the border only if border box and auto size - var strMinusWidth = '-' + _strWidth; - var updateBorderX = (widthAuto && _isBorderBox) || !_isBorderBox; - var updateBorderY = (heightAuto && _isBorderBox) || !_isBorderBox; - var border = { - c: force, - t: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strTop + strMinusWidth), true) : 0, - r: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strRight + strMinusWidth), true) : 0, - b: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strBottom + strMinusWidth), true) : 0, - l: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strLeft + strMinusWidth), true) : 0 - }; - - //detect margin: - var margin = { - c: force, - t: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strTop)), - r: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strRight)), - b: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strBottom)), - l: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strLeft)) - }; - - //detect css max width & height: - var cssMaxValue = { - h: String(_hostElement.css(_strMaxMinus + _strHeight)), - w: String(_hostElement.css(_strMaxMinus + _strWidth)) - }; - - //vars to apply correct css - var contentElementCSS = {}; - var contentGlueElementCSS = {}; - - //funcs - var getHostSize = function () { - //has to be clientSize because offsetSize respect borders - return { - w: _hostElementNative[LEXICON.cW], - h: _hostElementNative[LEXICON.cH] - }; - }; - var getViewportSize = function () { - //viewport size is padding container because it never has padding, margin and a border - //determine zoom rounding error -> sometimes scrollWidth/Height is smaller than clientWidth/Height - //if this happens add the difference to the viewportSize to compensate the rounding error - return { - w: _paddingElementNative[LEXICON.oW] + MATH.max(0, _contentElementNative[LEXICON.cW] - _contentElementNative[LEXICON.sW]), - h: _paddingElementNative[LEXICON.oH] + MATH.max(0, _contentElementNative[LEXICON.cH] - _contentElementNative[LEXICON.sH]) - }; - }; - - //set info for padding - var paddingAbsoluteX = _paddingX = padding.l + padding.r; - var paddingAbsoluteY = _paddingY = padding.t + padding.b; - paddingAbsoluteX *= paddingAbsolute ? 1 : 0; - paddingAbsoluteY *= paddingAbsolute ? 1 : 0; - padding.c = checkCacheAutoForce(padding, _cssPaddingCache); - - //set info for border - _borderX = border.l + border.r; - _borderY = border.t + border.b; - border.c = checkCacheAutoForce(border, _cssBorderCache); - - //set info for margin - _marginX = margin.l + margin.r; - _marginY = margin.t + margin.b; - margin.c = checkCacheAutoForce(margin, _cssMarginCache); - - //set info for css max value - cssMaxValue.ih = parseToZeroOrNumber(cssMaxValue.h); //ih = integer height - cssMaxValue.iw = parseToZeroOrNumber(cssMaxValue.w); //iw = integer width - cssMaxValue.ch = cssMaxValue.h.indexOf('px') > -1; //ch = correct height - cssMaxValue.cw = cssMaxValue.w.indexOf('px') > -1; //cw = correct width - cssMaxValue.c = checkCacheAutoForce(cssMaxValue, _cssMaxValueCache); - - //refresh cache - _displayIsHiddenCache = displayIsHidden; - _textareaAutoWrappingCache = textareaAutoWrapping; - _cssDirectionCache = cssDirection; - _cssBoxSizingCache = boxSizing; - _widthAutoCache = widthAuto; - _heightAutoCache = heightAuto; - _cssPaddingCache = padding; - _cssBorderCache = border; - _cssMarginCache = margin; - _cssMaxValueCache = cssMaxValue; - - //IEFix direction changed - if (cssDirectionChanged && _sizeAutoObserverAdded) - _sizeAutoObserverElement.css(_strFloat, isRTLRight); - - //apply padding: - if (padding.c || cssDirectionChanged || paddingAbsoluteChanged || widthAutoChanged || heightAutoChanged || boxSizingChanged || sizeAutoCapableChanged) { - var paddingElementCSS = {}; - var textareaCSS = {}; - setTopRightBottomLeft(contentGlueElementCSS, _strMarginMinus, [-padding.t, -padding.r, -padding.b, -padding.l]); - if (paddingAbsolute) { - setTopRightBottomLeft(paddingElementCSS, _strEmpty, [padding.t, padding.r, padding.b, padding.l]); - if (_isTextarea) - setTopRightBottomLeft(textareaCSS, _strPaddingMinus); - else - setTopRightBottomLeft(contentElementCSS, _strPaddingMinus); - } - else { - setTopRightBottomLeft(paddingElementCSS, _strEmpty); - if (_isTextarea) - setTopRightBottomLeft(textareaCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); - else - setTopRightBottomLeft(contentElementCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); - } - _paddingElement.css(paddingElementCSS); - _targetElement.css(textareaCSS); - } - - //viewport size is padding container because it never has padding, margin and a border. - _viewportSize = getViewportSize(); - - //update Textarea - var textareaSize = _isTextarea ? textareaUpdate() : false; - var textareaSizeChanged = _isTextarea && checkCacheAutoForce(textareaSize, _textareaSizeCache); - var textareaDynOrigSize = _isTextarea && textareaSize ? { - w: textareaDynWidth ? textareaSize._dynamicWidth : textareaSize._originalWidth, - h: textareaDynHeight ? textareaSize._dynamicHeight : textareaSize._originalHeight - } : {}; - _textareaSizeCache = textareaSize; - - //fix height auto / width auto in cooperation with current padding & boxSizing behavior: - if (heightAuto && (heightAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c)) { - /* - if (cssMaxValue.ch) - contentElementCSS[_strMaxMinus + _strHeight] = - (cssMaxValue.ch ? (cssMaxValue.ih - paddingAbsoluteY + (_isBorderBox ? -_borderY : _paddingY)) - : _strEmpty); - */ - contentElementCSS[_strHeight] = _strAuto; - } - else if (heightAutoChanged || paddingAbsoluteChanged) { - contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; - contentElementCSS[_strHeight] = _strHundredPercent; - } - if (widthAuto && (widthAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c || cssDirectionChanged)) { - /* - if (cssMaxValue.cw) - contentElementCSS[_strMaxMinus + _strWidth] = - (cssMaxValue.cw ? (cssMaxValue.iw - paddingAbsoluteX + (_isBorderBox ? -_borderX : _paddingX)) + - (_nativeScrollbarIsOverlaid.y ? _overlayScrollbarDummySize.y : 0) - : _strEmpty); - */ - contentElementCSS[_strWidth] = _strAuto; - contentGlueElementCSS[_strMaxMinus + _strWidth] = _strHundredPercent; //IE Fix - } - else if (widthAutoChanged || paddingAbsoluteChanged) { - contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; - contentElementCSS[_strWidth] = _strHundredPercent; - contentElementCSS[_strFloat] = _strEmpty; - contentGlueElementCSS[_strMaxMinus + _strWidth] = _strEmpty; //IE Fix - } - if (widthAuto) { - if (!cssMaxValue.cw) - contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; - //textareaDynOrigSize.w || _strAuto :: doesnt works because applied margin will shift width - contentGlueElementCSS[_strWidth] = _strAuto; - - contentElementCSS[_strWidth] = _strAuto; - contentElementCSS[_strFloat] = isRTLRight; - } - else { - contentGlueElementCSS[_strWidth] = _strEmpty; - } - if (heightAuto) { - if (!cssMaxValue.ch) - contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; - //textareaDynOrigSize.h || _contentElementNative[LEXICON.cH] :: use for anti scroll jumping - contentGlueElementCSS[_strHeight] = textareaDynOrigSize.h || _contentElementNative[LEXICON.cH]; - } - else { - contentGlueElementCSS[_strHeight] = _strEmpty; - } - if (sizeAutoCapable) - _contentGlueElement.css(contentGlueElementCSS); - _contentElement.css(contentElementCSS); - - //CHECKPOINT HERE ~ - contentElementCSS = {}; - contentGlueElementCSS = {}; - - //if [content(host) client / scroll size, or target element direction, or content(host) max-sizes] changed, or force is true - if (hostSizeChanged || contentSizeChanged || textareaSizeChanged || cssDirectionChanged || boxSizingChanged || paddingAbsoluteChanged || widthAutoChanged || widthAuto || heightAutoChanged || heightAuto || cssMaxValue.c || ignoreOverlayScrollbarHidingChanged || overflowBehaviorChanged || clipAlwaysChanged || resizeChanged || scrollbarsVisibilityChanged || scrollbarsAutoHideChanged || scrollbarsDragScrollingChanged || scrollbarsClickScrollingChanged || textareaDynWidthChanged || textareaDynHeightChanged || textareaAutoWrappingChanged) { - var strOverflow = 'overflow'; - var strOverflowX = strOverflow + '-x'; - var strOverflowY = strOverflow + '-y'; - var strHidden = 'hidden'; - var strVisible = 'visible'; - - //Reset the viewport (very important for natively overlaid scrollbars and zoom change - //don't change the overflow prop as it is very expensive and affects performance !A LOT! - if(!_nativeScrollbarStyling) { - var viewportElementResetCSS = {}; - var resetXTmp = _hasOverflowCache.y && _hideOverflowCache.ys && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.y ? _viewportElement.css(isRTLLeft) : -_nativeScrollbarSize.y) : 0; - var resetBottomTmp = _hasOverflowCache.x && _hideOverflowCache.xs && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.x ? _viewportElement.css(_strBottom) : -_nativeScrollbarSize.x) : 0; - setTopRightBottomLeft(viewportElementResetCSS, _strEmpty); - _viewportElement.css(viewportElementResetCSS); - } - - //measure several sizes: - var contentMeasureElement = getContentMeasureElement(); - //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 - var contentSize = { - //use clientSize because natively overlaidScrollbars add borders - w: textareaDynOrigSize.w || contentMeasureElement[LEXICON.cW], - h: textareaDynOrigSize.h || contentMeasureElement[LEXICON.cH] - }; - var scrollSize = { - w: contentMeasureElement[LEXICON.sW], - h: contentMeasureElement[LEXICON.sH] - }; - - //apply the correct viewport style and measure viewport size - if(!_nativeScrollbarStyling) { - viewportElementResetCSS[_strBottom] = wasHeightAuto ? _strEmpty : resetBottomTmp; - viewportElementResetCSS[isRTLLeft] = wasWidthAuto ? _strEmpty : resetXTmp; - _viewportElement.css(viewportElementResetCSS); - } - _viewportSize = getViewportSize(); - - //measure and correct several sizes - var hostSize = getHostSize(); - var contentGlueSize = { - //client/scrollSize + AbsolutePadding -> because padding is only applied to the paddingElement if its absolute, so you have to add it manually - //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 - w: MATH.max((widthAuto ? contentSize.w : scrollSize.w) + paddingAbsoluteX, hostSize.w), - h: MATH.max((heightAuto ? contentSize.h : scrollSize.h) + paddingAbsoluteY, hostSize.h) - }; - contentGlueSize.c = checkCacheAutoForce(contentGlueSize, _contentGlueSizeCache); - _contentGlueSizeCache = contentGlueSize; - - //apply correct contentGlue size - if (sizeAutoCapable) { - //size contentGlue correctly to make sure the element has correct size if the sizing switches to auto - if (contentGlueSize.c || (heightAuto || widthAuto)) { - contentGlueElementCSS[_strWidth] = contentGlueSize.w; - contentGlueElementCSS[_strHeight] = contentGlueSize.h; - - //textarea-sizes are already calculated correctly at this point - if (!_isTextarea) { - contentSize = { - //use clientSize because natively overlaidScrollbars add borders - w: contentMeasureElement[LEXICON.cW], - h: contentMeasureElement[LEXICON.cH] - }; - } - } - var textareaCoverCSS = {}; - var setContentGlueElementCSSfunction = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var wh = scrollbarVars._w_h; - var strWH = scrollbarVars._width_height; - var autoSize = horizontal ? widthAuto : heightAuto; - var borderSize = horizontal ? _borderX : _borderY; - var paddingSize = horizontal ? _paddingX : _paddingY; - var marginSize = horizontal ? _marginX : _marginY; - var maxSize = contentGlueElementCSS[strWH] + (_isBorderBox ? borderSize : -paddingSize); - - //make contentGlue size -1 if element is not auto sized, to make sure that a resize event happens when the element shrinks - if (!autoSize || (!autoSize && border.c)) - contentGlueElementCSS[strWH] = hostSize[wh] - (_isBorderBox ? 0 : paddingSize + borderSize) - 1 - marginSize; - - //if size is auto and host is same size as max size, make content glue size +1 to make sure size changes will be detected - if (autoSize && cssMaxValue['c' + wh] && cssMaxValue['i' + wh] === maxSize) - contentGlueElementCSS[strWH] = maxSize + (_isBorderBox ? 0 : paddingSize) + 1; - - //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) - if (autoSize && (contentSize[wh] < _viewportSize[wh]) && (horizontal && _isTextarea ? !textareaAutoWrapping : true)) { - if (_isTextarea) - textareaCoverCSS[strWH] = parseToZeroOrNumber(_textareaCoverElement.css(strWH)) - 1; - contentGlueElementCSS[strWH] -= 1; - } - - //make sure content glue size is at least 1 - if (contentSize[wh] > 0) - contentGlueElementCSS[strWH] = MATH.max(1, contentGlueElementCSS[strWH]); - }; - setContentGlueElementCSSfunction(true); - setContentGlueElementCSSfunction(false); - - if (_isTextarea) - _textareaCoverElement.css(textareaCoverCSS); - _contentGlueElement.css(contentGlueElementCSS); - } - if (widthAuto) - contentElementCSS[_strWidth] = _strHundredPercent; - if (widthAuto && !_isBorderBox && !_mutationObserversConnected) - contentElementCSS[_strFloat] = 'none'; - - //apply and reset content style - _contentElement.css(contentElementCSS); - contentElementCSS = {}; - - //measure again, but this time all correct sizes: - var contentScrollSize = { - w: contentMeasureElement[LEXICON.sW], - h: contentMeasureElement[LEXICON.sH], - }; - contentScrollSize.c = contentSizeChanged = checkCacheAutoForce(contentScrollSize, _contentScrollSizeCache); - _contentScrollSizeCache = contentScrollSize; - - //refresh viewport size after correct measuring - _viewportSize = getViewportSize(); - - hostSize = getHostSize(); - hostSizeChanged = checkCacheAutoForce(hostSize, _hostSizeCache); - _hostSizeCache = hostSize; - - var hideOverflowForceTextarea = _isTextarea && (_viewportSize.w === 0 || _viewportSize.h === 0); - var previousOverflowAmount = _overflowAmountCache; - var overflowBehaviorIsVS = {}; - var overflowBehaviorIsVH = {}; - var overflowBehaviorIsS = {}; - var overflowAmount = {}; - var hasOverflow = {}; - var hideOverflow = {}; - var canScroll = {}; - var viewportRect = _paddingElementNative[LEXICON.bCR](); - var setOverflowVariables = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var scrollbarVarsInverted = getScrollbarVars(!horizontal); - var xyI = scrollbarVarsInverted._x_y; - var xy = scrollbarVars._x_y; - var wh = scrollbarVars._w_h; - var widthHeight = scrollbarVars._width_height; - var scrollMax = _strScroll + scrollbarVars._Left_Top + 'Max'; - var fractionalOverflowAmount = viewportRect[widthHeight] ? MATH.abs(viewportRect[widthHeight] - _viewportSize[wh]) : 0; - var checkFractionalOverflowAmount = previousOverflowAmount && previousOverflowAmount[xy] > 0 && _viewportElementNative[scrollMax] === 0; - overflowBehaviorIsVS[xy] = overflowBehavior[xy] === 'v-s'; - overflowBehaviorIsVH[xy] = overflowBehavior[xy] === 'v-h'; - overflowBehaviorIsS[xy] = overflowBehavior[xy] === 's'; - overflowAmount[xy] = MATH.max(0, MATH.round((contentScrollSize[wh] - _viewportSize[wh]) * 100) / 100); - overflowAmount[xy] *= (hideOverflowForceTextarea || (checkFractionalOverflowAmount && fractionalOverflowAmount > 0 && fractionalOverflowAmount < 1)) ? 0 : 1; - hasOverflow[xy] = overflowAmount[xy] > 0; - - //hideOverflow: - //x || y : true === overflow is hidden by "overflow: scroll" OR "overflow: hidden" - //xs || ys : true === overflow is hidden by "overflow: scroll" - hideOverflow[xy] = overflowBehaviorIsVS[xy] || overflowBehaviorIsVH[xy] ? (hasOverflow[xyI] && !overflowBehaviorIsVS[xyI] && !overflowBehaviorIsVH[xyI]) : hasOverflow[xy]; - hideOverflow[xy + 's'] = hideOverflow[xy] ? (overflowBehaviorIsS[xy] || overflowBehaviorIsVS[xy]) : false; - - canScroll[xy] = hasOverflow[xy] && hideOverflow[xy + 's']; - }; - setOverflowVariables(true); - setOverflowVariables(false); - - overflowAmount.c = checkCacheAutoForce(overflowAmount, _overflowAmountCache); - _overflowAmountCache = overflowAmount; - hasOverflow.c = checkCacheAutoForce(hasOverflow, _hasOverflowCache); - _hasOverflowCache = hasOverflow; - hideOverflow.c = checkCacheAutoForce(hideOverflow, _hideOverflowCache); - _hideOverflowCache = hideOverflow; - - //if native scrollbar is overlay at x OR y axis, prepare DOM - if (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y) { - var borderDesign = 'px solid transparent'; - var contentArrangeElementCSS = {}; - var arrangeContent = {}; - var arrangeChanged = force; - var setContentElementCSS; - - if (hasOverflow.x || hasOverflow.y) { - arrangeContent.w = _nativeScrollbarIsOverlaid.y && hasOverflow.y ? contentScrollSize.w + _overlayScrollbarDummySize.y : _strEmpty; - arrangeContent.h = _nativeScrollbarIsOverlaid.x && hasOverflow.x ? contentScrollSize.h + _overlayScrollbarDummySize.x : _strEmpty; - arrangeChanged = checkCacheAutoForce(arrangeContent, _arrangeContentSizeCache); - _arrangeContentSizeCache = arrangeContent; - } - - if (hasOverflow.c || hideOverflow.c || contentScrollSize.c || cssDirectionChanged || widthAutoChanged || heightAutoChanged || widthAuto || heightAuto || ignoreOverlayScrollbarHidingChanged) { - contentElementCSS[_strMarginMinus + isRTLRight] = contentElementCSS[_strBorderMinus + isRTLRight] = _strEmpty; - setContentElementCSS = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var scrollbarVarsInverted = getScrollbarVars(!horizontal); - var xy = scrollbarVars._x_y; - var strDirection = horizontal ? _strBottom : isRTLLeft; - var invertedAutoSize = horizontal ? heightAuto : widthAuto; - - if (_nativeScrollbarIsOverlaid[xy] && hasOverflow[xy] && hideOverflow[xy + 's']) { - contentElementCSS[_strMarginMinus + strDirection] = invertedAutoSize ? (ignoreOverlayScrollbarHiding ? _strEmpty : _overlayScrollbarDummySize[xy]) : _strEmpty; - contentElementCSS[_strBorderMinus + strDirection] = ((horizontal ? !invertedAutoSize : true) && !ignoreOverlayScrollbarHiding) ? (_overlayScrollbarDummySize[xy] + borderDesign) : _strEmpty; - } - else { - arrangeContent[scrollbarVarsInverted._w_h] = - contentElementCSS[_strMarginMinus + strDirection] = - contentElementCSS[_strBorderMinus + strDirection] = _strEmpty; - arrangeChanged = true; - } - }; - - if (_nativeScrollbarStyling) { - if (ignoreOverlayScrollbarHiding) - removeClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); - else - addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); - } - else { - setContentElementCSS(true); - setContentElementCSS(false); - } - } - if (ignoreOverlayScrollbarHiding) { - arrangeContent.w = arrangeContent.h = _strEmpty; - arrangeChanged = true; - } - if (arrangeChanged && !_nativeScrollbarStyling) { - contentArrangeElementCSS[_strWidth] = hideOverflow.y ? arrangeContent.w : _strEmpty; - contentArrangeElementCSS[_strHeight] = hideOverflow.x ? arrangeContent.h : _strEmpty; - - if (!_contentArrangeElement) { - _contentArrangeElement = FRAMEWORK(generateDiv(_classNameContentArrangeElement)); - _viewportElement.prepend(_contentArrangeElement); - } - _contentArrangeElement.css(contentArrangeElementCSS); - } - _contentElement.css(contentElementCSS); - } - - var viewportElementCSS = {}; - var paddingElementCSS = {}; - var setViewportCSS; - if (hostSizeChanged || hasOverflow.c || hideOverflow.c || contentScrollSize.c || overflowBehaviorChanged || boxSizingChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged || clipAlwaysChanged || heightAutoChanged) { - viewportElementCSS[isRTLRight] = _strEmpty; - setViewportCSS = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var scrollbarVarsInverted = getScrollbarVars(!horizontal); - var xy = scrollbarVars._x_y; - var XY = scrollbarVars._X_Y; - var strDirection = horizontal ? _strBottom : isRTLLeft; - - var reset = function () { - viewportElementCSS[strDirection] = _strEmpty; - _contentBorderSize[scrollbarVarsInverted._w_h] = 0; - }; - if (hasOverflow[xy] && hideOverflow[xy + 's']) { - viewportElementCSS[strOverflow + XY] = _strScroll; - if (ignoreOverlayScrollbarHiding || _nativeScrollbarStyling) { - reset(); - } - else { - viewportElementCSS[strDirection] = -(_nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[xy] : _nativeScrollbarSize[xy]); - _contentBorderSize[scrollbarVarsInverted._w_h] = _nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[scrollbarVarsInverted._x_y] : 0; - } - } else { - viewportElementCSS[strOverflow + XY] = _strEmpty; - reset(); - } - }; - setViewportCSS(true); - setViewportCSS(false); - - // if the scroll container is too small and if there is any overflow with no overlay scrollbar (and scrollbar styling isn't possible), - // make viewport element greater in size (Firefox hide Scrollbars fix) - // because firefox starts hiding scrollbars on too small elements - // with this behavior the overflow calculation may be incorrect or the scrollbars would appear suddenly - // https://bugzilla.mozilla.org/show_bug.cgi?id=292284 - if (!_nativeScrollbarStyling - && (_viewportSize.h < _nativeScrollbarMinSize.x || _viewportSize.w < _nativeScrollbarMinSize.y) - && ((hasOverflow.x && hideOverflow.x && !_nativeScrollbarIsOverlaid.x) || (hasOverflow.y && hideOverflow.y && !_nativeScrollbarIsOverlaid.y))) { - viewportElementCSS[_strPaddingMinus + _strTop] = _nativeScrollbarMinSize.x; - viewportElementCSS[_strMarginMinus + _strTop] = -_nativeScrollbarMinSize.x; - - viewportElementCSS[_strPaddingMinus + isRTLRight] = _nativeScrollbarMinSize.y; - viewportElementCSS[_strMarginMinus + isRTLRight] = -_nativeScrollbarMinSize.y; - } - else { - viewportElementCSS[_strPaddingMinus + _strTop] = - viewportElementCSS[_strMarginMinus + _strTop] = - viewportElementCSS[_strPaddingMinus + isRTLRight] = - viewportElementCSS[_strMarginMinus + isRTLRight] = _strEmpty; - } - viewportElementCSS[_strPaddingMinus + isRTLLeft] = - viewportElementCSS[_strMarginMinus + isRTLLeft] = _strEmpty; - - //if there is any overflow (x OR y axis) and this overflow shall be hidden, make overflow hidden, else overflow visible - if ((hasOverflow.x && hideOverflow.x) || (hasOverflow.y && hideOverflow.y) || hideOverflowForceTextarea) { - //only hide if is Textarea - if (_isTextarea && hideOverflowForceTextarea) { - paddingElementCSS[strOverflowX] = - paddingElementCSS[strOverflowY] = strHidden; - } - } - else { - if (!clipAlways || (overflowBehaviorIsVH.x || overflowBehaviorIsVS.x || overflowBehaviorIsVH.y || overflowBehaviorIsVS.y)) { - //only un-hide if Textarea - if (_isTextarea) { - paddingElementCSS[strOverflowX] = - paddingElementCSS[strOverflowY] = _strEmpty; - } - viewportElementCSS[strOverflowX] = - viewportElementCSS[strOverflowY] = strVisible; - } - } - - _paddingElement.css(paddingElementCSS); - _viewportElement.css(viewportElementCSS); - viewportElementCSS = {}; - - //force soft redraw in webkit because without the scrollbars will may appear because DOM wont be redrawn under special conditions - if ((hasOverflow.c || boxSizingChanged || widthAutoChanged || heightAutoChanged) && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { - var elementStyle = _contentElementNative[LEXICON.s]; - var dump; - elementStyle.webkitTransform = 'scale(1)'; - elementStyle.display = 'run-in'; - dump = _contentElementNative[LEXICON.oH]; - elementStyle.display = _strEmpty; //|| dump; //use dump to prevent it from deletion if minify - elementStyle.webkitTransform = _strEmpty; - } - /* - //force hard redraw in webkit if native overlaid scrollbars shall appear - if (ignoreOverlayScrollbarHidingChanged && ignoreOverlayScrollbarHiding) { - _hostElement.hide(); - var dump = _hostElementNative[LEXICON.oH]; - _hostElement.show(); - } - */ - } - - //change to direction RTL and width auto Bugfix in Webkit - //without this fix, the DOM still thinks the scrollbar is LTR and thus the content is shifted to the left - contentElementCSS = {}; - if (cssDirectionChanged || widthAutoChanged || heightAutoChanged) { - if (_isRTL && widthAuto) { - var floatTmp = _contentElement.css(_strFloat); - var posLeftWithoutFloat = MATH.round(_contentElement.css(_strFloat, _strEmpty).css(_strLeft, _strEmpty).position().left); - _contentElement.css(_strFloat, floatTmp); - var posLeftWithFloat = MATH.round(_contentElement.position().left); - - if (posLeftWithoutFloat !== posLeftWithFloat) - contentElementCSS[_strLeft] = posLeftWithoutFloat; - } - else { - contentElementCSS[_strLeft] = _strEmpty; - } - } - _contentElement.css(contentElementCSS); - - //handle scroll position - if (_isTextarea && contentSizeChanged) { - var textareaInfo = getTextareaInfo(); - if (textareaInfo) { - var textareaRowsChanged = _textareaInfoCache === undefined ? true : textareaInfo._rows !== _textareaInfoCache._rows; - var cursorRow = textareaInfo._cursorRow; - var cursorCol = textareaInfo._cursorColumn; - var widestRow = textareaInfo._widestRow; - var lastRow = textareaInfo._rows; - var lastCol = textareaInfo._columns; - var cursorPos = textareaInfo._cursorPosition; - var cursorMax = textareaInfo._cursorMax; - var cursorIsLastPosition = (cursorPos >= cursorMax && _textareaHasFocus); - var textareaScrollAmount = { - x: (!textareaAutoWrapping && (cursorCol === lastCol && cursorRow === widestRow)) ? _overflowAmountCache.x : -1, - y: (textareaAutoWrapping ? cursorIsLastPosition || textareaRowsChanged && (previousOverflowAmount ? (currScroll.y === previousOverflowAmount.y) : false) : (cursorIsLastPosition || textareaRowsChanged) && cursorRow === lastRow) ? _overflowAmountCache.y : -1 - }; - currScroll.x = textareaScrollAmount.x > -1 ? (_isRTL && _normalizeRTLCache && _rtlScrollBehavior.i ? 0 : textareaScrollAmount.x) : currScroll.x; //if inverted, scroll to 0 -> normalized this means to max scroll offset. - currScroll.y = textareaScrollAmount.y > -1 ? textareaScrollAmount.y : currScroll.y; - } - _textareaInfoCache = textareaInfo; - } - if (_isRTL && _rtlScrollBehavior.i && _nativeScrollbarIsOverlaid.y && hasOverflow.x && _normalizeRTLCache) - currScroll.x += _contentBorderSize.w || 0; - if (widthAuto) - _hostElement[_strScrollLeft](0); - if (heightAuto) - _hostElement[_strScrollTop](0); - _viewportElement[_strScrollLeft](currScroll.x)[_strScrollTop](currScroll.y); - - //scrollbars management: - var scrollbarsVisibilityVisible = scrollbarsVisibility === 'v'; - var scrollbarsVisibilityHidden = scrollbarsVisibility === 'h'; - var scrollbarsVisibilityAuto = scrollbarsVisibility === 'a'; - - var showScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, true, canScroll.x); - var showScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, true, canScroll.y); - var hideScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, false, canScroll.x); - var hideScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, false, canScroll.y); - - //manage class name which indicates scrollable overflow - if (hideOverflow.x || hideOverflow.y) - addClass(_hostElement, _classNameHostOverflow); - else - removeClass(_hostElement, _classNameHostOverflow); - if (hideOverflow.x) - addClass(_hostElement, _classNameHostOverflowX); - else - removeClass(_hostElement, _classNameHostOverflowX); - if (hideOverflow.y) - addClass(_hostElement, _classNameHostOverflowY); - else - removeClass(_hostElement, _classNameHostOverflowY); - - //add or remove rtl class name for styling purposes - if (cssDirectionChanged) { - if (_isRTL) - addClass(_hostElement, _classNameHostRTL); - else - removeClass(_hostElement, _classNameHostRTL); - } - - //manage the resize feature (CSS3 resize "polyfill" for this plugin) - if (_isBody) - addClass(_hostElement, _classNameHostResizeDisabled); - if (resizeChanged) { - removeClass(_scrollbarCornerElement, [ - _classNameScrollbarCornerResize, - _classNameScrollbarCornerResizeB, - _classNameScrollbarCornerResizeH, - _classNameScrollbarCornerResizeV].join(_strSpace)); - if (_resizeNone) { - addClass(_hostElement, _classNameHostResizeDisabled); - } - else { - removeClass(_hostElement, _classNameHostResizeDisabled); - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResize); - if (_resizeBoth) - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeB); - else if (_resizeHorizontal) - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeH); - else if (_resizeVertical) - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeV); - } - } - - //manage the scrollbars general visibility + the scrollbar interactivity (unusable class name) - if (scrollbarsVisibilityChanged || overflowBehaviorChanged || hideOverflow.c || hasOverflow.c || ignoreOverlayScrollbarHidingChanged) { - if (ignoreOverlayScrollbarHiding) { - if (ignoreOverlayScrollbarHidingChanged) { - removeClass(_hostElement, _classNameHostScrolling); - if (ignoreOverlayScrollbarHiding) { - hideScrollbarH(); - hideScrollbarV(); - } - } - } - else if (scrollbarsVisibilityAuto) { - if (canScroll.x) - showScrollbarH(); - else - hideScrollbarH(); - - if (canScroll.y) - showScrollbarV(); - else - hideScrollbarV(); - } - else if (scrollbarsVisibilityVisible) { - showScrollbarH(); - showScrollbarV(); - } - else if (scrollbarsVisibilityHidden) { - hideScrollbarH(); - hideScrollbarV(); - } - } - - //manage the scrollbars auto hide feature (auto hide them after specific actions) - if (scrollbarsAutoHideChanged || ignoreOverlayScrollbarHidingChanged) { - if (_scrollbarsAutoHideLeave || _scrollbarsAutoHideMove) { - setupHostMouseTouchEvents(true); - setupHostMouseTouchEvents(); - } - else { - setupHostMouseTouchEvents(true); - } - - if (_scrollbarsAutoHideNever) - refreshScrollbarsAutoHide(true); - else - refreshScrollbarsAutoHide(false, true); - } - - //manage scrollbars handle length & offset - don't remove! - if (hostSizeChanged || overflowAmount.c || heightAutoChanged || widthAutoChanged || resizeChanged || boxSizingChanged || paddingAbsoluteChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged) { - refreshScrollbarHandleLength(true); - refreshScrollbarHandleOffset(true); - refreshScrollbarHandleLength(false); - refreshScrollbarHandleOffset(false); - } - - //manage interactivity - if (scrollbarsClickScrollingChanged) - refreshScrollbarsInteractive(true, scrollbarsClickScrolling); - if (scrollbarsDragScrollingChanged) - refreshScrollbarsInteractive(false, scrollbarsDragScrolling); - - //callbacks: - if (cssDirectionChanged) { - dispatchCallback('onDirectionChanged', { - isRTL: _isRTL, - dir: cssDirection - }); - } - if (hostSizeChanged) { - dispatchCallback('onHostSizeChanged', { - width: _hostSizeCache.w, - height: _hostSizeCache.h - }); - } - if (contentSizeChanged) { - dispatchCallback('onContentSizeChanged', { - width: _contentScrollSizeCache.w, - height: _contentScrollSizeCache.h - }); - } - if (hasOverflow.c || hideOverflow.c) { - dispatchCallback('onOverflowChanged', { - x: hasOverflow.x, - y: hasOverflow.y, - xScrollable: hideOverflow.xs, - yScrollable: hideOverflow.ys, - clipped: hideOverflow.x || hideOverflow.y - }); - } - if (overflowAmount.c) { - dispatchCallback('onOverflowAmountChanged', { - x: overflowAmount.x, - y: overflowAmount.y - }); - } - } - - //fix body min size - if (_isBody && _bodyMinSizeCache && (_hasOverflowCache.c || _bodyMinSizeCache.c)) { - //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. - if (!_bodyMinSizeCache.f) - bodyMinSizeChanged(); - if (_nativeScrollbarIsOverlaid.y && _hasOverflowCache.x) - _contentElement.css(_strMinMinus + _strWidth, _bodyMinSizeCache.w + _overlayScrollbarDummySize.y); - if (_nativeScrollbarIsOverlaid.x && _hasOverflowCache.y) - _contentElement.css(_strMinMinus + _strHeight, _bodyMinSizeCache.h + _overlayScrollbarDummySize.x); - _bodyMinSizeCache.c = false; - } - - //freezeResizeObserver(_sizeObserverElement, false); - //freezeResizeObserver(_sizeAutoObserverElement, false); - - dispatchCallback('onUpdated', { forced: force }); - } - - - //==== Options ====// - - /** - * Sets new options but doesn't call the update method. - * @param newOptions The object which contains the new options. - * @returns {*} A object which contains the changed options. - */ - function setOptions(newOptions) { - var validatedOpts = _pluginsOptions._validate(newOptions, _pluginsOptions._template, true, _currentOptions) - - _currentOptions = extendDeep({}, _currentOptions, validatedOpts._default); - _currentPreparedOptions = extendDeep({}, _currentPreparedOptions, validatedOpts._prepared); - - return validatedOpts._prepared; - } - - - //==== Structure ====// - - /** - * Builds or destroys the wrapper and helper DOM elements. - * @param destroy Indicates whether the DOM shall be build or destroyed. - */ - function setupStructureDOM(destroy) { - var strParent = 'parent'; - var classNameResizeObserverHost = 'os-resize-observer-host'; - var classNameTextareaElementFull = _classNameTextareaElement + _strSpace + _classNameTextInherit; - var textareaClass = _isTextarea ? _strSpace + _classNameTextInherit : _strEmpty; - var adoptAttrs = _currentPreparedOptions.textarea.inheritedAttrs; - var adoptAttrsMap = {}; - var applyAdoptedAttrs = function () { - var applyAdoptedAttrsElm = destroy ? _targetElement : _hostElement; - each(adoptAttrsMap, function (key, value) { - if (type(value) == TYPES.s) { - if (key == LEXICON.c) - applyAdoptedAttrsElm.addClass(value); - else - applyAdoptedAttrsElm.attr(key, value); - } - }); - }; - var hostElementClassNames = [ - _classNameHostElement, - _classNameHostTextareaElement, - _classNameHostResizeDisabled, - _classNameHostRTL, - _classNameHostScrollbarHorizontalHidden, - _classNameHostScrollbarVerticalHidden, - _classNameHostTransition, - _classNameHostScrolling, - _classNameHostOverflow, - _classNameHostOverflowX, - _classNameHostOverflowY, - _classNameThemeNone, - _classNameTextareaElement, - _classNameTextInherit, - _classNameCache].join(_strSpace); - var hostElementCSS = {}; - - //get host element as first element, because that's the most upper element and required for the other elements - _hostElement = _hostElement || (_isTextarea ? (_domExists ? _targetElement[strParent]()[strParent]()[strParent]()[strParent]() : FRAMEWORK(generateDiv(_classNameHostTextareaElement))) : _targetElement); - _contentElement = _contentElement || selectOrGenerateDivByClass(_classNameContentElement + textareaClass); - _viewportElement = _viewportElement || selectOrGenerateDivByClass(_classNameViewportElement + textareaClass); - _paddingElement = _paddingElement || selectOrGenerateDivByClass(_classNamePaddingElement + textareaClass); - _sizeObserverElement = _sizeObserverElement || selectOrGenerateDivByClass(classNameResizeObserverHost); - _textareaCoverElement = _textareaCoverElement || (_isTextarea ? selectOrGenerateDivByClass(_classNameTextareaCoverElement) : undefined); - - //on destroy, remove all generated class names from the host element before collecting the adopted attributes - //to prevent adopting generated class names - if (destroy) - removeClass(_hostElement, hostElementClassNames); - - //collect all adopted attributes - adoptAttrs = type(adoptAttrs) == TYPES.s ? adoptAttrs.split(_strSpace) : adoptAttrs; - if (type(adoptAttrs) == TYPES.a && _isTextarea) { - each(adoptAttrs, function (i, v) { - if (type(v) == TYPES.s) { - adoptAttrsMap[v] = destroy ? _hostElement.attr(v) : _targetElement.attr(v); - } - }); - } - - if (!destroy) { - if (_isTextarea) { - if (!_currentPreparedOptions.sizeAutoCapable) { - hostElementCSS[_strWidth] = _targetElement.css(_strWidth); - hostElementCSS[_strHeight] = _targetElement.css(_strHeight); - } - - if (!_domExists) - _targetElement.addClass(_classNameTextInherit).wrap(_hostElement); - - //jQuery clones elements in wrap functions, so we have to select them again - _hostElement = _targetElement[strParent]().css(hostElementCSS); - } - - if (!_domExists) { - //add the correct class to the target element - addClass(_targetElement, _isTextarea ? classNameTextareaElementFull : _classNameHostElement); - - //wrap the content into the generated elements to create the required DOM - _hostElement.wrapInner(_contentElement) - .wrapInner(_viewportElement) - .wrapInner(_paddingElement) - .prepend(_sizeObserverElement); - - //jQuery clones elements in wrap functions, so we have to select them again - _contentElement = findFirst(_hostElement, _strDot + _classNameContentElement); - _viewportElement = findFirst(_hostElement, _strDot + _classNameViewportElement); - _paddingElement = findFirst(_hostElement, _strDot + _classNamePaddingElement); - - if (_isTextarea) { - _contentElement.prepend(_textareaCoverElement); - applyAdoptedAttrs(); - } - } - - if (_nativeScrollbarStyling) - addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); - if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y) - addClass(_viewportElement, _classNameViewportNativeScrollbarsOverlaid); - if (_isBody) - addClass(_htmlElement, _classNameHTMLElement); - - _sizeObserverElementNative = _sizeObserverElement[0]; - _hostElementNative = _hostElement[0]; - _paddingElementNative = _paddingElement[0]; - _viewportElementNative = _viewportElement[0]; - _contentElementNative = _contentElement[0]; - - updateViewportAttrsFromTarget(); - } - else { - if (_domExists && _initialized) { - //clear size observer - _sizeObserverElement.children().remove(); - - //remove the style property and classes from already generated elements - each([_paddingElement, _viewportElement, _contentElement, _textareaCoverElement], function (i, elm) { - if (elm) { - removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); - } - }); - - //add classes to the host element which was removed previously to match the expected DOM - addClass(_hostElement, _isTextarea ? _classNameHostTextareaElement : _classNameHostElement); - } - else { - //remove size observer - remove(_sizeObserverElement); - - //unwrap the content to restore DOM - _contentElement.contents() - .unwrap() - .unwrap() - .unwrap(); - - if (_isTextarea) { - _targetElement.unwrap(); - remove(_hostElement); - remove(_textareaCoverElement); - applyAdoptedAttrs(); - } - } - - if (_isTextarea) - _targetElement.removeAttr(LEXICON.s); - - if (_isBody) - removeClass(_htmlElement, _classNameHTMLElement); - } - } - - /** - * Adds or removes all wrapper elements interactivity events. - * @param destroy Indicates whether the Events shall be added or removed. - */ - function setupStructureEvents() { - var textareaKeyDownRestrictedKeyCodes = [ - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 123, //F1 to F12 - 33, 34, //page up, page down - 37, 38, 39, 40, //left, up, right, down arrows - 16, 17, 18, 19, 20, 144 //Shift, Ctrl, Alt, Pause, CapsLock, NumLock - ]; - var textareaKeyDownKeyCodesList = []; - var textareaUpdateIntervalID; - var scrollStopTimeoutId; - var scrollStopDelay = 175; - var strFocus = 'focus'; - - function updateTextarea(doClearInterval) { - textareaUpdate(); - _base.update(_strAuto); - if (doClearInterval && _autoUpdateRecommended) - clearInterval(textareaUpdateIntervalID); - } - function textareaOnScroll(event) { - _targetElement[_strScrollLeft](_rtlScrollBehavior.i && _normalizeRTLCache ? 9999999 : 0); - _targetElement[_strScrollTop](0); - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - return false; - } - function textareaOnDrop(event) { - setTimeout(function () { - if (!_destroyed) - updateTextarea(); - }, 50); - } - function textareaOnFocus() { - _textareaHasFocus = true; - addClass(_hostElement, strFocus); - } - function textareaOnFocusout() { - _textareaHasFocus = false; - textareaKeyDownKeyCodesList = []; - removeClass(_hostElement, strFocus); - updateTextarea(true); - } - function textareaOnKeyDown(event) { - var keyCode = event.keyCode; - - if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { - if (!textareaKeyDownKeyCodesList[LEXICON.l]) { - updateTextarea(); - textareaUpdateIntervalID = setInterval(updateTextarea, 1000 / 60); - } - if (inArray(keyCode, textareaKeyDownKeyCodesList) < 0) - textareaKeyDownKeyCodesList.push(keyCode); - } - } - function textareaOnKeyUp(event) { - var keyCode = event.keyCode; - var index = inArray(keyCode, textareaKeyDownKeyCodesList); - - if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { - if (index > -1) - textareaKeyDownKeyCodesList.splice(index, 1); - if (!textareaKeyDownKeyCodesList[LEXICON.l]) - updateTextarea(true); - } - } - function contentOnTransitionEnd(event) { - if (_autoUpdateCache === true) - return; - event = event.originalEvent || event; - if (isSizeAffectingCSSProperty(event.propertyName)) - _base.update(_strAuto); - } - function viewportOnScroll(event) { - if (!_sleeping) { - if (scrollStopTimeoutId !== undefined) - clearTimeout(scrollStopTimeoutId); - else { - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(true); - - if (!nativeOverlayScrollbarsAreActive()) - addClass(_hostElement, _classNameHostScrolling); - - dispatchCallback('onScrollStart', event); - } - - //if a scrollbars handle gets dragged, the mousemove event is responsible for refreshing the handle offset - //because if CSS scroll-snap is used, the handle offset gets only refreshed on every snap point - //this looks laggy & clunky, it looks much better if the offset refreshes with the mousemove - if (!_scrollbarsHandlesDefineScrollPos) { - refreshScrollbarHandleOffset(true); - refreshScrollbarHandleOffset(false); - } - dispatchCallback('onScroll', event); - - scrollStopTimeoutId = setTimeout(function () { - if (!_destroyed) { - //OnScrollStop: - clearTimeout(scrollStopTimeoutId); - scrollStopTimeoutId = undefined; - - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(false); - - if (!nativeOverlayScrollbarsAreActive()) - removeClass(_hostElement, _classNameHostScrolling); - - dispatchCallback('onScrollStop', event); - } - }, scrollStopDelay); - } - } - - - if (_isTextarea) { - if (_msieVersion > 9 || !_autoUpdateRecommended) { - addDestroyEventListener(_targetElement, 'input', updateTextarea); - } - else { - addDestroyEventListener(_targetElement, - [_strKeyDownEvent, _strKeyUpEvent], - [textareaOnKeyDown, textareaOnKeyUp]); - } - - addDestroyEventListener(_targetElement, - [_strScroll, 'drop', strFocus, strFocus + 'out'], - [textareaOnScroll, textareaOnDrop, textareaOnFocus, textareaOnFocusout]); - } - else { - addDestroyEventListener(_contentElement, _strTransitionEndEvent, contentOnTransitionEnd); - } - addDestroyEventListener(_viewportElement, _strScroll, viewportOnScroll, true); - } - - - //==== Scrollbars ====// - - /** - * Builds or destroys all scrollbar DOM elements (scrollbar, track, handle) - * @param destroy Indicates whether the DOM shall be build or destroyed. - */ - function setupScrollbarsDOM(destroy) { - var selectOrGenerateScrollbarDOM = function (isHorizontal) { - var scrollbarClassName = isHorizontal ? _classNameScrollbarHorizontal : _classNameScrollbarVertical; - var scrollbar = selectOrGenerateDivByClass(_classNameScrollbar + _strSpace + scrollbarClassName, true); - var track = selectOrGenerateDivByClass(_classNameScrollbarTrack, scrollbar); - var handle = selectOrGenerateDivByClass(_classNameScrollbarHandle, scrollbar); - - if (!_domExists && !destroy) { - scrollbar.append(track); - track.append(handle); - } - - return { - _scrollbar: scrollbar, - _track: track, - _handle: handle - }; - }; - function resetScrollbarDOM(isHorizontal) { - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbar = scrollbarVars._scrollbar; - var track = scrollbarVars._track; - var handle = scrollbarVars._handle; - - if (_domExists && _initialized) { - each([scrollbar, track, handle], function (i, elm) { - removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); - }); - } - else { - remove(scrollbar || selectOrGenerateScrollbarDOM(isHorizontal)._scrollbar); - } - } - var horizontalElements; - var verticalElements; - - if (!destroy) { - horizontalElements = selectOrGenerateScrollbarDOM(true); - verticalElements = selectOrGenerateScrollbarDOM(); - - _scrollbarHorizontalElement = horizontalElements._scrollbar; - _scrollbarHorizontalTrackElement = horizontalElements._track; - _scrollbarHorizontalHandleElement = horizontalElements._handle; - _scrollbarVerticalElement = verticalElements._scrollbar; - _scrollbarVerticalTrackElement = verticalElements._track; - _scrollbarVerticalHandleElement = verticalElements._handle; - - if (!_domExists) { - _paddingElement.after(_scrollbarVerticalElement); - _paddingElement.after(_scrollbarHorizontalElement); - } - } - else { - resetScrollbarDOM(true); - resetScrollbarDOM(); - } - } - - /** - * Initializes all scrollbar interactivity events. (track and handle dragging, clicking, scrolling) - * @param isHorizontal True if the target scrollbar is the horizontal scrollbar, false if the target scrollbar is the vertical scrollbar. - */ - function setupScrollbarEvents(isHorizontal) { - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbarVarsInfo = scrollbarVars._info; - var insideIFrame = _windowElementNative.top !== _windowElementNative; - var xy = scrollbarVars._x_y; - var XY = scrollbarVars._X_Y; - var scroll = _strScroll + scrollbarVars._Left_Top; - var strActive = 'active'; - var strSnapHandle = 'snapHandle'; - var scrollDurationFactor = 1; - var increaseDecreaseScrollAmountKeyCodes = [16, 17]; //shift, ctrl - var trackTimeout; - var mouseDownScroll; - var mouseDownOffset; - var mouseDownInvertedScale; - - function getPointerPosition(event) { - return _msieVersion && insideIFrame ? event['screen' + XY] : COMPATIBILITY.page(event)[xy]; //use screen coordinates in EDGE & IE because the page values are incorrect in frames. - } - function getPreparedScrollbarsOption(name) { - return _currentPreparedOptions.scrollbars[name]; - } - function increaseTrackScrollAmount() { - scrollDurationFactor = 0.5; - } - function decreaseTrackScrollAmount() { - scrollDurationFactor = 1; - } - function documentKeyDown(event) { - if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) - increaseTrackScrollAmount(); - } - function documentKeyUp(event) { - if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) - decreaseTrackScrollAmount(); - } - function onMouseTouchDownContinue(event) { - var originalEvent = event.originalEvent || event; - var isTouchEvent = originalEvent.touches !== undefined; - return _sleeping || _destroyed || nativeOverlayScrollbarsAreActive() || !_scrollbarsDragScrollingCache || (isTouchEvent && !getPreparedScrollbarsOption('touchSupport')) ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; - } - function documentDragMove(event) { - if (onMouseTouchDownContinue(event)) { - var trackLength = scrollbarVarsInfo._trackLength; - var handleLength = scrollbarVarsInfo._handleLength; - var scrollRange = scrollbarVarsInfo._maxScroll; - var scrollRaw = (getPointerPosition(event) - mouseDownOffset) * mouseDownInvertedScale; - var scrollDeltaPercent = scrollRaw / (trackLength - handleLength); - var scrollDelta = (scrollRange * scrollDeltaPercent); - scrollDelta = isFinite(scrollDelta) ? scrollDelta : 0; - if (_isRTL && isHorizontal && !_rtlScrollBehavior.i) - scrollDelta *= -1; - - _viewportElement[scroll](MATH.round(mouseDownScroll + scrollDelta)); - - if (_scrollbarsHandlesDefineScrollPos) - refreshScrollbarHandleOffset(isHorizontal, mouseDownScroll + scrollDelta); - - if (!_supportPassiveEvents) - COMPATIBILITY.prvD(event); - } - else - documentMouseTouchUp(event); - } - function documentMouseTouchUp(event) { - event = event || event.originalEvent; - - setupResponsiveEventListener(_documentElement, - [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], - [documentDragMove, documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart], - true); - - if (_scrollbarsHandlesDefineScrollPos) - refreshScrollbarHandleOffset(isHorizontal, true); - - _scrollbarsHandlesDefineScrollPos = false; - removeClass(_bodyElement, _classNameDragging); - removeClass(scrollbarVars._handle, strActive); - removeClass(scrollbarVars._track, strActive); - removeClass(scrollbarVars._scrollbar, strActive); - - mouseDownScroll = undefined; - mouseDownOffset = undefined; - mouseDownInvertedScale = 1; - - decreaseTrackScrollAmount(); - - if (trackTimeout !== undefined) { - _base.scrollStop(); - clearTimeout(trackTimeout); - trackTimeout = undefined; - } - - if (event) { - var rect = _hostElementNative[LEXICON.bCR](); - var mouseInsideHost = event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom; - - //if mouse is outside host element - if (!mouseInsideHost) - hostOnMouseLeave(); - - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(false); - } - } - function onHandleMouseTouchDown(event) { - if (onMouseTouchDownContinue(event)) - onHandleMouseTouchDownAction(event); - } - function onHandleMouseTouchDownAction(event) { - mouseDownScroll = _viewportElement[scroll](); - mouseDownScroll = isNaN(mouseDownScroll) ? 0 : mouseDownScroll; - if (_isRTL && isHorizontal && !_rtlScrollBehavior.n || !_isRTL) - mouseDownScroll = mouseDownScroll < 0 ? 0 : mouseDownScroll; - - mouseDownInvertedScale = getHostElementInvertedScale()[xy]; - mouseDownOffset = getPointerPosition(event); - - _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); - addClass(_bodyElement, _classNameDragging); - addClass(scrollbarVars._handle, strActive); - addClass(scrollbarVars._scrollbar, strActive); - - setupResponsiveEventListener(_documentElement, - [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strSelectStartEvent], - [documentDragMove, documentMouseTouchUp, documentOnSelectStart]); - - if (_msieVersion || !_documentMixed) - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - function onTrackMouseTouchDown(event) { - if (onMouseTouchDownContinue(event)) { - var scrollDistance = MATH.round(_viewportSize[scrollbarVars._w_h]); - var trackOffset = scrollbarVars._track.offset()[scrollbarVars._left_top]; - var ctrlKey = event.ctrlKey; - var instantScroll = event.shiftKey; - var instantScrollTransition = instantScroll && ctrlKey; - var isFirstIteration = true; - var easing = 'linear'; - var decreaseScroll; - var finishedCondition; - var scrollActionFinsished = function (transition) { - if (_scrollbarsHandlesDefineScrollPos) - refreshScrollbarHandleOffset(isHorizontal, transition); - }; - var scrollActionInstantFinished = function () { - scrollActionFinsished(); - onHandleMouseTouchDownAction(event); - }; - var scrollAction = function () { - if (!_destroyed) { - var mouseOffset = (mouseDownOffset - trackOffset) * mouseDownInvertedScale; - var handleOffset = scrollbarVarsInfo._handleOffset; - var trackLength = scrollbarVarsInfo._trackLength; - var handleLength = scrollbarVarsInfo._handleLength; - var scrollRange = scrollbarVarsInfo._maxScroll; - var currScroll = scrollbarVarsInfo._currentScroll; - var scrollDuration = 270 * scrollDurationFactor; - var timeoutDelay = isFirstIteration ? MATH.max(400, scrollDuration) : scrollDuration; - var instantScrollPosition = scrollRange * ((mouseOffset - (handleLength / 2)) / (trackLength - handleLength)); // 100% * positionPercent - var rtlIsNormal = _isRTL && isHorizontal && ((!_rtlScrollBehavior.i && !_rtlScrollBehavior.n) || _normalizeRTLCache); - var decreaseScrollCondition = rtlIsNormal ? handleOffset < mouseOffset : handleOffset > mouseOffset; - var scrollObj = {}; - var animationObj = { - easing: easing, - step: function (now) { - if (_scrollbarsHandlesDefineScrollPos) { - _viewportElement[scroll](now); //https://github.com/jquery/jquery/issues/4340 - refreshScrollbarHandleOffset(isHorizontal, now); - } - } - }; - instantScrollPosition = isFinite(instantScrollPosition) ? instantScrollPosition : 0; - instantScrollPosition = _isRTL && isHorizontal && !_rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; - - //_base.scrollStop(); - - if (instantScroll) { - _viewportElement[scroll](instantScrollPosition); //scroll instantly to new position - if (instantScrollTransition) { - //get the scroll position after instant scroll (in case CSS Snap Points are used) to get the correct snapped scroll position - //and the animation stops at the correct point - instantScrollPosition = _viewportElement[scroll](); - //scroll back to the position before instant scrolling so animation can be performed - _viewportElement[scroll](currScroll); - - instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; - instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.n ? -instantScrollPosition : instantScrollPosition; - - scrollObj[xy] = instantScrollPosition; - _base.scroll(scrollObj, extendDeep(animationObj, { - duration: 130, - complete: scrollActionInstantFinished - })); - } - else - scrollActionInstantFinished(); - } - else { - decreaseScroll = isFirstIteration ? decreaseScrollCondition : decreaseScroll; - finishedCondition = rtlIsNormal - ? (decreaseScroll ? handleOffset + handleLength >= mouseOffset : handleOffset <= mouseOffset) - : (decreaseScroll ? handleOffset <= mouseOffset : handleOffset + handleLength >= mouseOffset); - - if (finishedCondition) { - clearTimeout(trackTimeout); - _base.scrollStop(); - trackTimeout = undefined; - scrollActionFinsished(true); - } - else { - trackTimeout = setTimeout(scrollAction, timeoutDelay); - - scrollObj[xy] = (decreaseScroll ? '-=' : '+=') + scrollDistance; - _base.scroll(scrollObj, extendDeep(animationObj, { - duration: scrollDuration - })); - } - isFirstIteration = false; - } - } - }; - if (ctrlKey) - increaseTrackScrollAmount(); - - mouseDownInvertedScale = getHostElementInvertedScale()[xy]; - mouseDownOffset = COMPATIBILITY.page(event)[xy]; - - _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); - addClass(_bodyElement, _classNameDragging); - addClass(scrollbarVars._track, strActive); - addClass(scrollbarVars._scrollbar, strActive); - - setupResponsiveEventListener(_documentElement, - [_strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], - [documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart]); - - scrollAction(); - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - } - function onTrackMouseTouchEnter(event) { - //make sure both scrollbars will stay visible if one scrollbar is hovered if autoHide is "scroll" or "move". - _scrollbarsHandleHovered = true; - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(true); - } - function onTrackMouseTouchLeave(event) { - _scrollbarsHandleHovered = false; - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(false); - } - function onScrollbarMouseTouchDown(event) { - COMPATIBILITY.stpP(event); - } - - addDestroyEventListener(scrollbarVars._handle, - _strMouseTouchDownEvent, - onHandleMouseTouchDown); - addDestroyEventListener(scrollbarVars._track, - [_strMouseTouchDownEvent, _strMouseTouchEnter, _strMouseTouchLeave], - [onTrackMouseTouchDown, onTrackMouseTouchEnter, onTrackMouseTouchLeave]); - addDestroyEventListener(scrollbarVars._scrollbar, - _strMouseTouchDownEvent, - onScrollbarMouseTouchDown); - - if (_supportTransition) { - addDestroyEventListener(scrollbarVars._scrollbar, _strTransitionEndEvent, function (event) { - if (event.target !== scrollbarVars._scrollbar[0]) - return; - refreshScrollbarHandleLength(isHorizontal); - refreshScrollbarHandleOffset(isHorizontal); - }); - } - } - - /** - * Shows or hides the given scrollbar and applied a class name which indicates if the scrollbar is scrollable or not. - * @param isHorizontal True if the horizontal scrollbar is the target, false if the vertical scrollbar is the target. - * @param shallBeVisible True if the scrollbar shall be shown, false if hidden. - * @param canScroll True if the scrollbar is scrollable, false otherwise. - */ - function refreshScrollbarAppearance(isHorizontal, shallBeVisible, canScroll) { - var scrollbarClassName = isHorizontal ? _classNameHostScrollbarHorizontalHidden : _classNameHostScrollbarVerticalHidden; - var scrollbarElement = isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement; - - if (shallBeVisible) - removeClass(_hostElement, scrollbarClassName); - else - addClass(_hostElement, scrollbarClassName); - - if (canScroll) - removeClass(scrollbarElement, _classNameScrollbarUnusable); - else - addClass(scrollbarElement, _classNameScrollbarUnusable); - } - - /** - * Autoshows / autohides both scrollbars with. - * @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. - * @param delayfree True if the scrollbars shall be hidden without a delay, false or undefined otherwise. - */ - function refreshScrollbarsAutoHide(shallBeVisible, delayfree) { - clearTimeout(_scrollbarsAutoHideTimeoutId); - if (shallBeVisible) { - //if(_hasOverflowCache.x && _hideOverflowCache.xs) - removeClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); - //if(_hasOverflowCache.y && _hideOverflowCache.ys) - removeClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); - } - else { - var anyActive; - var strActive = 'active'; - var hide = function () { - if (!_scrollbarsHandleHovered && !_destroyed) { - anyActive = _scrollbarHorizontalHandleElement.hasClass(strActive) || _scrollbarVerticalHandleElement.hasClass(strActive); - if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) - addClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); - if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) - addClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); - } - }; - if (_scrollbarsAutoHideDelay > 0 && delayfree !== true) - _scrollbarsAutoHideTimeoutId = setTimeout(hide, _scrollbarsAutoHideDelay); - else - hide(); - } - } - - /** - * Refreshes the handle length of the given scrollbar. - * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. - */ - function refreshScrollbarHandleLength(isHorizontal) { - var handleCSS = {}; - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbarVarsInfo = scrollbarVars._info; - var digit = 1000000; - //get and apply intended handle length - var handleRatio = MATH.min(1, (_hostSizeCache[scrollbarVars._w_h] - (_paddingAbsoluteCache ? (isHorizontal ? _paddingX : _paddingY) : 0)) / _contentScrollSizeCache[scrollbarVars._w_h]); - handleCSS[scrollbarVars._width_height] = (MATH.floor(handleRatio * 100 * digit) / digit) + '%'; //the last * digit / digit is for flooring to the 4th digit - - if (!nativeOverlayScrollbarsAreActive()) - scrollbarVars._handle.css(handleCSS); - - //measure the handle length to respect min & max length - scrollbarVarsInfo._handleLength = scrollbarVars._handle[0]['offset' + scrollbarVars._Width_Height]; - scrollbarVarsInfo._handleLengthRatio = handleRatio; - } - - /** - * Refreshes the handle offset of the given scrollbar. - * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. - * @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) - */ - function refreshScrollbarHandleOffset(isHorizontal, scrollOrTransition) { - var transition = type(scrollOrTransition) == TYPES.b; - var transitionDuration = 250; - var isRTLisHorizontal = _isRTL && isHorizontal; - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbarVarsInfo = scrollbarVars._info; - var strTranslateBrace = 'translate('; - var strTransform = VENDORS._cssProperty('transform'); - var strTransition = VENDORS._cssProperty('transition'); - var nativeScroll = isHorizontal ? _viewportElement[_strScrollLeft]() : _viewportElement[_strScrollTop](); - var currentScroll = scrollOrTransition === undefined || transition ? nativeScroll : scrollOrTransition; - - //measure the handle length to respect min & max length - var handleLength = scrollbarVarsInfo._handleLength; - var trackLength = scrollbarVars._track[0]['offset' + scrollbarVars._Width_Height]; - var handleTrackDiff = trackLength - handleLength; - var handleCSS = {}; - var transformOffset; - var translateValue; - - //DONT use the variable '_contentScrollSizeCache[scrollbarVars._w_h]' instead of '_viewportElement[0]['scroll' + scrollbarVars._Width_Height]' - // because its a bit behind during the small delay when content size updates - //(delay = mutationObserverContentLag, if its 0 then this var could be used) - var maxScroll = (_viewportElementNative[_strScroll + scrollbarVars._Width_Height] - _viewportElementNative['client' + scrollbarVars._Width_Height]) * (_rtlScrollBehavior.n && isRTLisHorizontal ? -1 : 1); //* -1 if rtl scroll max is negative - var getScrollRatio = function (base) { - return isNaN(base / maxScroll) ? 0 : MATH.max(0, MATH.min(1, base / maxScroll)); - }; - var getHandleOffset = function (scrollRatio) { - var offset = handleTrackDiff * scrollRatio; - offset = isNaN(offset) ? 0 : offset; - offset = (isRTLisHorizontal && !_rtlScrollBehavior.i) ? (trackLength - handleLength - offset) : offset; - offset = MATH.max(0, offset); - return offset; - }; - var scrollRatio = getScrollRatio(nativeScroll); - var unsnappedScrollRatio = getScrollRatio(currentScroll); - var handleOffset = getHandleOffset(unsnappedScrollRatio); - var snappedHandleOffset = getHandleOffset(scrollRatio); - - scrollbarVarsInfo._maxScroll = maxScroll; - scrollbarVarsInfo._currentScroll = nativeScroll; - scrollbarVarsInfo._currentScrollRatio = scrollRatio; - - if (_supportTransform) { - transformOffset = isRTLisHorizontal ? -(trackLength - handleLength - handleOffset) : handleOffset; //in px - //transformOffset = (transformOffset / trackLength * 100) * (trackLength / handleLength); //in % - translateValue = isHorizontal ? strTranslateBrace + transformOffset + 'px, 0)' : strTranslateBrace + '0, ' + transformOffset + 'px)'; - - handleCSS[strTransform] = translateValue; - - //apply or clear up transition - if (_supportTransition) - handleCSS[strTransition] = transition && MATH.abs(handleOffset - scrollbarVarsInfo._handleOffset) > 1 ? getCSSTransitionString(scrollbarVars._handle) + ', ' + (strTransform + _strSpace + transitionDuration + 'ms') : _strEmpty; - } - else - handleCSS[scrollbarVars._left_top] = handleOffset; - - - //only apply css if offset has changed and overflow exists. - if (!nativeOverlayScrollbarsAreActive()) { - scrollbarVars._handle.css(handleCSS); - - //clear up transition - if (_supportTransform && _supportTransition && transition) { - scrollbarVars._handle.one(_strTransitionEndEvent, function () { - if (!_destroyed) - scrollbarVars._handle.css(strTransition, _strEmpty); - }); - } - } - - scrollbarVarsInfo._handleOffset = handleOffset; - scrollbarVarsInfo._snappedHandleOffset = snappedHandleOffset; - scrollbarVarsInfo._trackLength = trackLength; - } - - /** - * Refreshes the interactivity of the given scrollbar element. - * @param isTrack True if the track element is the target, false if the handle element is the target. - * @param value True for interactivity false for no interactivity. - */ - function refreshScrollbarsInteractive(isTrack, value) { - var action = value ? 'removeClass' : 'addClass'; - var element1 = isTrack ? _scrollbarHorizontalTrackElement : _scrollbarHorizontalHandleElement; - var element2 = isTrack ? _scrollbarVerticalTrackElement : _scrollbarVerticalHandleElement; - var className = isTrack ? _classNameScrollbarTrackOff : _classNameScrollbarHandleOff; - - element1[action](className); - element2[action](className); - } - - /** - * Returns a object which is used for fast access for specific variables. - * @param isHorizontal True if the horizontal scrollbar vars shall be accessed, false if the vertical scrollbar vars shall be accessed. - * @returns {{wh: string, WH: string, lt: string, _wh: string, _lt: string, t: *, h: *, c: {}, s: *}} - */ - function getScrollbarVars(isHorizontal) { - return { - _width_height: isHorizontal ? _strWidth : _strHeight, - _Width_Height: isHorizontal ? 'Width' : 'Height', - _left_top: isHorizontal ? _strLeft : _strTop, - _Left_Top: isHorizontal ? 'Left' : 'Top', - _x_y: isHorizontal ? _strX : _strY, - _X_Y: isHorizontal ? 'X' : 'Y', - _w_h: isHorizontal ? 'w' : 'h', - _l_t: isHorizontal ? 'l' : 't', - _track: isHorizontal ? _scrollbarHorizontalTrackElement : _scrollbarVerticalTrackElement, - _handle: isHorizontal ? _scrollbarHorizontalHandleElement : _scrollbarVerticalHandleElement, - _scrollbar: isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement, - _info: isHorizontal ? _scrollHorizontalInfo : _scrollVerticalInfo - }; - } - - - //==== Scrollbar Corner ====// - - /** - * Builds or destroys the scrollbar corner DOM element. - * @param destroy Indicates whether the DOM shall be build or destroyed. - */ - function setupScrollbarCornerDOM(destroy) { - _scrollbarCornerElement = _scrollbarCornerElement || selectOrGenerateDivByClass(_classNameScrollbarCorner, true); - - if (!destroy) { - if (!_domExists) { - _hostElement.append(_scrollbarCornerElement); - } - } - else { - if (_domExists && _initialized) { - removeClass(_scrollbarCornerElement.removeAttr(LEXICON.s), _classNamesDynamicDestroy); - } - else { - remove(_scrollbarCornerElement); - } - } - } - - /** - * Initializes all scrollbar corner interactivity events. - */ - function setupScrollbarCornerEvents() { - var insideIFrame = _windowElementNative.top !== _windowElementNative; - var mouseDownPosition = {}; - var mouseDownSize = {}; - var mouseDownInvertedScale = {}; - var reconnectMutationObserver; - - function documentDragMove(event) { - if (onMouseTouchDownContinue(event)) { - var pageOffset = getCoordinates(event); - var hostElementCSS = {}; - if (_resizeHorizontal || _resizeBoth) - hostElementCSS[_strWidth] = (mouseDownSize.w + (pageOffset.x - mouseDownPosition.x) * mouseDownInvertedScale.x); - if (_resizeVertical || _resizeBoth) - hostElementCSS[_strHeight] = (mouseDownSize.h + (pageOffset.y - mouseDownPosition.y) * mouseDownInvertedScale.y); - _hostElement.css(hostElementCSS); - COMPATIBILITY.stpP(event); - } - else { - documentMouseTouchUp(event); - } - } - function documentMouseTouchUp(event) { - var eventIsTrusted = event !== undefined; - - setupResponsiveEventListener(_documentElement, - [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], - [documentOnSelectStart, documentDragMove, documentMouseTouchUp], - true); - - removeClass(_bodyElement, _classNameDragging); - if (_scrollbarCornerElement.releaseCapture) - _scrollbarCornerElement.releaseCapture(); - - if (eventIsTrusted) { - if (reconnectMutationObserver) - connectMutationObservers(); - _base.update(_strAuto); - } - reconnectMutationObserver = false; - } - function onMouseTouchDownContinue(event) { - var originalEvent = event.originalEvent || event; - var isTouchEvent = originalEvent.touches !== undefined; - return _sleeping || _destroyed ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; - } - function getCoordinates(event) { - return _msieVersion && insideIFrame ? { x: event.screenX, y: event.screenY } : COMPATIBILITY.page(event); - } - - addDestroyEventListener(_scrollbarCornerElement, _strMouseTouchDownEvent, function (event) { - if (onMouseTouchDownContinue(event) && !_resizeNone) { - if (_mutationObserversConnected) { - reconnectMutationObserver = true; - disconnectMutationObservers(); - } - - mouseDownPosition = getCoordinates(event); - - mouseDownSize.w = _hostElementNative[LEXICON.oW] - (!_isBorderBox ? _paddingX : 0); - mouseDownSize.h = _hostElementNative[LEXICON.oH] - (!_isBorderBox ? _paddingY : 0); - mouseDownInvertedScale = getHostElementInvertedScale(); - - setupResponsiveEventListener(_documentElement, - [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], - [documentOnSelectStart, documentDragMove, documentMouseTouchUp]); - - addClass(_bodyElement, _classNameDragging); - if (_scrollbarCornerElement.setCapture) - _scrollbarCornerElement.setCapture(); - - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - }); - } - - - //==== Utils ====// - - /** - * Calls the callback with the given name. The Context of this callback is always _base (this). - * @param name The name of the target which shall be called. - * @param args The args with which the callback shall be called. - */ - function dispatchCallback(name, args) { - if (_initialized) { - var callback = _currentPreparedOptions.callbacks[name]; - var extensionOnName = name; - var ext; - - if (extensionOnName.substr(0, 2) === 'on') - extensionOnName = extensionOnName.substr(2, 1).toLowerCase() + extensionOnName.substr(3); - - if (type(callback) == TYPES.f) - callback.call(_base, args); - - each(_extensions, function () { - ext = this; - if (type(ext.on) == TYPES.f) - ext.on(extensionOnName, args); - }); - } - else if (!_destroyed) - _callbacksInitQeueue.push({ n: name, a: args }); - } - - /** - * Sets the "top, right, bottom, left" properties, with a given prefix, of the given css object. - * @param targetCSSObject The css object to which the values shall be applied. - * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix) - * @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]. - * If this argument is undefined the value '' (empty string) will be applied to all properties. - */ - function setTopRightBottomLeft(targetCSSObject, prefix, values) { - if (values === undefined) - values = [_strEmpty, _strEmpty, _strEmpty, _strEmpty]; - - targetCSSObject[prefix + _strTop] = values[0]; - targetCSSObject[prefix + _strRight] = values[1]; - targetCSSObject[prefix + _strBottom] = values[2]; - targetCSSObject[prefix + _strLeft] = values[3]; - } - - /** - * Returns the computed CSS transition string from the given element. - * @param element The element from which the transition string shall be returned. - * @returns {string} The CSS transition string from the given element. - */ - function getCSSTransitionString(element) { - var transitionStr = VENDORS._cssProperty('transition'); - var assembledValue = element.css(transitionStr); - if (assembledValue) - return assembledValue; - var regExpString = '\\s*(' + '([^,(]+(\\(.+?\\))?)+' + ')[\\s,]*'; - var regExpMain = new RegExp(regExpString); - var regExpValidate = new RegExp('^(' + regExpString + ')+$'); - var properties = 'property duration timing-function delay'.split(' '); - var result = []; - var strResult; - var valueArray; - var i = 0; - var j; - var splitCssStyleByComma = function (str) { - strResult = []; - if (!str.match(regExpValidate)) - return str; - while (str.match(regExpMain)) { - strResult.push(RegExp.$1); - str = str.replace(regExpMain, _strEmpty); - } - - return strResult; - }; - for (; i < properties[LEXICON.l]; i++) { - valueArray = splitCssStyleByComma(element.css(transitionStr + '-' + properties[i])); - for (j = 0; j < valueArray[LEXICON.l]; j++) - result[j] = (result[j] ? result[j] + _strSpace : _strEmpty) + valueArray[j]; - } - return result.join(', '); - } - - /** - * Calculates the host-elements inverted scale. (invertedScale = 1 / scale) - * @returns {{x: number, y: number}} The scale of the host-element. - */ - function getHostElementInvertedScale() { - var rect = _paddingElementNative[LEXICON.bCR](); - return { - x: _supportTransform ? 1 / (MATH.round(rect.width) / _paddingElementNative[LEXICON.oW]) || 1 : 1, - y: _supportTransform ? 1 / (MATH.round(rect.height) / _paddingElementNative[LEXICON.oH]) || 1 : 1 - }; - } - - /** - * Checks whether the given object is a HTMLElement. - * @param o The object which shall be checked. - * @returns {boolean} True the given object is a HTMLElement, false otherwise. - */ - function isHTMLElement(o) { - var strOwnerDocument = 'ownerDocument'; - var strHTMLElement = 'HTMLElement'; - var wnd = o && o[strOwnerDocument] ? (o[strOwnerDocument].parentWindow || window) : window; - return ( - typeof wnd[strHTMLElement] == TYPES.o ? o instanceof wnd[strHTMLElement] : //DOM2 - o && typeof o == TYPES.o && o !== null && o.nodeType === 1 && typeof o.nodeName == TYPES.s - ); - } - - /** - * Compares 2 arrays and returns the differences between them as a array. - * @param a1 The first array which shall be compared. - * @param a2 The second array which shall be compared. - * @returns {Array} The differences between the two arrays. - */ - function getArrayDifferences(a1, a2) { - var a = []; - var diff = []; - var i; - var k; - for (i = 0; i < a1.length; i++) - a[a1[i]] = true; - for (i = 0; i < a2.length; i++) { - if (a[a2[i]]) - delete a[a2[i]]; - else - a[a2[i]] = true; - } - for (k in a) - diff.push(k); - return diff; - } - - /** - * Returns Zero or the number to which the value can be parsed. - * @param value The value which shall be parsed. - * @param toFloat Indicates whether the number shall be parsed to a float. - */ - function parseToZeroOrNumber(value, toFloat) { - var num = toFloat ? parseFloat(value) : parseInt(value, 10); - return isNaN(num) ? 0 : num; - } - - /** - * Gets several information of the textarea and returns them as a object or undefined if the browser doesn't support it. - * @returns {{cursorRow: Number, cursorCol, rows: Number, cols: number, wRow: number, pos: number, max : number}} or undefined if not supported. - */ - function getTextareaInfo() { - //read needed values - var textareaCursorPosition = _targetElementNative.selectionStart; - if (textareaCursorPosition === undefined) - return; - - var textareaValue = _targetElement.val(); - var textareaLength = textareaValue[LEXICON.l]; - var textareaRowSplit = textareaValue.split('\n'); - var textareaLastRow = textareaRowSplit[LEXICON.l]; - var textareaCurrentCursorRowSplit = textareaValue.substr(0, textareaCursorPosition).split('\n'); - var widestRow = 0; - var textareaLastCol = 0; - var cursorRow = textareaCurrentCursorRowSplit[LEXICON.l]; - var cursorCol = textareaCurrentCursorRowSplit[textareaCurrentCursorRowSplit[LEXICON.l] - 1][LEXICON.l]; - var rowCols; - var i; - - //get widest Row and the last column of the textarea - for (i = 0; i < textareaRowSplit[LEXICON.l]; i++) { - rowCols = textareaRowSplit[i][LEXICON.l]; - if (rowCols > textareaLastCol) { - widestRow = i + 1; - textareaLastCol = rowCols; - } - } - - return { - _cursorRow: cursorRow, //cursorRow - _cursorColumn: cursorCol, //cursorCol - _rows: textareaLastRow, //rows - _columns: textareaLastCol, //cols - _widestRow: widestRow, //wRow - _cursorPosition: textareaCursorPosition, //pos - _cursorMax: textareaLength //max - }; - } - - /** - * Determines whether native overlay scrollbars are active. - * @returns {boolean} True if native overlay scrollbars are active, false otherwise. - */ - function nativeOverlayScrollbarsAreActive() { - return (_ignoreOverlayScrollbarHidingCache && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)); - } - - /** - * Gets the element which is used to measure the content size. - * @returns {*} TextareaCover if target element is textarea else the ContentElement. - */ - function getContentMeasureElement() { - return _isTextarea ? _textareaCoverElement[0] : _contentElementNative; - } - - /** - * Generates a string which represents a HTML div with the given classes or attributes. - * @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".) - * @param content The content of the div as string. - * @returns {string} The concated string which represents a HTML div and its content. - */ - function generateDiv(classesOrAttrs, content) { - return '
' + - (content || _strEmpty) + - '
'; - } - - /** - * Selects or generates a div with the given class attribute. - * @param className The class names (divided by spaces) of the div which shall be selected or generated. - * @param selectParentOrOnlyChildren The parent element from which of the element shall be selected. (if undefined or boolean its hostElement) - * If its a boolean it decides whether only the children of the host element shall be selected. - * @returns {*} The generated or selected element. - */ - function selectOrGenerateDivByClass(className, selectParentOrOnlyChildren) { - var onlyChildren = type(selectParentOrOnlyChildren) == TYPES.b; - var selectParent = onlyChildren ? _hostElement : (selectParentOrOnlyChildren || _hostElement); - - return (_domExists && !selectParent[LEXICON.l]) - ? null - : _domExists - ? selectParent[onlyChildren ? 'children' : 'find'](_strDot + className.replace(/\s/g, _strDot)).eq(0) - : FRAMEWORK(generateDiv(className)) - } - - /** - * Gets the value of the given property from the given object. - * @param obj The object from which the property value shall be got. - * @param path The property of which the value shall be got. - * @returns {*} Returns the value of the searched property or undefined of the property wasn't found. - */ - function getObjectPropVal(obj, path) { - var splits = path.split(_strDot); - var i = 0; - var val; - for (; i < splits.length; i++) { - if (!obj[LEXICON.hOP](splits[i])) - return; - val = obj[splits[i]]; - if (i < splits.length && type(val) == TYPES.o) - obj = val; - } - return val; - } - - /** - * Sets the value of the given property from the given object. - * @param obj The object from which the property value shall be set. - * @param path The property of which the value shall be set. - * @param val The value of the property which shall be set. - */ - function setObjectPropVal(obj, path, val) { - var splits = path.split(_strDot); - var splitsLength = splits.length; - var i = 0; - var extendObj = {}; - var extendObjRoot = extendObj; - for (; i < splitsLength; i++) - extendObj = extendObj[splits[i]] = i + 1 < splitsLength ? {} : val; - FRAMEWORK.extend(obj, extendObjRoot, true); - } - - - //==== Utils Cache ====// - - /** - * Compares two values or objects and returns true if they aren't equal. - * @param current The first value or object which shall be compared. - * @param cache The second value or object which shall be compared. - * @param force If true the returned value is always true. - * @returns {boolean} True if both values or objects aren't equal or force is true, false otherwise. - */ - function checkCache(current, cache, force) { - if (force) - return force; - if (type(current) == TYPES.o && type(cache) == TYPES.o) { - for (var prop in current) { - if (prop !== 'c') { - if (current[LEXICON.hOP](prop) && cache[LEXICON.hOP](prop)) { - if (checkCache(current[prop], cache[prop])) - return true; - } - else { - return true; - } - } - } - } - else { - return current !== cache; - } - return false; - } - - - //==== Shortcuts ====// - - /** - * jQuery extend method shortcut with a appended "true" as first argument. - */ - function extendDeep() { - return FRAMEWORK.extend.apply(this, [true].concat([].slice.call(arguments))); - } - - /** - * jQuery addClass method shortcut. - */ - function addClass(el, classes) { - return _frameworkProto.addClass.call(el, classes); - } - - /** - * jQuery removeClass method shortcut. - */ - function removeClass(el, classes) { - return _frameworkProto.removeClass.call(el, classes); - } - - /** - * jQuery remove method shortcut. - */ - function remove(el) { - return _frameworkProto.remove.call(el); - } - - /** - * Finds the first child element with the given selector of the given element. - * @param el The root element from which the selector shall be valid. - * @param selector The selector of the searched element. - * @returns {*} The first element which is a child of the given element and matches the givens selector. - */ - function findFirst(el, selector) { - return _frameworkProto.find.call(el, selector).eq(0); - } - - - //==== API ====// - - /** - * 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. - * This behavior can be reset by calling the update method. - */ - _base.sleep = function () { - _sleeping = true; - }; - - /** - * Updates the plugin and DOM to the current options. - * This method should only be called if a update is 100% required. - * @param force True if every property shall be updated and the cache shall be ignored. - * !INTERNAL USAGE! : force can be a string "auto", "sync" or "zoom" too - * 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. - * 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. - * if "zoom" then a update takes place where it's assumed that content and host size changed - * @returns {boolean|undefined} - * If force is "sync" then a boolean is returned which indicates whether a update was needed due to pending changes. - * If force is "auto" then a boolean is returned whether a update was needed due to attribute or size changes. - * undefined otherwise. - */ - _base.update = function (force) { - if (_destroyed) - return; - - var attrsChanged; - var contentSizeC; - var isString = type(force) == TYPES.s; - var imgElementSelector = 'img'; - var imgElementLoadEvent = 'load'; - var doUpdateAuto; - var mutHost; - var mutContent; - - if (isString) { - if (force === _strAuto) { - attrsChanged = meaningfulAttrsChanged(); - contentSizeC = updateAutoContentSizeChanged(); - doUpdateAuto = attrsChanged || contentSizeC; - if (doUpdateAuto) { - update({ - _contentSizeChanged: contentSizeC, - _changedOptions: _initialized ? undefined : _currentPreparedOptions - }); - } - } - else if (force === _strSync) { - if (_mutationObserversConnected) { - mutHost = _mutationObserverHostCallback(_mutationObserverHost.takeRecords()); - mutContent = _mutationObserverContentCallback(_mutationObserverContent.takeRecords()); - } - else { - mutHost = _base.update(_strAuto); - } - } - else if (force === 'zoom') { - update({ - _hostSizeChanged: true, - _contentSizeChanged: true - }); - } - } - else { - force = _sleeping || force; - _sleeping = false; - if (!_base.update(_strSync) || force) - update({ _force: force }); - } - if (!_isTextarea) { - _contentElement.find(imgElementSelector).each(function (i, el) { - var index = COMPATIBILITY.inA(el, _imgs); - if (index === -1) - FRAMEWORK(el).off(imgElementLoadEvent, imgOnLoad).on(imgElementLoadEvent, imgOnLoad); - }); - } - return doUpdateAuto || mutHost || mutContent; - }; - - /** - Gets or sets the current options. The update method will be called automatically if new options were set. - * @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. - * @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. - * @returns {*} - */ - _base.options = function (newOptions, value) { - var option = {}; - var changedOps; - - //return current options if newOptions are undefined or empty - if (FRAMEWORK.isEmptyObject(newOptions) || !FRAMEWORK.isPlainObject(newOptions)) { - if (type(newOptions) == TYPES.s) { - if (arguments.length > 1) { - setObjectPropVal(option, newOptions, value); - changedOps = setOptions(option); - } - else - return getObjectPropVal(_currentOptions, newOptions); - } - else - return _currentOptions; - } - else { - changedOps = setOptions(newOptions); - } - - if (!FRAMEWORK.isEmptyObject(changedOps)) { - update({ _changedOptions: changedOps }); - } - }; - - /** - * Restore the DOM, disconnects all observers, remove all resize observers and put the instance to sleep. - */ - _base.destroy = function () { - if (_destroyed) - return; - - //remove this instance from auto update loop - autoUpdateLoop.remove(_base); - - //disconnect all mutation observers - disconnectMutationObservers(); - - //remove all resize observers - setupResizeObserver(_sizeObserverElement); - setupResizeObserver(_sizeAutoObserverElement); - - //remove all extensions - for (var extName in _extensions) - _base.removeExt(extName); - - //remove all 'destroy' events - while (_destroyEvents[LEXICON.l] > 0) - _destroyEvents.pop()(); - - //remove all events from host element - setupHostMouseTouchEvents(true); - - //remove all helper / detection elements - if (_contentGlueElement) - remove(_contentGlueElement); - if (_contentArrangeElement) - remove(_contentArrangeElement); - if (_sizeAutoObserverAdded) - remove(_sizeAutoObserverElement); - - //remove all generated DOM - setupScrollbarsDOM(true); - setupScrollbarCornerDOM(true); - setupStructureDOM(true); - - //remove all generated image load events - for (var i = 0; i < _imgs[LEXICON.l]; i++) - FRAMEWORK(_imgs[i]).off('load', imgOnLoad); - _imgs = undefined; - - _destroyed = true; - _sleeping = true; - - //remove this instance from the instances list - INSTANCES(pluginTargetElement, 0); - dispatchCallback('onDestroyed'); - - //remove all properties and methods - //for (var property in _base) - // delete _base[property]; - //_base = undefined; - }; - - /** - * Scrolls to a given position or element. - * @param coordinates - * 1. Can be "coordinates" which looks like: - * { x : ?, y : ? } OR Object with x and y properties - * { left : ?, top : ? } OR Object with left and top properties - * { l : ?, t : ? } OR Object with l and t properties - * [ ?, ? ] OR Array where the first two element are the coordinates (first is x, second is y) - * ? A single value which stays for both axis - * A value can be a number, a string or a calculation. - * - * Operators: - * [NONE] The current scroll will be overwritten by the value. - * '+=' The value will be added to the current scroll offset - * '-=' The value will be subtracted from the current scroll offset - * '*=' The current scroll wil be multiplicated by the value. - * '/=' The current scroll wil be divided by the value. - * - * Units: - * [NONE] The value is the final scroll amount. final = (value * 1) - * 'px' Same as none - * '%' The value is dependent on the current scroll value. final = ((currentScrollValue / 100) * value) - * 'vw' The value is multiplicated by the viewport width. final = (value * viewportWidth) - * 'vh' The value is multiplicated by the viewport height. final = (value * viewportHeight) - * - * example final values: - * 200, '200px', '50%', '1vw', '1vh', '+=200', '/=1vw', '*=2px', '-=5vh', '+=33%', '+= 50% - 2px', '-= 1vw - 50%' - * - * 2. Can be a HTML or jQuery element: - * The final scroll offset is the offset (without margin) of the given HTML / jQuery element. - * - * 3. Can be a object with a HTML or jQuery element with additional settings: - * { - * el : [HTMLElement, jQuery element], MUST be specified, else this object isn't valid. - * scroll : [string, array, object], Default value is 'always'. - * block : [string, array, object], Default value is 'begin'. - * margin : [number, boolean, array, object] Default value is false. - * } - * - * Possible scroll settings are: - * 'always' Scrolls always. - * 'ifneeded' Scrolls only if the element isnt fully in view. - * 'never' Scrolls never. - * - * Possible block settings are: - * 'begin' Both axis shall be docked to the "begin" edge. - The element will be docked to the top and left edge of the viewport. - * '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.) - * 'center' Both axis shall be docked to "center". - The element will be centered in the viewport. - * 'nearest' The element will be docked to the nearest edge(s). - * - * Possible margin settings are: -- The actual margin of the element wont be affect, this option affects only the final scroll offset. - * [BOOLEAN] If true the css margin of the element will be used, if false no margin will be used. - * [NUMBER] The margin will be used for all edges. - * - * @param duration The duration of the scroll animation, OR a jQuery animation configuration object. - * @param easing The animation easing. - * @param complete The animation complete callback. - * @returns {{ - * position: {x: number, y: number}, - * ratio: {x: number, y: number}, - * max: {x: number, y: number}, - * handleOffset: {x: number, y: number}, - * handleLength: {x: number, y: number}, - * handleLengthRatio: {x: number, y: number}, t - * rackLength: {x: number, y: number}, - * isRTL: boolean, - * isRTLNormalized: boolean - * }} - */ - _base.scroll = function (coordinates, duration, easing, complete) { - if (arguments.length === 0 || coordinates === undefined) { - var infoX = _scrollHorizontalInfo; - var infoY = _scrollVerticalInfo; - var normalizeInvert = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.i; - var normalizeNegate = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.n; - var scrollX = infoX._currentScroll; - var scrollXRatio = infoX._currentScrollRatio; - var maxScrollX = infoX._maxScroll; - scrollXRatio = normalizeInvert ? 1 - scrollXRatio : scrollXRatio; - scrollX = normalizeInvert ? maxScrollX - scrollX : scrollX; - scrollX *= normalizeNegate ? -1 : 1; - maxScrollX *= normalizeNegate ? -1 : 1; - - return { - position: { - x: scrollX, - y: infoY._currentScroll - }, - ratio: { - x: scrollXRatio, - y: infoY._currentScrollRatio - }, - max: { - x: maxScrollX, - y: infoY._maxScroll - }, - handleOffset: { - x: infoX._handleOffset, - y: infoY._handleOffset - }, - handleLength: { - x: infoX._handleLength, - y: infoY._handleLength - }, - handleLengthRatio: { - x: infoX._handleLengthRatio, - y: infoY._handleLengthRatio - }, - trackLength: { - x: infoX._trackLength, - y: infoY._trackLength - }, - snappedHandleOffset: { - x: infoX._snappedHandleOffset, - y: infoY._snappedHandleOffset - }, - isRTL: _isRTL, - isRTLNormalized: _normalizeRTLCache - }; - } - - _base.update(_strSync); - - var normalizeRTL = _normalizeRTLCache; - var coordinatesXAxisProps = [_strX, _strLeft, 'l']; - var coordinatesYAxisProps = [_strY, _strTop, 't']; - var coordinatesOperators = ['+=', '-=', '*=', '/=']; - var durationIsObject = type(duration) == TYPES.o; - var completeCallback = durationIsObject ? duration.complete : complete; - var i; - var finalScroll = {}; - var specialEasing = {}; - var doScrollLeft; - var doScrollTop; - var animationOptions; - var strEnd = 'end'; - var strBegin = 'begin'; - var strCenter = 'center'; - var strNearest = 'nearest'; - var strAlways = 'always'; - var strNever = 'never'; - var strIfNeeded = 'ifneeded'; - var strLength = LEXICON.l; - var settingsAxis; - var settingsScroll; - var settingsBlock; - var settingsMargin; - var finalElement; - var elementObjSettingsAxisValues = [_strX, _strY, 'xy', 'yx']; - var elementObjSettingsBlockValues = [strBegin, strEnd, strCenter, strNearest]; - var elementObjSettingsScrollValues = [strAlways, strNever, strIfNeeded]; - var coordinatesIsElementObj = coordinates[LEXICON.hOP]('el'); - var possibleElement = coordinatesIsElementObj ? coordinates.el : coordinates; - var possibleElementIsJQuery = possibleElement instanceof FRAMEWORK || JQUERY ? possibleElement instanceof JQUERY : false; - var possibleElementIsHTMLElement = possibleElementIsJQuery ? false : isHTMLElement(possibleElement); - var updateScrollbarInfos = function () { - if (doScrollLeft) - refreshScrollbarHandleOffset(true); - if (doScrollTop) - refreshScrollbarHandleOffset(false); - }; - var proxyCompleteCallback = type(completeCallback) != TYPES.f ? undefined : function () { - updateScrollbarInfos(); - completeCallback(); - }; - function checkSettingsStringValue(currValue, allowedValues) { - for (i = 0; i < allowedValues[strLength]; i++) { - if (currValue === allowedValues[i]) - return true; - } - return false; - } - function getRawScroll(isX, coordinates) { - var coordinateProps = isX ? coordinatesXAxisProps : coordinatesYAxisProps; - coordinates = type(coordinates) == TYPES.s || type(coordinates) == TYPES.n ? [coordinates, coordinates] : coordinates; - - if (type(coordinates) == TYPES.a) - return isX ? coordinates[0] : coordinates[1]; - else if (type(coordinates) == TYPES.o) { - //decides RTL normalization "hack" with .n - //normalizeRTL = type(coordinates.n) == TYPES.b ? coordinates.n : normalizeRTL; - for (i = 0; i < coordinateProps[strLength]; i++) - if (coordinateProps[i] in coordinates) - return coordinates[coordinateProps[i]]; - } - } - function getFinalScroll(isX, rawScroll) { - var isString = type(rawScroll) == TYPES.s; - var operator; - var amount; - var scrollInfo = isX ? _scrollHorizontalInfo : _scrollVerticalInfo; - var currScroll = scrollInfo._currentScroll; - var maxScroll = scrollInfo._maxScroll; - var mult = ' * '; - var finalValue; - var isRTLisX = _isRTL && isX; - var normalizeShortcuts = isRTLisX && _rtlScrollBehavior.n && !normalizeRTL; - var strReplace = 'replace'; - var evalFunc = eval; - var possibleOperator; - if (isString) { - //check operator - if (rawScroll[strLength] > 2) { - possibleOperator = rawScroll.substr(0, 2); - if (inArray(possibleOperator, coordinatesOperators) > -1) - operator = possibleOperator; - } - - //calculate units and shortcuts - rawScroll = operator ? rawScroll.substr(2) : rawScroll; - rawScroll = rawScroll - [strReplace](/min/g, 0) //'min' = 0% - [strReplace](//g, (normalizeShortcuts ? '-' : _strEmpty) + _strHundredPercent) //'>' = 100% - [strReplace](/px/g, _strEmpty) - [strReplace](/%/g, mult + (maxScroll * (isRTLisX && _rtlScrollBehavior.n ? -1 : 1) / 100.0)) - [strReplace](/vw/g, mult + _viewportSize.w) - [strReplace](/vh/g, mult + _viewportSize.h); - amount = parseToZeroOrNumber(isNaN(rawScroll) ? parseToZeroOrNumber(evalFunc(rawScroll), true).toFixed() : rawScroll); - } - else { - amount = rawScroll; - } - - if (amount !== undefined && !isNaN(amount) && type(amount) == TYPES.n) { - var normalizeIsRTLisX = normalizeRTL && isRTLisX; - var operatorCurrScroll = currScroll * (normalizeIsRTLisX && _rtlScrollBehavior.n ? -1 : 1); - var invert = normalizeIsRTLisX && _rtlScrollBehavior.i; - var negate = normalizeIsRTLisX && _rtlScrollBehavior.n; - operatorCurrScroll = invert ? (maxScroll - operatorCurrScroll) : operatorCurrScroll; - switch (operator) { - case '+=': - finalValue = operatorCurrScroll + amount; - break; - case '-=': - finalValue = operatorCurrScroll - amount; - break; - case '*=': - finalValue = operatorCurrScroll * amount; - break; - case '/=': - finalValue = operatorCurrScroll / amount; - break; - default: - finalValue = amount; - break; - } - finalValue = invert ? maxScroll - finalValue : finalValue; - finalValue *= negate ? -1 : 1; - finalValue = isRTLisX && _rtlScrollBehavior.n ? MATH.min(0, MATH.max(maxScroll, finalValue)) : MATH.max(0, MATH.min(maxScroll, finalValue)); - } - return finalValue === currScroll ? undefined : finalValue; - } - function getPerAxisValue(value, valueInternalType, defaultValue, allowedValues) { - var resultDefault = [defaultValue, defaultValue]; - var valueType = type(value); - var valueArrLength; - var valueArrItem; - - //value can be [ string, or array of two strings ] - if (valueType == valueInternalType) { - value = [value, value]; - } - else if (valueType == TYPES.a) { - valueArrLength = value[strLength]; - if (valueArrLength > 2 || valueArrLength < 1) - value = resultDefault; - else { - if (valueArrLength === 1) - value[1] = defaultValue; - for (i = 0; i < valueArrLength; i++) { - valueArrItem = value[i]; - if (type(valueArrItem) != valueInternalType || !checkSettingsStringValue(valueArrItem, allowedValues)) { - value = resultDefault; - break; - } - } - } - } - else if (valueType == TYPES.o) - value = [value[_strX] || defaultValue, value[_strY] || defaultValue]; - else - value = resultDefault; - return { x: value[0], y: value[1] }; - } - function generateMargin(marginTopRightBottomLeftArray) { - var result = []; - var currValue; - var currValueType; - var valueDirections = [_strTop, _strRight, _strBottom, _strLeft]; - for (i = 0; i < marginTopRightBottomLeftArray[strLength]; i++) { - if (i === valueDirections[strLength]) - break; - currValue = marginTopRightBottomLeftArray[i]; - currValueType = type(currValue); - if (currValueType == TYPES.b) - result.push(currValue ? parseToZeroOrNumber(finalElement.css(_strMarginMinus + valueDirections[i])) : 0); - else - result.push(currValueType == TYPES.n ? currValue : 0); - } - return result; - } - - if (possibleElementIsJQuery || possibleElementIsHTMLElement) { - //get settings - var margin = coordinatesIsElementObj ? coordinates.margin : 0; - var axis = coordinatesIsElementObj ? coordinates.axis : 0; - var scroll = coordinatesIsElementObj ? coordinates.scroll : 0; - var block = coordinatesIsElementObj ? coordinates.block : 0; - var marginDefault = [0, 0, 0, 0]; - var marginType = type(margin); - var marginLength; - finalElement = possibleElementIsJQuery ? possibleElement : FRAMEWORK(possibleElement); - - if (finalElement[strLength] > 0) { - //margin can be [ boolean, number, array of 2, array of 4, object ] - if (marginType == TYPES.n || marginType == TYPES.b) - margin = generateMargin([margin, margin, margin, margin]); - else if (marginType == TYPES.a) { - marginLength = margin[strLength]; - if (marginLength === 2) - margin = generateMargin([margin[0], margin[1], margin[0], margin[1]]); - else if (marginLength >= 4) - margin = generateMargin(margin); - else - margin = marginDefault; - } - else if (marginType == TYPES.o) - margin = generateMargin([margin[_strTop], margin[_strRight], margin[_strBottom], margin[_strLeft]]); - else - margin = marginDefault; - - //block = type(block) === TYPES.b ? block ? [ strNearest, strBegin ] : [ strNearest, strEnd ] : block; - settingsAxis = checkSettingsStringValue(axis, elementObjSettingsAxisValues) ? axis : 'xy'; - settingsScroll = getPerAxisValue(scroll, TYPES.s, strAlways, elementObjSettingsScrollValues); - settingsBlock = getPerAxisValue(block, TYPES.s, strBegin, elementObjSettingsBlockValues); - settingsMargin = margin; - - var viewportScroll = { - l: _scrollHorizontalInfo._currentScroll, - t: _scrollVerticalInfo._currentScroll - }; - // use padding element instead of viewport element because padding element has never padding, margin or position applied. - var viewportOffset = _paddingElement.offset(); - - //get coordinates - var elementOffset = finalElement.offset(); - var doNotScroll = { - x: settingsScroll.x == strNever || settingsAxis == _strY, - y: settingsScroll.y == strNever || settingsAxis == _strX - }; - elementOffset[_strTop] -= settingsMargin[0]; - elementOffset[_strLeft] -= settingsMargin[3]; - var elementScrollCoordinates = { - x: MATH.round(elementOffset[_strLeft] - viewportOffset[_strLeft] + viewportScroll.l), - y: MATH.round(elementOffset[_strTop] - viewportOffset[_strTop] + viewportScroll.t) - }; - if (_isRTL) { - if (!_rtlScrollBehavior.n && !_rtlScrollBehavior.i) - elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + viewportScroll.l); - if (_rtlScrollBehavior.n && normalizeRTL) - elementScrollCoordinates.x *= -1; - if (_rtlScrollBehavior.i && normalizeRTL) - elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + (_scrollHorizontalInfo._maxScroll - viewportScroll.l)); - } - - //measuring is required - if (settingsBlock.x != strBegin || settingsBlock.y != strBegin || settingsScroll.x == strIfNeeded || settingsScroll.y == strIfNeeded || _isRTL) { - var measuringElm = finalElement[0]; - var rawElementSize = _supportTransform ? measuringElm[LEXICON.bCR]() : { - width: measuringElm[LEXICON.oW], - height: measuringElm[LEXICON.oH] - }; - var elementSize = { - w: rawElementSize[_strWidth] + settingsMargin[3] + settingsMargin[1], - h: rawElementSize[_strHeight] + settingsMargin[0] + settingsMargin[2] - }; - var finalizeBlock = function (isX) { - var vars = getScrollbarVars(isX); - var wh = vars._w_h; - var lt = vars._left_top; - var xy = vars._x_y; - var blockIsEnd = settingsBlock[xy] == (isX ? _isRTL ? strBegin : strEnd : strEnd); - var blockIsCenter = settingsBlock[xy] == strCenter; - var blockIsNearest = settingsBlock[xy] == strNearest; - var scrollNever = settingsScroll[xy] == strNever; - var scrollIfNeeded = settingsScroll[xy] == strIfNeeded; - var vpSize = _viewportSize[wh]; - var vpOffset = viewportOffset[lt]; - var elSize = elementSize[wh]; - var elOffset = elementOffset[lt]; - var divide = blockIsCenter ? 2 : 1; - var elementCenterOffset = elOffset + (elSize / 2); - var viewportCenterOffset = vpOffset + (vpSize / 2); - var isInView = - elSize <= vpSize - && elOffset >= vpOffset - && elOffset + elSize <= vpOffset + vpSize; - - if (scrollNever) - doNotScroll[xy] = true; - else if (!doNotScroll[xy]) { - if (blockIsNearest || scrollIfNeeded) { - doNotScroll[xy] = scrollIfNeeded ? isInView : false; - blockIsEnd = elSize < vpSize ? elementCenterOffset > viewportCenterOffset : elementCenterOffset < viewportCenterOffset; - } - elementScrollCoordinates[xy] -= blockIsEnd || blockIsCenter ? ((vpSize / divide) - (elSize / divide)) * (isX && _isRTL && normalizeRTL ? -1 : 1) : 0; - } - }; - finalizeBlock(true); - finalizeBlock(false); - } - - if (doNotScroll.y) - delete elementScrollCoordinates.y; - if (doNotScroll.x) - delete elementScrollCoordinates.x; - - coordinates = elementScrollCoordinates; - } - } - - finalScroll[_strScrollLeft] = getFinalScroll(true, getRawScroll(true, coordinates)); - finalScroll[_strScrollTop] = getFinalScroll(false, getRawScroll(false, coordinates)); - doScrollLeft = finalScroll[_strScrollLeft] !== undefined; - doScrollTop = finalScroll[_strScrollTop] !== undefined; - - if ((doScrollLeft || doScrollTop) && (duration > 0 || durationIsObject)) { - if (durationIsObject) { - duration.complete = proxyCompleteCallback; - _viewportElement.animate(finalScroll, duration); - } - else { - animationOptions = { - duration: duration, - complete: proxyCompleteCallback - }; - if (type(easing) == TYPES.a || FRAMEWORK.isPlainObject(easing)) { - specialEasing[_strScrollLeft] = easing[0] || easing.x; - specialEasing[_strScrollTop] = easing[1] || easing.y; - animationOptions.specialEasing = specialEasing; - } - else { - animationOptions.easing = easing; - } - _viewportElement.animate(finalScroll, animationOptions); - } - } - else { - if (doScrollLeft) - _viewportElement[_strScrollLeft](finalScroll[_strScrollLeft]); - if (doScrollTop) - _viewportElement[_strScrollTop](finalScroll[_strScrollTop]); - updateScrollbarInfos(); - } - }; - - /** - * Stops all scroll animations. - * @returns {*} The current OverlayScrollbars instance (for chaining). - */ - _base.scrollStop = function (param1, param2, param3) { - _viewportElement.stop(param1, param2, param3); - return _base; - }; - - /** - * Returns all relevant elements. - * @param elementName The name of the element which shall be returned. - * @returns {{target: *, host: *, padding: *, viewport: *, content: *, scrollbarHorizontal: {scrollbar: *, track: *, handle: *}, scrollbarVertical: {scrollbar: *, track: *, handle: *}, scrollbarCorner: *} | *} - */ - _base.getElements = function (elementName) { - var obj = { - target: _targetElementNative, - host: _hostElementNative, - padding: _paddingElementNative, - viewport: _viewportElementNative, - content: _contentElementNative, - scrollbarHorizontal: { - scrollbar: _scrollbarHorizontalElement[0], - track: _scrollbarHorizontalTrackElement[0], - handle: _scrollbarHorizontalHandleElement[0] - }, - scrollbarVertical: { - scrollbar: _scrollbarVerticalElement[0], - track: _scrollbarVerticalTrackElement[0], - handle: _scrollbarVerticalHandleElement[0] - }, - scrollbarCorner: _scrollbarCornerElement[0] - }; - return type(elementName) == TYPES.s ? getObjectPropVal(obj, elementName) : obj; - }; - - /** - * Returns a object which describes the current state of this instance. - * @param stateProperty A specific property from the state object which shall be returned. - * @returns {{widthAuto, heightAuto, overflowAmount, hideOverflow, hasOverflow, contentScrollSize, viewportSize, hostSize, autoUpdate} | *} - */ - _base.getState = function (stateProperty) { - function prepare(obj) { - if (!FRAMEWORK.isPlainObject(obj)) - return obj; - var extended = extendDeep({}, obj); - var changePropertyName = function (from, to) { - if (extended[LEXICON.hOP](from)) { - extended[to] = extended[from]; - delete extended[from]; - } - }; - changePropertyName('w', _strWidth); //change w to width - changePropertyName('h', _strHeight); //change h to height - delete extended.c; //delete c (the 'changed' prop) - return extended; - }; - var obj = { - destroyed: !!prepare(_destroyed), - sleeping: !!prepare(_sleeping), - autoUpdate: prepare(!_mutationObserversConnected), - widthAuto: prepare(_widthAutoCache), - heightAuto: prepare(_heightAutoCache), - padding: prepare(_cssPaddingCache), - overflowAmount: prepare(_overflowAmountCache), - hideOverflow: prepare(_hideOverflowCache), - hasOverflow: prepare(_hasOverflowCache), - contentScrollSize: prepare(_contentScrollSizeCache), - viewportSize: prepare(_viewportSize), - hostSize: prepare(_hostSizeCache), - documentMixed: prepare(_documentMixed) - }; - return type(stateProperty) == TYPES.s ? getObjectPropVal(obj, stateProperty) : obj; - }; - - /** - * Gets all or specific extension instance. - * @param extName The name of the extension from which the instance shall be got. - * @returns {{}} The instance of the extension with the given name or undefined if the instance couldn't be found. - */ - _base.ext = function (extName) { - var result; - var privateMethods = _extensionsPrivateMethods.split(' '); - var i = 0; - if (type(extName) == TYPES.s) { - if (_extensions[LEXICON.hOP](extName)) { - result = extendDeep({}, _extensions[extName]); - for (; i < privateMethods.length; i++) - delete result[privateMethods[i]]; - } - } - else { - result = {}; - for (i in _extensions) - result[i] = extendDeep({}, _base.ext(i)); - } - return result; - }; - - /** - * Adds a extension to this instance. - * @param extName The name of the extension which shall be added. - * @param extensionOptions The extension options which shall be used. - * @returns {{}} The instance of the added extension or undefined if the extension couldn't be added properly. - */ - _base.addExt = function (extName, extensionOptions) { - var registeredExtensionObj = _plugin.extension(extName); - var instance; - var instanceAdded; - var instanceContract; - var contractResult; - var contractFulfilled = true; - if (registeredExtensionObj) { - if (!_extensions[LEXICON.hOP](extName)) { - instance = registeredExtensionObj.extensionFactory.call(_base, - extendDeep({}, registeredExtensionObj.defaultOptions), - FRAMEWORK, - COMPATIBILITY); - - if (instance) { - instanceContract = instance.contract; - if (type(instanceContract) == TYPES.f) { - contractResult = instanceContract(window); - contractFulfilled = type(contractResult) == TYPES.b ? contractResult : contractFulfilled; - } - if (contractFulfilled) { - _extensions[extName] = instance; - instanceAdded = instance.added; - if (type(instanceAdded) == TYPES.f) - instanceAdded(extensionOptions); - - return _base.ext(extName); - } - } - } - else - return _base.ext(extName); - } - else - console.warn("A extension with the name \"" + extName + "\" isn't registered."); - }; - - /** - * Removes a extension from this instance. - * @param extName The name of the extension which shall be removed. - * @returns {boolean} True if the extension was removed, false otherwise e.g. if the extension wasn't added before. - */ - _base.removeExt = function (extName) { - var instance = _extensions[extName]; - var instanceRemoved; - if (instance) { - delete _extensions[extName]; - - instanceRemoved = instance.removed; - if (type(instanceRemoved) == TYPES.f) - instanceRemoved(); - - return true; - } - return false; - }; - - /** - * Constructs the plugin. - * @param targetElement The element to which the plugin shall be applied. - * @param options The initial options of the plugin. - * @param extensions The extension(s) which shall be added right after the initialization. - * @returns {boolean} True if the plugin was successfully initialized, false otherwise. - */ - function construct(targetElement, options, extensions) { - _defaultOptions = globals.defaultOptions; - _nativeScrollbarStyling = globals.nativeScrollbarStyling; - _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); - _nativeScrollbarIsOverlaid = extendDeep({}, globals.nativeScrollbarIsOverlaid); - _overlayScrollbarDummySize = extendDeep({}, globals.overlayScrollbarDummySize); - _rtlScrollBehavior = extendDeep({}, globals.rtlScrollBehavior); - - //parse & set options but don't update - setOptions(extendDeep({}, _defaultOptions, options)); - - _cssCalc = globals.cssCalc; - _msieVersion = globals.msie; - _autoUpdateRecommended = globals.autoUpdateRecommended; - _supportTransition = globals.supportTransition; - _supportTransform = globals.supportTransform; - _supportPassiveEvents = globals.supportPassiveEvents; - _supportResizeObserver = globals.supportResizeObserver; - _supportMutationObserver = globals.supportMutationObserver; - _restrictedMeasuring = globals.restrictedMeasuring; - _documentElement = FRAMEWORK(targetElement.ownerDocument); - _documentElementNative = _documentElement[0]; - _windowElement = FRAMEWORK(_documentElementNative.defaultView || _documentElementNative.parentWindow); - _windowElementNative = _windowElement[0]; - _htmlElement = findFirst(_documentElement, 'html'); - _bodyElement = findFirst(_htmlElement, 'body'); - _targetElement = FRAMEWORK(targetElement); - _targetElementNative = _targetElement[0]; - _isTextarea = _targetElement.is('textarea'); - _isBody = _targetElement.is('body'); - _documentMixed = _documentElementNative !== document; - - /* On a div Element The if checks only whether: - * - the targetElement has the class "os-host" - * - the targetElement has a a child with the class "os-padding" - * - * If that's the case, its assumed the DOM has already the following structure: - * (The ".os-host" element is the targetElement) - * - *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- * - * ===================================================================================== - * - * On a Textarea Element The if checks only whether: - * - the targetElement has the class "os-textarea" - * - the targetElement is inside a element with the class "os-content" - * - * If that's the case, its assumed the DOM has already the following structure: - * (The ".os-textarea" (textarea) element is the targetElement) - * - *
- *
- *
- *
- *
- *
- * - *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- */ - _domExists = _isTextarea - ? _targetElement.hasClass(_classNameTextareaElement) && _targetElement.parent().hasClass(_classNameContentElement) - : _targetElement.hasClass(_classNameHostElement) && _targetElement.children(_strDot + _classNamePaddingElement)[LEXICON.l]; - - var initBodyScroll; - var bodyMouseTouchDownListener; - - //check if the plugin hasn't to be initialized - if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y && !_currentPreparedOptions.nativeScrollbarsOverlaid.initialize) { - dispatchCallback('onInitializationWithdrawn'); - if (_domExists) { - setupStructureDOM(true); - setupScrollbarsDOM(true); - setupScrollbarCornerDOM(true); - } - - _destroyed = true; - _sleeping = true; - - return _base; - } - - if (_isBody) { - initBodyScroll = {}; - initBodyScroll.l = MATH.max(_targetElement[_strScrollLeft](), _htmlElement[_strScrollLeft](), _windowElement[_strScrollLeft]()); - initBodyScroll.t = MATH.max(_targetElement[_strScrollTop](), _htmlElement[_strScrollTop](), _windowElement[_strScrollTop]()); - - bodyMouseTouchDownListener = function () { - _viewportElement.removeAttr(LEXICON.ti); - setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, true, true); - } - } - - //build OverlayScrollbars DOM - setupStructureDOM(); - setupScrollbarsDOM(); - setupScrollbarCornerDOM(); - - //create OverlayScrollbars events - setupStructureEvents(); - setupScrollbarEvents(true); - setupScrollbarEvents(false); - setupScrollbarCornerEvents(); - - //create mutation observers - createMutationObservers(); - - //build resize observer for the host element - setupResizeObserver(_sizeObserverElement, hostOnResized); - - if (_isBody) { - //apply the body scroll to handle it right in the update method - _viewportElement[_strScrollLeft](initBodyScroll.l)[_strScrollTop](initBodyScroll.t); - - //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 - if (document.activeElement == targetElement && _viewportElementNative.focus) { - //set a tabindex to make the viewportElement focusable - _viewportElement.attr(LEXICON.ti, '-1'); - _viewportElementNative.focus(); - - /* the tabindex has to be removed due to; - * If you set the tabindex attribute on an
, then its child content cannot be scrolled with the arrow keys unless you set tabindex on the content, too - * https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex - */ - setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, false, true); - } - } - - //update for the first time & initialize cache - _base.update(_strAuto); - - //the plugin is initialized now! - _initialized = true; - dispatchCallback('onInitialized'); - - //call all callbacks which would fire before the initialized was complete - each(_callbacksInitQeueue, function (index, value) { dispatchCallback(value.n, value.a); }); - _callbacksInitQeueue = []; - - //add extensions - if (type(extensions) == TYPES.s) - extensions = [extensions]; - if (COMPATIBILITY.isA(extensions)) - each(extensions, function (index, value) { _base.addExt(value); }); - else if (FRAMEWORK.isPlainObject(extensions)) - each(extensions, function (key, value) { _base.addExt(key, value); }); - - //add the transition class for transitions AFTER the first update & AFTER the applied extensions (for preventing unwanted transitions) - setTimeout(function () { - if (_supportTransition && !_destroyed) - addClass(_hostElement, _classNameHostTransition); - }, 333); - - return _base; - } - - if (_plugin.valid(construct(pluginTargetElement, options, extensions))) { - INSTANCES(pluginTargetElement, _base); - } - - return _base; - } - - /** - * Initializes a new OverlayScrollbarsInstance object or changes options if already initialized or returns the current instance. - * @param pluginTargetElements The elements to which the Plugin shall be initialized. - * @param options The custom options with which the plugin shall be initialized. - * @param extensions The extension(s) which shall be added right after initialization. - * @returns {*} - */ - _plugin = window[PLUGINNAME] = function (pluginTargetElements, options, extensions) { - if (arguments[LEXICON.l] === 0) - return this; - - var arr = []; - var optsIsPlainObj = FRAMEWORK.isPlainObject(options); - var inst; - var result; - - //pluginTargetElements is null or undefined - if (!pluginTargetElements) - return optsIsPlainObj || !options ? result : arr; - - /* - pluginTargetElements will be converted to: - 1. A jQueryElement Array - 2. A HTMLElement Array - 3. A Array with a single HTML Element - so pluginTargetElements is always a array. - */ - pluginTargetElements = pluginTargetElements[LEXICON.l] != undefined ? pluginTargetElements : [pluginTargetElements[0] || pluginTargetElements]; - initOverlayScrollbarsStatics(); - - if (pluginTargetElements[LEXICON.l] > 0) { - if (optsIsPlainObj) { - FRAMEWORK.each(pluginTargetElements, function (i, v) { - inst = v; - if (inst !== undefined) - arr.push(OverlayScrollbarsInstance(inst, options, extensions, _pluginsGlobals, _pluginsAutoUpdateLoop)); - }); - } - else { - FRAMEWORK.each(pluginTargetElements, function (i, v) { - inst = INSTANCES(v); - if ((options === '!' && _plugin.valid(inst)) || (COMPATIBILITY.type(options) == TYPES.f && options(v, inst))) - arr.push(inst); - else if (options === undefined) - arr.push(inst); - }); - } - result = arr[LEXICON.l] === 1 ? arr[0] : arr; - } - return result; - }; - - /** - * Returns a object which contains global information about the plugin and each instance of it. - * The returned object is just a copy, that means that changes to the returned object won't have any effect to the original object. - */ - _plugin.globals = function () { - initOverlayScrollbarsStatics(); - var globals = FRAMEWORK.extend(true, {}, _pluginsGlobals); - delete globals['msie']; - return globals; - }; - - /** - * Gets or Sets the default options for each new plugin initialization. - * @param newDefaultOptions The object with which the default options shall be extended. - */ - _plugin.defaultOptions = function (newDefaultOptions) { - initOverlayScrollbarsStatics(); - var currDefaultOptions = _pluginsGlobals.defaultOptions; - if (newDefaultOptions === undefined) - return FRAMEWORK.extend(true, {}, currDefaultOptions); - - //set the new default options - _pluginsGlobals.defaultOptions = FRAMEWORK.extend(true, {}, currDefaultOptions, _pluginsOptions._validate(newDefaultOptions, _pluginsOptions._template, true, currDefaultOptions)._default); - }; - - /** - * Checks whether the passed instance is a non-destroyed OverlayScrollbars instance. - * @param osInstance The potential OverlayScrollbars instance which shall be checked. - * @returns {boolean} True if the passed value is a non-destroyed OverlayScrollbars instance, false otherwise. - */ - _plugin.valid = function (osInstance) { - return osInstance instanceof _plugin && !osInstance.getState().destroyed; - }; - - /** - * Registers, Unregisters or returns a extension. - * Register: Pass the name and the extension. (defaultOptions is optional) - * Unregister: Pass the name and anything except a function as extension parameter. - * Get extension: Pass the name of the extension which shall be got. - * Get all extensions: Pass no arguments. - * @param extensionName The name of the extension which shall be registered, unregistered or returned. - * @param extension A function which generates the instance of the extension or anything other to remove a already registered extension. - * @param defaultOptions The default options which shall be used for the registered extension. - */ - _plugin.extension = function (extensionName, extension, defaultOptions) { - var extNameTypeString = COMPATIBILITY.type(extensionName) == TYPES.s; - var argLen = arguments[LEXICON.l]; - var i = 0; - if (argLen < 1 || !extNameTypeString) { - //return a copy of all extension objects - return FRAMEWORK.extend(true, { length: _pluginsExtensions[LEXICON.l] }, _pluginsExtensions); - } - else if (extNameTypeString) { - if (COMPATIBILITY.type(extension) == TYPES.f) { - //register extension - _pluginsExtensions.push({ - name: extensionName, - extensionFactory: extension, - defaultOptions: defaultOptions - }); - } - else { - for (; i < _pluginsExtensions[LEXICON.l]; i++) { - if (_pluginsExtensions[i].name === extensionName) { - if (argLen > 1) - _pluginsExtensions.splice(i, 1); //remove extension - else - return FRAMEWORK.extend(true, {}, _pluginsExtensions[i]); //return extension with the given name - } - } - } - } - }; - - return _plugin; - })(); - - if (JQUERY && JQUERY.fn) { - /** - * The jQuery initialization interface. - * @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. - * @param extensions The extension(s) which shall be added right after initialization. - * @returns {*} After initialization it returns the jQuery element array, else it returns the instance(s) of the elements which are selected. - */ - JQUERY.fn.overlayScrollbars = function (options, extensions) { - var _elements = this; - if (JQUERY.isPlainObject(options)) { - JQUERY.each(_elements, function () { PLUGIN(this, options, extensions); }); - return _elements; - } - else - return PLUGIN(_elements, options); - }; - } - return PLUGIN; - } +/*! + * OverlayScrollbars + * https://github.com/KingSora/OverlayScrollbars + * + * Version: 1.11.0 + * + * Copyright KingSora | Rene Haas. + * https://github.com/KingSora + * + * Released under the MIT license. + * Date: 29.02.2020 + */ + +(function (global, factory) { + if (typeof define === 'function' && define.amd) + define(function () { return factory(global, global.document, undefined); }); + else if (typeof module === 'object' && typeof module.exports === 'object') + module.exports = factory(global, global.document, undefined); + else + factory(global, global.document, undefined); +}(typeof window !== 'undefined' ? window : this, + function (window, document, undefined) { + 'use strict'; + var PLUGINNAME = 'OverlayScrollbars'; + var TYPES = { + o: 'object', + f: 'function', + a: 'array', + s: 'string', + b: 'boolean', + n: 'number', + u: 'undefined', + z: 'null' + //d : 'date', + //e : 'error', + //r : 'regexp', + //y : 'symbol' + }; + var LEXICON = { + c: 'class', + s: 'style', + i: 'id', + l: 'length', + p: 'prototype', + ti: 'tabindex', + oH: 'offsetHeight', + cH: 'clientHeight', + sH: 'scrollHeight', + oW: 'offsetWidth', + cW: 'clientWidth', + sW: 'scrollWidth', + hOP: 'hasOwnProperty', + bCR: 'getBoundingClientRect' + }; + var VENDORS = (function () { + //https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix + var jsCache = {}; + var cssCache = {}; + var cssPrefixes = ['-webkit-', '-moz-', '-o-', '-ms-']; + var jsPrefixes = ['WebKit', 'Moz', 'O', 'MS']; + function firstLetterToUpper(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + + return { + _cssPrefixes: cssPrefixes, + _jsPrefixes: jsPrefixes, + _cssProperty: function (name) { + var result = cssCache[name]; + + if (cssCache[LEXICON.hOP](name)) + return result; + + var uppercasedName = firstLetterToUpper(name); + var elmStyle = document.createElement('div')[LEXICON.s]; + var resultPossibilities; + var i = 0; + var v; + var currVendorWithoutDashes; + + for (; i < cssPrefixes.length; i++) { + currVendorWithoutDashes = cssPrefixes[i].replace(/-/g, ''); + resultPossibilities = [ + name, //transition + cssPrefixes[i] + name, //-webkit-transition + currVendorWithoutDashes + uppercasedName, //webkitTransition + firstLetterToUpper(currVendorWithoutDashes) + uppercasedName //WebkitTransition + ]; + for (v = 0; v < resultPossibilities[LEXICON.l]; v++) { + if (elmStyle[resultPossibilities[v]] !== undefined) { + result = resultPossibilities[v]; + break; + } + } + } + + cssCache[name] = result; + return result; + }, + _jsAPI: function (name, isInterface, fallback) { + var i = 0; + var result = jsCache[name]; + + if (!jsCache[LEXICON.hOP](name)) { + result = window[name]; + for (; i < jsPrefixes[LEXICON.l]; i++) + result = result || window[(isInterface ? jsPrefixes[i] : jsPrefixes[i].toLowerCase()) + firstLetterToUpper(name)]; + jsCache[name] = result; + } + return result || fallback; + } + + } + })(); + var COMPATIBILITY = (function () { + function windowSize(x) { + return x ? window.innerWidth || document.documentElement[LEXICON.cW] || document.body[LEXICON.cW] : window.innerHeight || document.documentElement[LEXICON.cH] || document.body[LEXICON.cH]; + } + function bind(func, thisObj) { + if (typeof func != TYPES.f) { + throw "Can't bind function!"; + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + //throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + var proto = LEXICON.p; + var aArgs = Array[proto].slice.call(arguments, 2); + var fNOP = function () { }; + var fBound = function () { return func.apply(this instanceof fNOP ? this : thisObj, aArgs.concat(Array[proto].slice.call(arguments))); }; + + if (func[proto]) + fNOP[proto] = func[proto]; // Function.prototype doesn't have a prototype property + fBound[proto] = new fNOP(); + + return fBound; + } + + return { + /** + * Gets the current window width. + * @returns {Number|number} The current window width in pixel. + */ + wW: bind(windowSize, 0, true), + + /** + * Gets the current window height. + * @returns {Number|number} The current window height in pixel. + */ + wH: bind(windowSize, 0), + + /** + * Gets the MutationObserver Object or undefined if not supported. + * @returns {MutationObserver|*|undefined} The MutationsObserver Object or undefined. + */ + mO: bind(VENDORS._jsAPI, 0, 'MutationObserver', true), + + /** + * Gets the ResizeObserver Object or undefined if not supported. + * @returns {MutationObserver|*|undefined} The ResizeObserver Object or undefined. + */ + rO: bind(VENDORS._jsAPI, 0, 'ResizeObserver', true), + + /** + * Gets the RequestAnimationFrame method or it's corresponding polyfill. + * @returns {*|Function} The RequestAnimationFrame method or it's corresponding polyfill. + */ + rAF: bind(VENDORS._jsAPI, 0, 'requestAnimationFrame', false, function (func) { return window.setTimeout(func, 1000 / 60); }), + + /** + * Gets the CancelAnimationFrame method or it's corresponding polyfill. + * @returns {*|Function} The CancelAnimationFrame method or it's corresponding polyfill. + */ + cAF: bind(VENDORS._jsAPI, 0, 'cancelAnimationFrame', false, function (id) { return window.clearTimeout(id); }), + + /** + * Gets the current time. + * @returns {number} The current time. + */ + now: function () { + return Date.now && Date.now() || new Date().getTime(); + }, + + /** + * Stops the propagation of the given event. + * @param event The event of which the propagation shall be stoped. + */ + stpP: function (event) { + if (event.stopPropagation) + event.stopPropagation(); + else + event.cancelBubble = true; + }, + + /** + * Prevents the default action of the given event. + * @param event The event of which the default action shall be prevented. + */ + prvD: function (event) { + if (event.preventDefault && event.cancelable) + event.preventDefault(); + else + event.returnValue = false; + }, + + /** + * Gets the pageX and pageY values of the given mouse event. + * @param event The mouse event of which the pageX and pageX shall be got. + * @returns {{x: number, y: number}} x = pageX value, y = pageY value. + */ + page: function (event) { + event = event.originalEvent || event; + + var strPage = 'page'; + var strClient = 'client'; + var strX = 'X'; + var strY = 'Y'; + var target = event.target || event.srcElement || document; + var eventDoc = target.ownerDocument || document; + var doc = eventDoc.documentElement; + var body = eventDoc.body; + + //if touch event return return pageX/Y of it + if (event.touches !== undefined) { + var touch = event.touches[0]; + return { + x: touch[strPage + strX], + y: touch[strPage + strY] + } + } + + // Calculate pageX/Y if not native supported + if (!event[strPage + strX] && event[strClient + strX] && event[strClient + strX] != null) { + + return { + x: event[strClient + strX] + + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - + (doc && doc.clientLeft || body && body.clientLeft || 0), + y: event[strClient + strY] + + (doc && doc.scrollTop || body && body.scrollTop || 0) - + (doc && doc.clientTop || body && body.clientTop || 0) + } + } + return { + x: event[strPage + strX], + y: event[strPage + strY] + }; + }, + + /** + * Gets the clicked mouse button of the given mouse event. + * @param event The mouse event of which the clicked button shal be got. + * @returns {number} The number of the clicked mouse button. (0 : none | 1 : leftButton | 2 : middleButton | 3 : rightButton) + */ + mBtn: function (event) { + var button = event.button; + if (!event.which && button !== undefined) + return (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); + else + return event.which; + }, + + /** + * Checks whether a item is in the given array and returns its index. + * @param item The item of which the position in the array shall be determined. + * @param arr The array. + * @returns {number} The zero based index of the item or -1 if the item isn't in the array. + */ + inA: function (item, arr) { + for (var i = 0; i < arr[LEXICON.l]; i++) + //Sometiems in IE a "SCRIPT70" Permission denied error occurs if HTML elements in a iFrame are compared + try { + if (arr[i] === item) + return i; + } + catch (e) { } + return -1; + }, + + /** + * Returns true if the given value is a array. + * @param arr The potential array. + * @returns {boolean} True if the given value is a array, false otherwise. + */ + isA: function (arr) { + var def = Array.isArray; + return def ? def(arr) : this.type(arr) == TYPES.a; + }, + + /** + * Determine the internal JavaScript [[Class]] of the given object. + * @param obj The object of which the type shall be determined. + * @returns {string} The type of the given object. + */ + type: function (obj) { + if (obj === undefined) + return obj + ''; + if (obj === null) + return obj + ''; + return Object[LEXICON.p].toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase(); + }, + + + bind: bind + + /** + * Gets the vendor-prefixed CSS property by the given name. + * For example the given name is "transform" and you're using a old Firefox browser then the returned value would be "-moz-transform". + * If the browser doesn't need a vendor-prefix, then the returned string is the given name. + * If the browser doesn't support the given property name at all (not even with a vendor-prefix) the returned value is null. + * @param propName The unprefixed CSS property name. + * @returns {string|null} The vendor-prefixed CSS property or null if the browser doesn't support the given CSS property. + + cssProp: function(propName) { + return VENDORS._cssProperty(propName); + } + */ + } + })(); + + var MATH = Math; + var JQUERY = window.jQuery; + var EASING = (function () { + var _easingsMath = { + p: MATH.PI, + c: MATH.cos, + s: MATH.sin, + w: MATH.pow, + t: MATH.sqrt, + n: MATH.asin, + a: MATH.abs, + o: 1.70158 + }; + + /* + x : current percent (0 - 1), + t : current time (duration * percent), + b : start value (from), + c : end value (to), + d : duration + + easingName : function(x, t, b, c, d) { return easedValue; } + */ + + return { + swing: function (x, t, b, c, d) { + return 0.5 - _easingsMath.c(x * _easingsMath.p) / 2; + }, + linear: function (x, t, b, c, d) { + return x; + }, + easeInQuad: function (x, t, b, c, d) { + return c * (t /= d) * t + b; + }, + easeOutQuad: function (x, t, b, c, d) { + return -c * (t /= d) * (t - 2) + b; + }, + easeInOutQuad: function (x, t, b, c, d) { + return ((t /= d / 2) < 1) ? c / 2 * t * t + b : -c / 2 * ((--t) * (t - 2) - 1) + b; + }, + easeInCubic: function (x, t, b, c, d) { + return c * (t /= d) * t * t + b; + }, + easeOutCubic: function (x, t, b, c, d) { + return c * ((t = t / d - 1) * t * t + 1) + b; + }, + easeInOutCubic: function (x, t, b, c, d) { + return ((t /= d / 2) < 1) ? c / 2 * t * t * t + b : c / 2 * ((t -= 2) * t * t + 2) + b; + }, + easeInQuart: function (x, t, b, c, d) { + return c * (t /= d) * t * t * t + b; + }, + easeOutQuart: function (x, t, b, c, d) { + return -c * ((t = t / d - 1) * t * t * t - 1) + b; + }, + easeInOutQuart: function (x, t, b, c, d) { + return ((t /= d / 2) < 1) ? c / 2 * t * t * t * t + b : -c / 2 * ((t -= 2) * t * t * t - 2) + b; + }, + easeInQuint: function (x, t, b, c, d) { + return c * (t /= d) * t * t * t * t + b; + }, + easeOutQuint: function (x, t, b, c, d) { + return c * ((t = t / d - 1) * t * t * t * t + 1) + b; + }, + easeInOutQuint: function (x, t, b, c, d) { + return ((t /= d / 2) < 1) ? c / 2 * t * t * t * t * t + b : c / 2 * ((t -= 2) * t * t * t * t + 2) + b; + }, + easeInSine: function (x, t, b, c, d) { + return -c * _easingsMath.c(t / d * (_easingsMath.p / 2)) + c + b; + }, + easeOutSine: function (x, t, b, c, d) { + return c * _easingsMath.s(t / d * (_easingsMath.p / 2)) + b; + }, + easeInOutSine: function (x, t, b, c, d) { + return -c / 2 * (_easingsMath.c(_easingsMath.p * t / d) - 1) + b; + }, + easeInExpo: function (x, t, b, c, d) { + return (t == 0) ? b : c * _easingsMath.w(2, 10 * (t / d - 1)) + b; + }, + easeOutExpo: function (x, t, b, c, d) { + return (t == d) ? b + c : c * (-_easingsMath.w(2, -10 * t / d) + 1) + b; + }, + easeInOutExpo: function (x, t, b, c, d) { + if (t == 0) return b; + if (t == d) return b + c; + if ((t /= d / 2) < 1) return c / 2 * _easingsMath.w(2, 10 * (t - 1)) + b; + return c / 2 * (-_easingsMath.w(2, -10 * --t) + 2) + b; + }, + easeInCirc: function (x, t, b, c, d) { + return -c * (_easingsMath.t(1 - (t /= d) * t) - 1) + b; + }, + easeOutCirc: function (x, t, b, c, d) { + return c * _easingsMath.t(1 - (t = t / d - 1) * t) + b; + }, + easeInOutCirc: function (x, t, b, c, d) { + return ((t /= d / 2) < 1) ? -c / 2 * (_easingsMath.t(1 - t * t) - 1) + b : c / 2 * (_easingsMath.t(1 - (t -= 2) * t) + 1) + b; + }, + easeInElastic: function (x, t, b, c, d) { + var s = _easingsMath.o; var p = 0; var a = c; + if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; + if (a < _easingsMath.a(c)) { a = c; s = p / 4; } + else s = p / (2 * _easingsMath.p) * _easingsMath.n(c / a); + return -(a * _easingsMath.w(2, 10 * (t -= 1)) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p)) + b; + }, + easeOutElastic: function (x, t, b, c, d) { + var s = _easingsMath.o; var p = 0; var a = c; + if (t == 0) return b; + if ((t /= d) == 1) return b + c; + if (!p) p = d * .3; + if (a < _easingsMath.a(c)) { a = c; s = p / 4; } + else s = p / (2 * _easingsMath.p) * _easingsMath.n(c / a); + return a * _easingsMath.w(2, -10 * t) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p) + c + b; + }, + easeInOutElastic: function (x, t, b, c, d) { + var s = _easingsMath.o; var p = 0; var a = c; + if (t == 0) return b; + if ((t /= d / 2) == 2) return b + c; + if (!p) p = d * (.3 * 1.5); + if (a < _easingsMath.a(c)) { a = c; s = p / 4; } + else s = p / (2 * _easingsMath.p) * _easingsMath.n(c / a); + if (t < 1) return -.5 * (a * _easingsMath.w(2, 10 * (t -= 1)) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p)) + b; + return a * _easingsMath.w(2, -10 * (t -= 1)) * _easingsMath.s((t * d - s) * (2 * _easingsMath.p) / p) * .5 + c + b; + }, + easeInBack: function (x, t, b, c, d, s) { + s = s || _easingsMath.o; + return c * (t /= d) * t * ((s + 1) * t - s) + b; + }, + easeOutBack: function (x, t, b, c, d, s) { + s = s || _easingsMath.o; + return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; + }, + easeInOutBack: function (x, t, b, c, d, s) { + s = s || _easingsMath.o; + return ((t /= d / 2) < 1) ? c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b : c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; + }, + easeInBounce: function (x, t, b, c, d) { + return c - this.easeOutBounce(x, d - t, 0, c, d) + b; + }, + easeOutBounce: function (x, t, b, c, d) { + var o = 7.5625; + if ((t /= d) < (1 / 2.75)) { + return c * (o * t * t) + b; + } else if (t < (2 / 2.75)) { + return c * (o * (t -= (1.5 / 2.75)) * t + .75) + b; + } else if (t < (2.5 / 2.75)) { + return c * (o * (t -= (2.25 / 2.75)) * t + .9375) + b; + } else { + return c * (o * (t -= (2.625 / 2.75)) * t + .984375) + b; + } + }, + easeInOutBounce: function (x, t, b, c, d) { + return (t < d / 2) ? this.easeInBounce(x, t * 2, 0, c, d) * .5 + b : this.easeOutBounce(x, t * 2 - d, 0, c, d) * .5 + c * .5 + b; + } + }; + /* + * + * TERMS OF USE - EASING EQUATIONS + * + * Open source under the BSD License. + * + * Copyright © 2001 Robert Penner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + })(); + var FRAMEWORK = (function () { + var _rnothtmlwhite = (/[^\x20\t\r\n\f]+/g); + var _strSpace = ' '; + var _strEmpty = ''; + var _strScrollLeft = 'scrollLeft'; + var _strScrollTop = 'scrollTop'; + var _animations = []; + var _type = COMPATIBILITY.type; + var _cssNumber = { + animationIterationCount: true, + columnCount: true, + fillOpacity: true, + flexGrow: true, + flexShrink: true, + fontWeight: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + widows: true, + zIndex: true, + zoom: true + }; + + function extend() { + var src, copyIsArray, copy, name, options, clone, target = arguments[0] || {}, + i = 1, + length = arguments[LEXICON.l], + deep = false; + + // Handle a deep copy situation + if (_type(target) == TYPES.b) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if (_type(target) != TYPES.o && !_type(target) == TYPES.f) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if (length === i) { + target = FakejQuery; + --i; + } + + for (; i < length; i++) { + // Only deal with non-null/undefined values + if ((options = arguments[i]) != null) { + // Extend the base object + for (name in options) { + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target === copy) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || (copyIsArray = COMPATIBILITY.isA(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && COMPATIBILITY.isA(src) ? src : []; + + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[name] = extend(deep, clone, copy); + + // Don't bring in undefined values + } else if (copy !== undefined) { + target[name] = copy; + } + } + } + } + + // Return the modified object + return target; + }; + + function inArray(item, arr, fromIndex) { + for (var i = fromIndex || 0; i < arr[LEXICON.l]; i++) + if (arr[i] === item) + return i; + return -1; + } + + function isFunction(obj) { + return _type(obj) == TYPES.f; + }; + + function isEmptyObject(obj) { + for (var name in obj) + return false; + return true; + }; + + function isPlainObject(obj) { + if (!obj || _type(obj) != TYPES.o) + return false; + + var key; + var proto = LEXICON.p; + var hasOwnProperty = Object[proto].hasOwnProperty; + var hasOwnConstructor = hasOwnProperty.call(obj, 'constructor'); + var hasIsPrototypeOf = obj.constructor && obj.constructor[proto] && hasOwnProperty.call(obj.constructor[proto], 'isPrototypeOf'); + + if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { + return false; + } + + + for (key in obj) { /**/ } + + return _type(key) == TYPES.u || hasOwnProperty.call(obj, key); + }; + + function each(obj, callback) { + var i = 0; + + if (isArrayLike(obj)) { + for (; i < obj[LEXICON.l]; i++) { + if (callback.call(obj[i], i, obj[i]) === false) + break; + } + } + else { + for (i in obj) { + if (callback.call(obj[i], i, obj[i]) === false) + break; + } + } + + return obj; + }; + + function isArrayLike(obj) { + var length = !!obj && [LEXICON.l] in obj && obj[LEXICON.l]; + var t = _type(obj); + return isFunction(t) ? false : (t == TYPES.a || length === 0 || _type(length) == TYPES.n && length > 0 && (length - 1) in obj); + } + + function stripAndCollapse(value) { + var tokens = value.match(_rnothtmlwhite) || []; + return tokens.join(_strSpace); + } + + function matches(elem, selector) { + var nodeList = (elem.parentNode || document).querySelectorAll(selector) || []; + var i = nodeList[LEXICON.l]; + + while (i--) + if (nodeList[i] == elem) + return true; + + return false; + } + + function insertAdjacentElement(el, strategy, child) { + if (_type(child) == TYPES.a) { + for (var i = 0; i < child[LEXICON.l]; i++) + insertAdjacentElement(el, strategy, child[i]); + } + else if (_type(child) == TYPES.s) + el.insertAdjacentHTML(strategy, child); + else + el.insertAdjacentElement(strategy, child.nodeType ? child : child[0]); + } + + function setCSSVal(el, prop, val) { + try { + if (el[LEXICON.s][prop] !== undefined) + el[LEXICON.s][prop] = parseCSSVal(prop, val); + } catch (e) { } + } + + function parseCSSVal(prop, val) { + if (!_cssNumber[prop.toLowerCase()] && _type(val) == TYPES.n) + val += 'px'; + return val; + } + + function startNextAnimationInQ(animObj, removeFromQ) { + var index; + var nextAnim; + if (removeFromQ !== false) + animObj.q.splice(0, 1); + if (animObj.q[LEXICON.l] > 0) { + nextAnim = animObj.q[0]; + animate(animObj.el, nextAnim.props, nextAnim.duration, nextAnim.easing, nextAnim.complete, true); + } + else { + index = inArray(animObj, _animations); + if (index > -1) + _animations.splice(index, 1); + } + } + + function setAnimationValue(el, prop, value) { + if (prop === _strScrollLeft || prop === _strScrollTop) + el[prop] = value; + else + setCSSVal(el, prop, value); + } + + function animate(el, props, options, easing, complete, guaranteedNext) { + var hasOptions = isPlainObject(options); + var from = {}; + var to = {}; + var i = 0; + var key; + var animObj; + var start; + var progress; + var step; + var specialEasing; + var duration; + if (hasOptions) { + easing = options.easing; + start = options.start; + progress = options.progress; + step = options.step; + specialEasing = options.specialEasing; + complete = options.complete; + duration = options.duration; + } + else + duration = options; + specialEasing = specialEasing || {}; + duration = duration || 400; + easing = easing || 'swing'; + guaranteedNext = guaranteedNext || false; + + for (; i < _animations[LEXICON.l]; i++) { + if (_animations[i].el === el) { + animObj = _animations[i]; + break; + } + } + + if (!animObj) { + animObj = { + el: el, + q: [] + }; + _animations.push(animObj); + } + + for (key in props) { + if (key === _strScrollLeft || key === _strScrollTop) + from[key] = el[key]; + else + from[key] = FakejQuery(el).css(key); + } + + for (key in from) { + if (from[key] !== props[key] && props[key] !== undefined) + to[key] = props[key]; + } + + if (!isEmptyObject(to)) { + var timeNow; + var end; + var percent; + var fromVal; + var toVal; + var easedVal; + var timeStart; + var frame; + var elapsed; + var qPos = guaranteedNext ? 0 : inArray(qObj, animObj.q); + var qObj = { + props: to, + duration: hasOptions ? options : duration, + easing: easing, + complete: complete + }; + if (qPos === -1) { + qPos = animObj.q[LEXICON.l]; + animObj.q.push(qObj); + } + + if (qPos === 0) { + if (duration > 0) { + timeStart = COMPATIBILITY.now(); + frame = function () { + timeNow = COMPATIBILITY.now(); + elapsed = (timeNow - timeStart); + end = qObj.stop || elapsed >= duration; + percent = 1 - ((MATH.max(0, timeStart + duration - timeNow) / duration) || 0); + + for (key in to) { + fromVal = parseFloat(from[key]); + toVal = parseFloat(to[key]); + easedVal = (toVal - fromVal) * EASING[specialEasing[key] || easing](percent, percent * duration, 0, 1, duration) + fromVal; + setAnimationValue(el, key, easedVal); + if (isFunction(step)) { + step(easedVal, { + elem: el, + prop: key, + start: fromVal, + now: easedVal, + end: toVal, + pos: percent, + options: { + easing: easing, + speacialEasing: specialEasing, + duration: duration, + complete: complete, + step: step + }, + startTime: timeStart + }); + } + } + + if (isFunction(progress)) + progress({}, percent, MATH.max(0, duration - elapsed)); + + if (end) { + startNextAnimationInQ(animObj); + if (isFunction(complete)) + complete(); + } + else + qObj.frame = COMPATIBILITY.rAF()(frame); + }; + qObj.frame = COMPATIBILITY.rAF()(frame); + } + else { + for (key in to) + setAnimationValue(el, key, to[key]); + startNextAnimationInQ(animObj); + } + } + } + else if (guaranteedNext) + startNextAnimationInQ(animObj); + } + + function stop(el, clearQ, jumpToEnd) { + var animObj; + var qObj; + var key; + var i = 0; + for (; i < _animations[LEXICON.l]; i++) { + animObj = _animations[i]; + if (animObj.el === el) { + if (animObj.q[LEXICON.l] > 0) { + qObj = animObj.q[0]; + qObj.stop = true; + COMPATIBILITY.cAF()(qObj.frame); + animObj.q.splice(0, 1); + + if (jumpToEnd) + for (key in qObj.props) + setAnimationValue(el, key, qObj.props[key]); + + if (clearQ) + animObj.q = []; + else + startNextAnimationInQ(animObj, false); + } + break; + } + } + } + + function elementIsVisible(el) { + return !!(el[LEXICON.oW] || el[LEXICON.oH] || el.getClientRects()[LEXICON.l]); + } + + function FakejQuery(selector) { + if (arguments[LEXICON.l] === 0) + return this; + + var base = new FakejQuery(); + var elements = selector; + var i = 0; + var elms; + var el; + + if (_type(selector) == TYPES.s) { + elements = []; + if (selector.charAt(0) === '<') { + el = document.createElement('div'); + el.innerHTML = selector; + elms = el.children; + } + else { + elms = document.querySelectorAll(selector); + } + + for (; i < elms[LEXICON.l]; i++) + elements.push(elms[i]); + } + + if (elements) { + if (_type(elements) != TYPES.s && (!isArrayLike(elements) || elements === window || elements === elements.self)) + elements = [elements]; + + for (i = 0; i < elements[LEXICON.l]; i++) + base[i] = elements[i]; + + base[LEXICON.l] = elements[LEXICON.l]; + } + + return base; + }; + + FakejQuery[LEXICON.p] = { + + //EVENTS: + + on: function (eventName, handler) { + eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [_strEmpty]; + + var eventNameLength = eventName[LEXICON.l]; + var i = 0; + var el; + return this.each(function () { + el = this; + try { + if (el.addEventListener) { + for (; i < eventNameLength; i++) + el.addEventListener(eventName[i], handler); + } + else if (el.detachEvent) { + for (; i < eventNameLength; i++) + el.attachEvent('on' + eventName[i], handler); + } + } catch (e) { } + }); + }, + + off: function (eventName, handler) { + eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [_strEmpty]; + + var eventNameLength = eventName[LEXICON.l]; + var i = 0; + var el; + return this.each(function () { + el = this; + try { + if (el.removeEventListener) { + for (; i < eventNameLength; i++) + el.removeEventListener(eventName[i], handler); + } + else if (el.detachEvent) { + for (; i < eventNameLength; i++) + el.detachEvent('on' + eventName[i], handler); + } + } catch (e) { } + }); + }, + + one: function (eventName, handler) { + eventName = (eventName || _strEmpty).match(_rnothtmlwhite) || [_strEmpty]; + return this.each(function () { + var el = FakejQuery(this); + FakejQuery.each(eventName, function (i, oneEventName) { + var oneHandler = function (e) { + handler.call(this, e); + el.off(oneEventName, oneHandler); + }; + el.on(oneEventName, oneHandler); + }); + }); + }, + + trigger: function (eventName) { + var el; + var event; + return this.each(function () { + el = this; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent(eventName, true, false); + el.dispatchEvent(event); + } + else { + el.fireEvent('on' + eventName); + } + }); + }, + + //DOM NODE INSERTING / REMOVING: + + append: function (child) { + return this.each(function () { insertAdjacentElement(this, 'beforeend', child); }); + }, + + prepend: function (child) { + return this.each(function () { insertAdjacentElement(this, 'afterbegin', child); }); + }, + + before: function (child) { + return this.each(function () { insertAdjacentElement(this, 'beforebegin', child); }); + }, + + after: function (child) { + return this.each(function () { insertAdjacentElement(this, 'afterend', child); }); + }, + + remove: function () { + return this.each(function () { + var el = this; + var parentNode = el.parentNode; + if (parentNode != null) + parentNode.removeChild(el); + }); + }, + + unwrap: function () { + var parents = []; + var i; + var el; + var parent; + + this.each(function () { + parent = this.parentNode; + if (inArray(parent, parents) === - 1) + parents.push(parent); + }); + + for (i = 0; i < parents[LEXICON.l]; i++) { + el = parents[i]; + parent = el.parentNode; + while (el.firstChild) + parent.insertBefore(el.firstChild, el); + parent.removeChild(el); + } + + return this; + }, + + wrapAll: function (wrapperHTML) { + var i; + var nodes = this; + var wrapper = FakejQuery(wrapperHTML)[0]; + var deepest = wrapper; + var parent = nodes[0].parentNode; + var previousSibling = nodes[0].previousSibling; + while (deepest.childNodes[LEXICON.l] > 0) + deepest = deepest.childNodes[0]; + + for (i = 0; nodes[LEXICON.l] - i; deepest.firstChild === nodes[0] && i++) + deepest.appendChild(nodes[i]); + + var nextSibling = previousSibling ? previousSibling.nextSibling : parent.firstChild; + parent.insertBefore(wrapper, nextSibling); + + return this; + }, + + wrapInner: function (wrapperHTML) { + return this.each(function () { + var el = FakejQuery(this); + var contents = el.contents(); + + if (contents[LEXICON.l]) + contents.wrapAll(wrapperHTML); + else + el.append(wrapperHTML); + }); + }, + + wrap: function (wrapperHTML) { + return this.each(function () { FakejQuery(this).wrapAll(wrapperHTML); }); + }, + + + //DOM NODE MANIPULATION / INFORMATION: + + css: function (styles, val) { + var el; + var key; + var cptStyle; + var getCptStyle = window.getComputedStyle; + if (_type(styles) == TYPES.s) { + if (val === undefined) { + el = this[0]; + cptStyle = getCptStyle ? getCptStyle(el, null) : el.currentStyle[styles]; + + //https://bugzilla.mozilla.org/show_bug.cgi?id=548397 can be null sometimes if iframe with display: none (firefox only!) + return getCptStyle ? cptStyle != null ? cptStyle.getPropertyValue(styles) : el[LEXICON.s][styles] : cptStyle; + } + else { + return this.each(function () { + setCSSVal(this, styles, val); + }); + } + } + else { + return this.each(function () { + for (key in styles) + setCSSVal(this, key, styles[key]); + }); + } + }, + + hasClass: function (className) { + var elem, i = 0; + var classNamePrepared = _strSpace + className + _strSpace; + var classList; + + while ((elem = this[i++])) { + classList = elem.classList; + if (classList && classList.contains(className)) + return true; + else if (elem.nodeType === 1 && (_strSpace + stripAndCollapse(elem.className + _strEmpty) + _strSpace).indexOf(classNamePrepared) > -1) + return true; + } + + return false; + }, + + addClass: function (className) { + var classes; + var elem; + var cur; + var curValue; + var clazz; + var finalValue; + var supportClassList; + var elmClassList; + var i = 0; + var v = 0; + + if (className) { + classes = className.match(_rnothtmlwhite) || []; + + while ((elem = this[i++])) { + elmClassList = elem.classList; + if (supportClassList === undefined) + supportClassList = elmClassList !== undefined; + + if (supportClassList) { + while ((clazz = classes[v++])) + elmClassList.add(clazz); + } + else { + curValue = elem.className + _strEmpty; + cur = elem.nodeType === 1 && (_strSpace + stripAndCollapse(curValue) + _strSpace); + + if (cur) { + while ((clazz = classes[v++])) + if (cur.indexOf(_strSpace + clazz + _strSpace) < 0) + cur += clazz + _strSpace; + + finalValue = stripAndCollapse(cur); + if (curValue !== finalValue) + elem.className = finalValue; + } + } + } + } + + return this; + }, + + removeClass: function (className) { + var classes; + var elem; + var cur; + var curValue; + var clazz; + var finalValue; + var supportClassList; + var elmClassList; + var i = 0; + var v = 0; + + if (className) { + classes = className.match(_rnothtmlwhite) || []; + + while ((elem = this[i++])) { + elmClassList = elem.classList; + if (supportClassList === undefined) + supportClassList = elmClassList !== undefined; + + if (supportClassList) { + while ((clazz = classes[v++])) + elmClassList.remove(clazz); + } + else { + curValue = elem.className + _strEmpty; + cur = elem.nodeType === 1 && (_strSpace + stripAndCollapse(curValue) + _strSpace); + + if (cur) { + while ((clazz = classes[v++])) + while (cur.indexOf(_strSpace + clazz + _strSpace) > -1) + cur = cur.replace(_strSpace + clazz + _strSpace, _strSpace); + + finalValue = stripAndCollapse(cur); + if (curValue !== finalValue) + elem.className = finalValue; + } + } + } + } + + return this; + }, + + hide: function () { + return this.each(function () { this[LEXICON.s].display = 'none'; }); + }, + + show: function () { + return this.each(function () { this[LEXICON.s].display = 'block'; }); + }, + + attr: function (attrName, value) { + var i = 0; + var el; + while (el = this[i++]) { + if (value === undefined) + return el.getAttribute(attrName); + el.setAttribute(attrName, value); + } + return this; + }, + + removeAttr: function (attrName) { + return this.each(function () { this.removeAttribute(attrName); }); + }, + + offset: function () { + var el = this[0]; + var rect = el[LEXICON.bCR](); + var scrollLeft = window.pageXOffset || document.documentElement[_strScrollLeft]; + var scrollTop = window.pageYOffset || document.documentElement[_strScrollTop]; + return { + top: rect.top + scrollTop, + left: rect.left + scrollLeft + }; + }, + + position: function () { + var el = this[0]; + return { + top: el.offsetTop, + left: el.offsetLeft + }; + }, + + scrollLeft: function (value) { + var i = 0; + var el; + while (el = this[i++]) { + if (value === undefined) + return el[_strScrollLeft]; + el[_strScrollLeft] = value; + } + return this; + }, + + scrollTop: function (value) { + var i = 0; + var el; + while (el = this[i++]) { + if (value === undefined) + return el[_strScrollTop]; + el[_strScrollTop] = value; + } + return this; + }, + + val: function (value) { + var el = this[0]; + if (!value) + return el.value; + el.value = value; + return this; + }, + + + //DOM TRAVERSAL / FILTERING: + + first: function () { + return this.eq(0); + }, + + last: function () { + return this.eq(-1); + }, + + eq: function (index) { + return FakejQuery(this[index >= 0 ? index : this[LEXICON.l] + index]); + }, + + find: function (selector) { + var children = []; + var i; + this.each(function () { + var el = this; + var ch = el.querySelectorAll(selector); + for (i = 0; i < ch[LEXICON.l]; i++) + children.push(ch[i]); + }); + return FakejQuery(children); + }, + + children: function (selector) { + var children = []; + var el; + var ch; + var i; + + this.each(function () { + ch = this.children; + for (i = 0; i < ch[LEXICON.l]; i++) { + el = ch[i]; + if (selector) { + if ((el.matches && el.matches(selector)) || matches(el, selector)) + children.push(el); + } + else + children.push(el); + } + }); + return FakejQuery(children); + }, + + parent: function (selector) { + var parents = []; + var parent; + this.each(function () { + parent = this.parentNode; + if (selector ? FakejQuery(parent).is(selector) : true) + parents.push(parent); + }); + return FakejQuery(parents); + }, + + is: function (selector) { + + var el; + var i; + for (i = 0; i < this[LEXICON.l]; i++) { + el = this[i]; + if (selector === ':visible') + return elementIsVisible(el); + if (selector === ':hidden') + return !elementIsVisible(el); + if ((el.matches && el.matches(selector)) || matches(el, selector)) + return true; + } + return false; + }, + + contents: function () { + var contents = []; + var childs; + var i; + + this.each(function () { + childs = this.childNodes; + for (i = 0; i < childs[LEXICON.l]; i++) + contents.push(childs[i]); + }); + + return FakejQuery(contents); + }, + + each: function (callback) { + return each(this, callback); + }, + + + //ANIMATION: + + animate: function (props, duration, easing, complete) { + return this.each(function () { animate(this, props, duration, easing, complete); }); + }, + + stop: function (clearQ, jump) { + return this.each(function () { stop(this, clearQ, jump); }); + } + }; + + extend(FakejQuery, { + extend: extend, + inArray: inArray, + isEmptyObject: isEmptyObject, + isPlainObject: isPlainObject, + each: each + }); + + return FakejQuery; + })(); + var INSTANCES = (function () { + var _targets = []; + var _instancePropertyString = '__overlayScrollbars__'; + + /** + * Register, unregister or get a certain (or all) instances. + * Register: Pass the target and the instance. + * Unregister: Pass the target and null. + * Get Instance: Pass the target from which the instance shall be got. + * Get Targets: Pass no arguments. + * @param target The target to which the instance shall be registered / from which the instance shall be unregistered / the instance shall be got + * @param instance The instance. + * @returns {*|void} Returns the instance from the given target. + */ + return function (target, instance) { + var argLen = arguments[LEXICON.l]; + if (argLen < 1) { + //return all targets + return _targets; + } + else { + if (instance) { + //register instance + target[_instancePropertyString] = instance; + _targets.push(target); + } + else { + var index = COMPATIBILITY.inA(target, _targets); + if (index > -1) { + if (argLen > 1) { + //unregister instance + delete target[_instancePropertyString]; + _targets.splice(index, 1); + } + else { + //get instance from target + return _targets[index][_instancePropertyString]; + } + } + } + } + } + })(); + var PLUGIN = (function () { + var _plugin; + var _pluginsGlobals; + var _pluginsAutoUpdateLoop; + var _pluginsExtensions = []; + var _pluginsOptions = (function () { + var type = COMPATIBILITY.type; + var possibleTemplateTypes = [ + TYPES.b, //boolean + TYPES.n, //number + TYPES.s, //string + TYPES.a, //array + TYPES.o, //object + TYPES.f, //function + TYPES.z //null + ]; + var restrictedStringsSplit = ' '; + var restrictedStringsPossibilitiesSplit = ':'; + var classNameAllowedValues = [TYPES.z, TYPES.s]; + var numberAllowedValues = TYPES.n; + var booleanNullAllowedValues = [TYPES.z, TYPES.b]; + var booleanTrueTemplate = [true, TYPES.b]; + var booleanFalseTemplate = [false, TYPES.b]; + var callbackTemplate = [null, [TYPES.z, TYPES.f]]; + var inheritedAttrsTemplate = [['style', 'class'], [TYPES.s, TYPES.a, TYPES.z]]; + var resizeAllowedValues = 'n:none b:both h:horizontal v:vertical'; + var overflowBehaviorAllowedValues = 'v-h:visible-hidden v-s:visible-scroll s:scroll h:hidden'; + var scrollbarsVisibilityAllowedValues = 'v:visible h:hidden a:auto'; + var scrollbarsAutoHideAllowedValues = 'n:never s:scroll l:leave m:move'; + var optionsDefaultsAndTemplate = { + className: ['os-theme-dark', classNameAllowedValues], //null || string + resize: ['none', resizeAllowedValues], //none || both || horizontal || vertical || n || b || h || v + sizeAutoCapable: booleanTrueTemplate, //true || false + clipAlways: booleanTrueTemplate, //true || false + normalizeRTL: booleanTrueTemplate, //true || false + paddingAbsolute: booleanFalseTemplate, //true || false + autoUpdate: [null, booleanNullAllowedValues], //true || false || null + autoUpdateInterval: [33, numberAllowedValues], //number + nativeScrollbarsOverlaid: { + showNativeScrollbars: booleanFalseTemplate, //true || false + initialize: booleanTrueTemplate //true || false + }, + overflowBehavior: { + x: ['scroll', overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s + y: ['scroll', overflowBehaviorAllowedValues] //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s + }, + scrollbars: { + visibility: ['auto', scrollbarsVisibilityAllowedValues], //visible || hidden || auto || v || h || a + autoHide: ['never', scrollbarsAutoHideAllowedValues], //never || scroll || leave || move || n || s || l || m + autoHideDelay: [800, numberAllowedValues], //number + dragScrolling: booleanTrueTemplate, //true || false + clickScrolling: booleanFalseTemplate, //true || false + touchSupport: booleanTrueTemplate, //true || false + snapHandle: booleanFalseTemplate //true || false + }, + textarea: { + dynWidth: booleanFalseTemplate, //true || false + dynHeight: booleanFalseTemplate, //true || false + inheritedAttrs: inheritedAttrsTemplate //string || array || null + }, + callbacks: { + onInitialized: callbackTemplate, //null || function + onInitializationWithdrawn: callbackTemplate, //null || function + onDestroyed: callbackTemplate, //null || function + onScrollStart: callbackTemplate, //null || function + onScroll: callbackTemplate, //null || function + onScrollStop: callbackTemplate, //null || function + onOverflowChanged: callbackTemplate, //null || function + onOverflowAmountChanged: callbackTemplate, //null || function + onDirectionChanged: callbackTemplate, //null || function + onContentSizeChanged: callbackTemplate, //null || function + onHostSizeChanged: callbackTemplate, //null || function + onUpdated: callbackTemplate //null || function + } + }; + var convert = function (template) { + var recursive = function (obj) { + var key; + var val; + var valType; + for (key in obj) { + if (!obj[LEXICON.hOP](key)) + continue; + val = obj[key]; + valType = type(val); + if (valType == TYPES.a) + obj[key] = val[template ? 1 : 0]; + else if (valType == TYPES.o) + obj[key] = recursive(val); + } + return obj; + }; + return recursive(FRAMEWORK.extend(true, {}, optionsDefaultsAndTemplate)); + }; + + return { + _defaults: convert(), + + _template: convert(true), + + /** + * Validates the passed object by the passed template. + * @param obj The object which shall be validated. + * @param template The template which defines the allowed values and types. + * @param writeErrors True if errors shall be logged to the console. + * @param diffObj If a object is passed then only valid differences to this object will be returned. + * @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. + */ + _validate: function (obj, template, writeErrors, diffObj) { + var validatedOptions = {}; + var validatedOptionsPrepared = {}; + var objectCopy = FRAMEWORK.extend(true, {}, obj); + var inArray = FRAMEWORK.inArray; + var isEmptyObj = FRAMEWORK.isEmptyObject; + var checkObjectProps = function (data, template, diffData, validatedOptions, validatedOptionsPrepared, prevPropName) { + for (var prop in template) { + if (template[LEXICON.hOP](prop) && data[LEXICON.hOP](prop)) { + var isValid = false; + var isDiff = false; + var templateValue = template[prop]; + var templateValueType = type(templateValue); + var templateIsComplex = templateValueType == TYPES.o; + var templateTypes = type(templateValue) != TYPES.a ? [templateValue] : templateValue; + var dataDiffValue = diffData[prop]; + var dataValue = data[prop]; + var dataValueType = type(dataValue); + var propPrefix = prevPropName ? prevPropName + '.' : ''; + var error = "The option \"" + propPrefix + prop + "\" wasn't set, because"; + var errorPossibleTypes = []; + var errorRestrictedStrings = []; + var restrictedStringValuesSplit; + var restrictedStringValuesPossibilitiesSplit; + var isRestrictedValue; + var mainPossibility; + var currType; + var i; + var v; + var j; + + dataDiffValue = dataDiffValue === undefined ? {} : dataDiffValue; + + //if the template has a object as value, it means that the options are complex (verschachtelt) + if (templateIsComplex && dataValueType == TYPES.o) { + validatedOptions[prop] = {}; + validatedOptionsPrepared[prop] = {}; + checkObjectProps(dataValue, templateValue, dataDiffValue, validatedOptions[prop], validatedOptionsPrepared[prop], propPrefix + prop); + FRAMEWORK.each([data, validatedOptions, validatedOptionsPrepared], function (index, value) { + if (isEmptyObj(value[prop])) { + delete value[prop]; + } + }); + } + else if (!templateIsComplex) { + for (i = 0; i < templateTypes[LEXICON.l]; i++) { + currType = templateTypes[i]; + templateValueType = type(currType); + //if currtype is string and starts with restrictedStringPrefix and end with restrictedStringSuffix + isRestrictedValue = templateValueType == TYPES.s && inArray(currType, possibleTemplateTypes) === -1; + if (isRestrictedValue) { + errorPossibleTypes.push(TYPES.s); + + //split it into a array which contains all possible values for example: ["y:yes", "n:no", "m:maybe"] + restrictedStringValuesSplit = currType.split(restrictedStringsSplit); + errorRestrictedStrings = errorRestrictedStrings.concat(restrictedStringValuesSplit); + for (v = 0; v < restrictedStringValuesSplit[LEXICON.l]; v++) { + //split the possible values into their possibiliteis for example: ["y", "yes"] -> the first is always the mainPossibility + restrictedStringValuesPossibilitiesSplit = restrictedStringValuesSplit[v].split(restrictedStringsPossibilitiesSplit); + mainPossibility = restrictedStringValuesPossibilitiesSplit[0]; + for (j = 0; j < restrictedStringValuesPossibilitiesSplit[LEXICON.l]; j++) { + //if any possibility matches with the dataValue, its valid + if (dataValue === restrictedStringValuesPossibilitiesSplit[j]) { + isValid = true; + break; + } + } + if (isValid) + break; + } + } + else { + errorPossibleTypes.push(currType); + + if (dataValueType === currType) { + isValid = true; + break; + } + } + } + + if (isValid) { + isDiff = dataValue !== dataDiffValue; + + if (isDiff) + validatedOptions[prop] = dataValue; + + if (isRestrictedValue ? inArray(dataDiffValue, restrictedStringValuesPossibilitiesSplit) < 0 : isDiff) + validatedOptionsPrepared[prop] = isRestrictedValue ? mainPossibility : dataValue; + } + else if (writeErrors) { + console.warn(error + " it doesn't accept the type [ " + dataValueType.toUpperCase() + " ] with the value of \"" + dataValue + "\".\r\n" + + "Accepted types are: [ " + errorPossibleTypes.join(', ').toUpperCase() + " ]." + + (errorRestrictedStrings[length] > 0 ? "\r\nValid strings are: [ " + errorRestrictedStrings.join(', ').split(restrictedStringsPossibilitiesSplit).join(', ') + " ]." : '')); + } + delete data[prop]; + } + } + } + }; + checkObjectProps(objectCopy, template, diffObj || {}, validatedOptions, validatedOptionsPrepared); + + //add values which aren't specified in the template to the finished validated object to prevent them from being discarded + /* + if(keepForeignProps) { + FRAMEWORK.extend(true, validatedOptions, objectCopy); + FRAMEWORK.extend(true, validatedOptionsPrepared, objectCopy); + } + */ + + if (!isEmptyObj(objectCopy) && writeErrors) + console.warn('The following options are discarded due to invalidity:\r\n' + window.JSON.stringify(objectCopy, null, 2)); + + return { + _default: validatedOptions, + _prepared: validatedOptionsPrepared + }; + } + } + }()); + + /** + * Initializes the object which contains global information about the plugin and each instance of it. + */ + function initOverlayScrollbarsStatics() { + if (!_pluginsGlobals) + _pluginsGlobals = new OverlayScrollbarsGlobals(_pluginsOptions._defaults); + if (!_pluginsAutoUpdateLoop) + _pluginsAutoUpdateLoop = new OverlayScrollbarsAutoUpdateLoop(_pluginsGlobals); + } + + /** + * 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. + * @param defaultOptions + * @constructor + */ + function OverlayScrollbarsGlobals(defaultOptions) { + var _base = this; + var strOverflow = 'overflow'; + var strHidden = 'hidden'; + var strScroll = 'scroll'; + var bodyElement = FRAMEWORK('body'); + var scrollbarDummyElement = FRAMEWORK('
'); + var scrollbarDummyElement0 = scrollbarDummyElement[0]; + var dummyContainerChild = FRAMEWORK(scrollbarDummyElement.children('div').eq(0)); + + bodyElement.append(scrollbarDummyElement); + scrollbarDummyElement.hide().show(); //fix IE8 bug (incorrect measuring) + + var nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement0); + var nativeScrollbarIsOverlaid = { + x: nativeScrollbarSize.x === 0, + y: nativeScrollbarSize.y === 0 + }; + var msie = (function () { + var ua = window.navigator.userAgent; + var strIndexOf = 'indexOf'; + var strSubString = 'substring'; + var msie = ua[strIndexOf]('MSIE '); + var trident = ua[strIndexOf]('Trident/'); + var edge = ua[strIndexOf]('Edge/'); + var rv = ua[strIndexOf]('rv:'); + var result; + var parseIntFunc = parseInt; + + // IE 10 or older => return version number + if (msie > 0) + result = parseIntFunc(ua[strSubString](msie + 5, ua[strIndexOf]('.', msie)), 10); + + // IE 11 => return version number + else if (trident > 0) + result = parseIntFunc(ua[strSubString](rv + 3, ua[strIndexOf]('.', rv)), 10); + + // Edge (IE 12+) => return version number + else if (edge > 0) + result = parseIntFunc(ua[strSubString](edge + 5, ua[strIndexOf]('.', edge)), 10); + + // other browser + return result; + })(); + + FRAMEWORK.extend(_base, { + defaultOptions: defaultOptions, + msie: msie, + autoUpdateLoop: false, + autoUpdateRecommended: !COMPATIBILITY.mO(), + nativeScrollbarSize: nativeScrollbarSize, + nativeScrollbarIsOverlaid: nativeScrollbarIsOverlaid, + nativeScrollbarStyling: (function () { + var result = false; + scrollbarDummyElement.addClass('os-viewport-native-scrollbars-invisible'); + try { + result = (scrollbarDummyElement.css('scrollbar-width') === 'none' && (msie > 9 || !msie)) || window.getComputedStyle(scrollbarDummyElement0, '::-webkit-scrollbar').getPropertyValue('display') === 'none'; + } catch (ex) { } + + //fix opera bug: scrollbar styles will only appear if overflow value is scroll or auto during the activation of the style. + //and set overflow to scroll + //scrollbarDummyElement.css(strOverflow, strHidden).hide().css(strOverflow, strScroll).show(); + //return (scrollbarDummyElement0[LEXICON.oH] - scrollbarDummyElement0[LEXICON.cH]) === 0 && (scrollbarDummyElement0[LEXICON.oW] - scrollbarDummyElement0[LEXICON.cW]) === 0; + + return result; + })(), + overlayScrollbarDummySize: { x: 30, y: 30 }, + cssCalc: (function () { + var dummyStyle = document.createElement('div')[LEXICON.s]; + var strCalc = 'calc'; + var i = -1; + var prop; + + for (; i < VENDORS._cssPrefixes[LEXICON.l]; i++) { + prop = i < 0 ? strCalc : VENDORS._cssPrefixes[i] + strCalc; + dummyStyle.cssText = 'width:' + prop + '(1px);'; + if (dummyStyle[LEXICON.l]) + return prop; + } + return null; + })(), + restrictedMeasuring: (function () { + //https://bugzilla.mozilla.org/show_bug.cgi?id=1439305 + //since 1.11.0 always false -> fixed via CSS (hopefully) + scrollbarDummyElement.css(strOverflow, strHidden); + var scrollSize = { + w: scrollbarDummyElement0[LEXICON.sW], + h: scrollbarDummyElement0[LEXICON.sH] + }; + scrollbarDummyElement.css(strOverflow, 'visible'); + var scrollSize2 = { + w: scrollbarDummyElement0[LEXICON.sW], + h: scrollbarDummyElement0[LEXICON.sH] + }; + return (scrollSize.w - scrollSize2.w) !== 0 || (scrollSize.h - scrollSize2.h) !== 0; + })(), + rtlScrollBehavior: (function () { + scrollbarDummyElement.css({ 'overflow-y': strHidden, 'overflow-x': strScroll, 'direction': 'rtl' }).scrollLeft(0); + var dummyContainerOffset = scrollbarDummyElement.offset(); + var dummyContainerChildOffset = dummyContainerChild.offset(); + //https://github.com/KingSora/OverlayScrollbars/issues/187 + scrollbarDummyElement.scrollLeft(-999); + var dummyContainerChildOffsetAfterScroll = dummyContainerChild.offset(); + return { + //origin direction = determines if the zero scroll position is on the left or right side + //'i' means 'invert' (i === true means that the axis must be inverted to be correct) + //true = on the left side + //false = on the right side + i: dummyContainerOffset.left === dummyContainerChildOffset.left, + //negative = determines if the maximum scroll is positive or negative + //'n' means 'negate' (n === true means that the axis must be negated to be correct) + //true = negative + //false = positive + n: dummyContainerChildOffset.left !== dummyContainerChildOffsetAfterScroll.left + }; + })(), + supportTransform: VENDORS._cssProperty('transform') !== undefined, + supportTransition: VENDORS._cssProperty('transition') !== undefined, + supportPassiveEvents: (function () { + var supportsPassive = false; + try { + window.addEventListener('test', null, Object.defineProperty({}, 'passive', { + get: function () { + supportsPassive = true; + } + })); + } catch (e) { } + return supportsPassive; + })(), + supportResizeObserver: !!COMPATIBILITY.rO(), + supportMutationObserver: !!COMPATIBILITY.mO() + }); + + scrollbarDummyElement.removeAttr(LEXICON.s).remove(); + + //Catch zoom event: + (function () { + if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) + return; + + var abs = MATH.abs; + var windowWidth = COMPATIBILITY.wW(); + var windowHeight = COMPATIBILITY.wH(); + var windowDpr = getWindowDPR(); + var onResize = function () { + if (INSTANCES().length > 0) { + var newW = COMPATIBILITY.wW(); + var newH = COMPATIBILITY.wH(); + var deltaW = newW - windowWidth; + var deltaH = newH - windowHeight; + + if (deltaW === 0 && deltaH === 0) + return; + + var deltaWRatio = MATH.round(newW / (windowWidth / 100.0)); + var deltaHRatio = MATH.round(newH / (windowHeight / 100.0)); + var absDeltaW = abs(deltaW); + var absDeltaH = abs(deltaH); + var absDeltaWRatio = abs(deltaWRatio); + var absDeltaHRatio = abs(deltaHRatio); + var newDPR = getWindowDPR(); + + var deltaIsBigger = absDeltaW > 2 && absDeltaH > 2; + var difference = !differenceIsBiggerThanOne(absDeltaWRatio, absDeltaHRatio); + var dprChanged = newDPR !== windowDpr && windowDpr > 0; + var isZoom = deltaIsBigger && difference && dprChanged; + var oldScrollbarSize = _base.nativeScrollbarSize; + var newScrollbarSize; + + if (isZoom) { + bodyElement.append(scrollbarDummyElement); + newScrollbarSize = _base.nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement[0]); + scrollbarDummyElement.remove(); + if (oldScrollbarSize.x !== newScrollbarSize.x || oldScrollbarSize.y !== newScrollbarSize.y) { + FRAMEWORK.each(INSTANCES(), function () { + if (INSTANCES(this)) + INSTANCES(this).update('zoom'); + }); + } + } + + windowWidth = newW; + windowHeight = newH; + windowDpr = newDPR; + } + }; + + function differenceIsBiggerThanOne(valOne, valTwo) { + var absValOne = abs(valOne); + var absValTwo = abs(valTwo); + return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo); + } + + function getWindowDPR() { + var dDPI = window.screen.deviceXDPI || 0; + var sDPI = window.screen.logicalXDPI || 1; + return window.devicePixelRatio || (dDPI / sDPI); + } + + FRAMEWORK(window).on('resize', onResize); + })(); + + function calcNativeScrollbarSize(measureElement) { + return { + x: measureElement[LEXICON.oH] - measureElement[LEXICON.cH], + y: measureElement[LEXICON.oW] - measureElement[LEXICON.cW] + }; + } + } + + /** + * 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. + * @constructor + */ + function OverlayScrollbarsAutoUpdateLoop(globals) { + var _base = this; + var _inArray = FRAMEWORK.inArray; + var _getNow = COMPATIBILITY.now; + var _strAutoUpdate = 'autoUpdate'; + var _strAutoUpdateInterval = _strAutoUpdate + 'Interval'; + var _strLength = LEXICON.l; + var _loopingInstances = []; + var _loopingInstancesIntervalCache = []; + var _loopIsActive = false; + var _loopIntervalDefault = 33; + var _loopInterval = _loopIntervalDefault; + var _loopTimeOld = _getNow(); + var _loopID; + + + /** + * The auto update loop which will run every 50 milliseconds or less if the update interval of a instance is lower than 50 milliseconds. + */ + var loop = function () { + if (_loopingInstances[_strLength] > 0 && _loopIsActive) { + _loopID = COMPATIBILITY.rAF()(function () { + loop(); + }); + var timeNew = _getNow(); + var timeDelta = timeNew - _loopTimeOld; + var lowestInterval; + var instance; + var instanceOptions; + var instanceAutoUpdateAllowed; + var instanceAutoUpdateInterval; + var now; + + if (timeDelta > _loopInterval) { + _loopTimeOld = timeNew - (timeDelta % _loopInterval); + lowestInterval = _loopIntervalDefault; + for (var i = 0; i < _loopingInstances[_strLength]; i++) { + instance = _loopingInstances[i]; + if (instance !== undefined) { + instanceOptions = instance.options(); + instanceAutoUpdateAllowed = instanceOptions[_strAutoUpdate]; + instanceAutoUpdateInterval = MATH.max(1, instanceOptions[_strAutoUpdateInterval]); + now = _getNow(); + + if ((instanceAutoUpdateAllowed === true || instanceAutoUpdateAllowed === null) && (now - _loopingInstancesIntervalCache[i]) > instanceAutoUpdateInterval) { + instance.update('auto'); + _loopingInstancesIntervalCache[i] = new Date(now += instanceAutoUpdateInterval); + } + + lowestInterval = MATH.max(1, MATH.min(lowestInterval, instanceAutoUpdateInterval)); + } + } + _loopInterval = lowestInterval; + } + } else { + _loopInterval = _loopIntervalDefault; + } + }; + + /** + * Add OverlayScrollbars instance to the auto update loop. Only successful if the instance isn't already added. + * @param instance The instance which shall be updated in a loop automatically. + */ + _base.add = function (instance) { + if (_inArray(instance, _loopingInstances) === -1) { + _loopingInstances.push(instance); + _loopingInstancesIntervalCache.push(_getNow()); + if (_loopingInstances[_strLength] > 0 && !_loopIsActive) { + _loopIsActive = true; + globals.autoUpdateLoop = _loopIsActive; + loop(); + } + } + }; + + /** + * Remove OverlayScrollbars instance from the auto update loop. Only successful if the instance was added before. + * @param instance The instance which shall be updated in a loop automatically. + */ + _base.remove = function (instance) { + var index = _inArray(instance, _loopingInstances); + if (index > -1) { + //remove from loopingInstances list + _loopingInstancesIntervalCache.splice(index, 1); + _loopingInstances.splice(index, 1); + + //correct update loop behavior + if (_loopingInstances[_strLength] === 0 && _loopIsActive) { + _loopIsActive = false; + globals.autoUpdateLoop = _loopIsActive; + if (_loopID !== undefined) { + COMPATIBILITY.cAF()(_loopID); + _loopID = -1; + } + } + } + }; + } + + /** + * A object which manages the scrollbars visibility of the target element. + * @param pluginTargetElement The element from which the scrollbars shall be hidden. + * @param options The custom options. + * @param extensions The custom extensions. + * @param globals + * @param autoUpdateLoop + * @returns {*} + * @constructor + */ + function OverlayScrollbarsInstance(pluginTargetElement, options, extensions, globals, autoUpdateLoop) { + //shortcuts + var type = COMPATIBILITY.type; + var inArray = FRAMEWORK.inArray; + var each = FRAMEWORK.each; + + //make correct instanceof + var _base = new _plugin(); + var _frameworkProto = FRAMEWORK[LEXICON.p]; + + //if passed element is no HTML element: skip and return + if (!isHTMLElement(pluginTargetElement)) + return; + + //if passed element is already initialized: set passed options if there are any and return its instance + if (INSTANCES(pluginTargetElement)) { + var inst = INSTANCES(pluginTargetElement); + inst.options(options); + return inst; + } + + //globals: + var _nativeScrollbarIsOverlaid; + var _overlayScrollbarDummySize; + var _rtlScrollBehavior; + var _autoUpdateRecommended; + var _msieVersion; + var _nativeScrollbarStyling; + var _cssCalc; + var _nativeScrollbarSize; + var _supportTransition; + var _supportTransform; + var _supportPassiveEvents; + var _supportResizeObserver; + var _supportMutationObserver; + var _restrictedMeasuring; + + //general readonly: + var _initialized; + var _destroyed; + var _isTextarea; + var _isBody; + var _documentMixed; + var _domExists; + + //general: + var _isBorderBox; + var _sizeAutoObserverAdded; + var _paddingX; + var _paddingY; + var _borderX; + var _borderY; + var _marginX; + var _marginY; + var _isRTL; + var _sleeping; + var _contentBorderSize = {}; + var _scrollHorizontalInfo = {}; + var _scrollVerticalInfo = {}; + var _viewportSize = {}; + var _nativeScrollbarMinSize = {}; + + //naming: + var _strMinusHidden = '-hidden'; + var _strMarginMinus = 'margin-'; + var _strPaddingMinus = 'padding-'; + var _strBorderMinus = 'border-'; + var _strTop = 'top'; + var _strRight = 'right'; + var _strBottom = 'bottom'; + var _strLeft = 'left'; + var _strMinMinus = 'min-'; + var _strMaxMinus = 'max-'; + var _strWidth = 'width'; + var _strHeight = 'height'; + var _strFloat = 'float'; + var _strEmpty = ''; + var _strAuto = 'auto'; + var _strSync = 'sync'; + var _strScroll = 'scroll'; + var _strHundredPercent = '100%'; + var _strX = 'x'; + var _strY = 'y'; + var _strDot = '.'; + var _strSpace = ' '; + var _strScrollbar = 'scrollbar'; + var _strMinusHorizontal = '-horizontal'; + var _strMinusVertical = '-vertical'; + var _strScrollLeft = _strScroll + 'Left'; + var _strScrollTop = _strScroll + 'Top'; + var _strMouseTouchDownEvent = 'mousedown touchstart'; + var _strMouseTouchUpEvent = 'mouseup touchend touchcancel'; + var _strMouseTouchMoveEvent = 'mousemove touchmove'; + var _strMouseTouchEnter = 'mouseenter'; + var _strMouseTouchLeave = 'mouseleave'; + var _strKeyDownEvent = 'keydown'; + var _strKeyUpEvent = 'keyup'; + var _strSelectStartEvent = 'selectstart'; + var _strTransitionEndEvent = 'transitionend webkitTransitionEnd oTransitionEnd'; + var _strResizeObserverProperty = '__overlayScrollbarsRO__'; + + //class names: + var _cassNamesPrefix = 'os-'; + var _classNameHTMLElement = _cassNamesPrefix + 'html'; + var _classNameHostElement = _cassNamesPrefix + 'host'; + var _classNameHostTextareaElement = _classNameHostElement + '-textarea'; + var _classNameHostScrollbarHorizontalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusHorizontal + _strMinusHidden; + var _classNameHostScrollbarVerticalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusVertical + _strMinusHidden; + var _classNameHostTransition = _classNameHostElement + '-transition'; + var _classNameHostRTL = _classNameHostElement + '-rtl'; + var _classNameHostResizeDisabled = _classNameHostElement + '-resize-disabled'; + var _classNameHostScrolling = _classNameHostElement + '-scrolling'; + var _classNameHostOverflow = _classNameHostElement + '-overflow'; + var _classNameHostOverflowX = _classNameHostOverflow + '-x'; + var _classNameHostOverflowY = _classNameHostOverflow + '-y'; + var _classNameTextareaElement = _cassNamesPrefix + 'textarea'; + var _classNameTextareaCoverElement = _classNameTextareaElement + '-cover'; + var _classNamePaddingElement = _cassNamesPrefix + 'padding'; + var _classNameViewportElement = _cassNamesPrefix + 'viewport'; + var _classNameViewportNativeScrollbarsInvisible = _classNameViewportElement + '-native-scrollbars-invisible'; + var _classNameViewportNativeScrollbarsOverlaid = _classNameViewportElement + '-native-scrollbars-overlaid'; + var _classNameContentElement = _cassNamesPrefix + 'content'; + var _classNameContentArrangeElement = _cassNamesPrefix + 'content-arrange'; + var _classNameContentGlueElement = _cassNamesPrefix + 'content-glue'; + var _classNameSizeAutoObserverElement = _cassNamesPrefix + 'size-auto-observer'; + var _classNameResizeObserverElement = _cassNamesPrefix + 'resize-observer'; + var _classNameResizeObserverItemElement = _cassNamesPrefix + 'resize-observer-item'; + var _classNameResizeObserverItemFinalElement = _classNameResizeObserverItemElement + '-final'; + var _classNameTextInherit = _cassNamesPrefix + 'text-inherit'; + var _classNameScrollbar = _cassNamesPrefix + _strScrollbar; + var _classNameScrollbarTrack = _classNameScrollbar + '-track'; + var _classNameScrollbarTrackOff = _classNameScrollbarTrack + '-off'; + var _classNameScrollbarHandle = _classNameScrollbar + '-handle'; + var _classNameScrollbarHandleOff = _classNameScrollbarHandle + '-off'; + var _classNameScrollbarUnusable = _classNameScrollbar + '-unusable'; + var _classNameScrollbarAutoHidden = _classNameScrollbar + '-' + _strAuto + _strMinusHidden; + var _classNameScrollbarCorner = _classNameScrollbar + '-corner'; + var _classNameScrollbarCornerResize = _classNameScrollbarCorner + '-resize'; + var _classNameScrollbarCornerResizeB = _classNameScrollbarCornerResize + '-both'; + var _classNameScrollbarCornerResizeH = _classNameScrollbarCornerResize + _strMinusHorizontal; + var _classNameScrollbarCornerResizeV = _classNameScrollbarCornerResize + _strMinusVertical; + var _classNameScrollbarHorizontal = _classNameScrollbar + _strMinusHorizontal; + var _classNameScrollbarVertical = _classNameScrollbar + _strMinusVertical; + var _classNameDragging = _cassNamesPrefix + 'dragging'; + var _classNameThemeNone = _cassNamesPrefix + 'theme-none'; + var _classNamesDynamicDestroy = [ + _classNameViewportNativeScrollbarsInvisible, + _classNameViewportNativeScrollbarsOverlaid, + _classNameScrollbarTrackOff, + _classNameScrollbarHandleOff, + _classNameScrollbarUnusable, + _classNameScrollbarAutoHidden, + _classNameScrollbarCornerResize, + _classNameScrollbarCornerResizeB, + _classNameScrollbarCornerResizeH, + _classNameScrollbarCornerResizeV, + _classNameDragging].join(_strSpace); + + //callbacks: + var _callbacksInitQeueue = []; + + //attrs viewport shall inherit from target + var _viewportAttrsFromTarget = [LEXICON.ti]; + + //options: + var _defaultOptions; + var _currentOptions; + var _currentPreparedOptions; + + //extensions: + var _extensions = {}; + var _extensionsPrivateMethods = 'added removed on contract'; + + //update + var _lastUpdateTime; + var _swallowedUpdateHints = {}; + var _swallowedUpdateTimeout; + var _swallowUpdateLag = 42; + var _imgs = []; + + //DOM elements: + var _windowElement; + var _documentElement; + var _htmlElement; + var _bodyElement; + var _targetElement; //the target element of this OverlayScrollbars object + var _hostElement; //the host element of this OverlayScrollbars object -> may be the same as targetElement + var _sizeAutoObserverElement; //observes size auto changes + var _sizeObserverElement; //observes size and padding changes + var _paddingElement; //manages the padding + var _viewportElement; //is the viewport of our scrollbar model + var _contentElement; //the element which holds the content + var _contentArrangeElement; //is needed for correct sizing of the content element (only if native scrollbars are overlays) + var _contentGlueElement; //has always the size of the content element + var _textareaCoverElement; //only applied if target is a textarea element. Used for correct size calculation and for prevention of uncontrolled scrolling + var _scrollbarCornerElement; + var _scrollbarHorizontalElement; + var _scrollbarHorizontalTrackElement; + var _scrollbarHorizontalHandleElement; + var _scrollbarVerticalElement; + var _scrollbarVerticalTrackElement; + var _scrollbarVerticalHandleElement; + var _windowElementNative; + var _documentElementNative; + var _targetElementNative; + var _hostElementNative; + var _sizeAutoObserverElementNative; + var _sizeObserverElementNative; + var _paddingElementNative; + var _viewportElementNative; + var _contentElementNative; + + //Cache: + var _hostSizeCache; + var _contentScrollSizeCache; + var _arrangeContentSizeCache; + var _hasOverflowCache; + var _hideOverflowCache; + var _widthAutoCache; + var _heightAutoCache; + var _cssMaxValueCache; + var _cssBoxSizingCache; + var _cssPaddingCache; + var _cssBorderCache; + var _cssMarginCache; + var _cssDirectionCache; + var _cssDirectionDetectedCache; + var _paddingAbsoluteCache; + var _clipAlwaysCache; + var _contentGlueSizeCache; + var _overflowBehaviorCache; + var _overflowAmountCache; + var _ignoreOverlayScrollbarHidingCache; + var _autoUpdateCache; + var _sizeAutoCapableCache; + var _contentElementScrollSizeChangeDetectedCache; + var _hostElementSizeChangeDetectedCache; + var _scrollbarsVisibilityCache; + var _scrollbarsAutoHideCache; + var _scrollbarsClickScrollingCache; + var _scrollbarsDragScrollingCache; + var _resizeCache; + var _normalizeRTLCache; + var _classNameCache; + var _oldClassName; + var _textareaAutoWrappingCache; + var _textareaInfoCache; + var _textareaSizeCache; + var _textareaDynHeightCache; + var _textareaDynWidthCache; + var _bodyMinSizeCache; + var _displayIsHiddenCache; + var _updateAutoCache = {}; + + //MutationObserver: + var _mutationObserverHost; + var _mutationObserverContent; + var _mutationObserverHostCallback; + var _mutationObserverContentCallback; + var _mutationObserversConnected; + var _mutationObserverAttrsTextarea = ['wrap', 'cols', 'rows']; + var _mutationObserverAttrsHost = [LEXICON.i, LEXICON.c, LEXICON.s, 'open'].concat(_viewportAttrsFromTarget); + + //events: + var _destroyEvents = []; + + //textarea: + var _textareaHasFocus; + + //scrollbars: + var _scrollbarsAutoHideTimeoutId; + var _scrollbarsAutoHideMoveTimeoutId; + var _scrollbarsAutoHideDelay; + var _scrollbarsAutoHideNever; + var _scrollbarsAutoHideScroll; + var _scrollbarsAutoHideMove; + var _scrollbarsAutoHideLeave; + var _scrollbarsHandleHovered; + var _scrollbarsHandlesDefineScrollPos; + + //resize + var _resizeNone; + var _resizeBoth; + var _resizeHorizontal; + var _resizeVertical; + + + //==== Event Listener ====// + + /** + * Adds or removes a event listener from the given element. + * @param element The element to which the event listener shall be applied or removed. + * @param eventNames The name(s) of the events. + * @param listener The method which shall be called. + * @param remove True if the handler shall be removed, false or undefined if the handler shall be added. + */ + function setupResponsiveEventListener(element, eventNames, listener, remove, passive) { + var collected = type(eventNames) == TYPES.a && type(listener) == TYPES.a; + var method = remove ? 'removeEventListener' : 'addEventListener'; + var onOff = remove ? 'off' : 'on'; + var events = collected ? false : eventNames.split(_strSpace) + var i = 0; + + if (collected) { + for (; i < eventNames[LEXICON.l]; i++) + setupResponsiveEventListener(element, eventNames[i], listener[i], remove); + } + else { + for (; i < events[LEXICON.l]; i++) { + if (_supportPassiveEvents) + element[0][method](events[i], listener, { passive: passive || false }); + else + element[onOff](events[i], listener); + } + } + } + + + function addDestroyEventListener(element, eventNames, listener, passive) { + setupResponsiveEventListener(element, eventNames, listener, false, passive); + _destroyEvents.push(COMPATIBILITY.bind(setupResponsiveEventListener, 0, element, eventNames, listener, true, passive)); + } + + //==== Resize Observer ====// + + /** + * Adds or removes a resize observer from the given element. + * @param targetElement The element to which the resize observer shall be added or removed. + * @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. + */ + function setupResizeObserver(targetElement, onElementResizedCallback) { + if (targetElement) { + var resizeObserver = COMPATIBILITY.rO(); + var strAnimationStartEvent = 'animationstart mozAnimationStart webkitAnimationStart MSAnimationStart'; + var strChildNodes = 'childNodes'; + var constScroll = 3333333; + var callback = function () { + targetElement[_strScrollTop](constScroll)[_strScrollLeft](_isRTL ? _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll : constScroll); + onElementResizedCallback(); + }; + //add resize observer: + if (onElementResizedCallback) { + if (_supportResizeObserver) { + var element = targetElement.addClass('observed').append(generateDiv(_classNameResizeObserverElement)).contents()[0]; + var observer = element[_strResizeObserverProperty] = new resizeObserver(callback); + observer.observe(element); + } + else { + if (_msieVersion > 9 || !_autoUpdateRecommended) { + targetElement.prepend( + generateDiv(_classNameResizeObserverElement, + generateDiv({ c: _classNameResizeObserverItemElement, dir: 'ltr' }, + generateDiv(_classNameResizeObserverItemElement, + generateDiv(_classNameResizeObserverItemFinalElement) + ) + + generateDiv(_classNameResizeObserverItemElement, + generateDiv({ c: _classNameResizeObserverItemFinalElement, style: 'width: 200%; height: 200%' }) + ) + ) + ) + ); + + var observerElement = targetElement[0][strChildNodes][0][strChildNodes][0]; + var shrinkElement = FRAMEWORK(observerElement[strChildNodes][1]); + var expandElement = FRAMEWORK(observerElement[strChildNodes][0]); + var expandElementChild = FRAMEWORK(expandElement[0][strChildNodes][0]); + var widthCache = observerElement[LEXICON.oW]; + var heightCache = observerElement[LEXICON.oH]; + var isDirty; + var rAFId; + var currWidth; + var currHeight; + var factor = 2; + var nativeScrollbarSize = globals.nativeScrollbarSize; //care don't make changes to this object!!! + var reset = function () { + /* + var sizeResetWidth = observerElement[LEXICON.oW] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; + var sizeResetHeight = observerElement[LEXICON.oH] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; + var expandChildCSS = {}; + expandChildCSS[_strWidth] = sizeResetWidth; + expandChildCSS[_strHeight] = sizeResetHeight; + expandElementChild.css(expandChildCSS); + + + expandElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); + shrinkElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); + */ + expandElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); + shrinkElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); + }; + var onResized = function () { + rAFId = 0; + if (!isDirty) + return; + + widthCache = currWidth; + heightCache = currHeight; + callback(); + }; + var onScroll = function (event) { + currWidth = observerElement[LEXICON.oW]; + currHeight = observerElement[LEXICON.oH]; + isDirty = currWidth != widthCache || currHeight != heightCache; + + if (event && isDirty && !rAFId) { + COMPATIBILITY.cAF()(rAFId); + rAFId = COMPATIBILITY.rAF()(onResized); + } + else if (!event) + onResized(); + + reset(); + if (event) { + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + return false; + }; + var expandChildCSS = {}; + var observerElementCSS = {}; + + setTopRightBottomLeft(observerElementCSS, _strEmpty, [ + -((nativeScrollbarSize.y + 1) * factor), + nativeScrollbarSize.x * -factor, + nativeScrollbarSize.y * -factor, + -((nativeScrollbarSize.x + 1) * factor) + ]); + + FRAMEWORK(observerElement).css(observerElementCSS); + expandElement.on(_strScroll, onScroll); + shrinkElement.on(_strScroll, onScroll); + targetElement.on(strAnimationStartEvent, function () { + onScroll(false); + }); + //lets assume that the divs will never be that large and a constant value is enough + expandChildCSS[_strWidth] = constScroll; + expandChildCSS[_strHeight] = constScroll; + expandElementChild.css(expandChildCSS); + + reset(); + } + else { + var attachEvent = _documentElementNative.attachEvent; + var isIE = _msieVersion !== undefined; + if (attachEvent) { + targetElement.prepend(generateDiv(_classNameResizeObserverElement)); + findFirst(targetElement, _strDot + _classNameResizeObserverElement)[0].attachEvent('onresize', callback); + } + else { + var obj = _documentElementNative.createElement(TYPES.o); + obj.setAttribute(LEXICON.ti, '-1'); + obj.setAttribute(LEXICON.c, _classNameResizeObserverElement); + obj.onload = function () { + var wnd = this.contentDocument.defaultView; + wnd.addEventListener('resize', callback); + wnd.document.documentElement.style.display = 'none'; + }; + obj.type = 'text/html'; + if (isIE) + targetElement.prepend(obj); + obj.data = 'about:blank'; + if (!isIE) + targetElement.prepend(obj); + targetElement.on(strAnimationStartEvent, callback); + } + } + } + + if (targetElement[0] === _sizeObserverElementNative) { + var directionChanged = function () { + var dir = _hostElement.css('direction'); + var css = {}; + var scrollLeftValue = 0; + var result = false; + if (dir !== _cssDirectionDetectedCache) { + if (dir === 'ltr') { + css[_strLeft] = 0; + css[_strRight] = _strAuto; + scrollLeftValue = constScroll; + } + else { + css[_strLeft] = _strAuto; + css[_strRight] = 0; + scrollLeftValue = _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll; + } + //execution order is important for IE!!! + _sizeObserverElement.children().eq(0).css(css); + _sizeObserverElement[_strScrollLeft](scrollLeftValue)[_strScrollTop](constScroll); + _cssDirectionDetectedCache = dir; + result = true; + } + return result; + }; + directionChanged(); + addDestroyEventListener(targetElement, _strScroll, function (event) { + if (directionChanged()) + update(); + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + return false; + }); + } + } + //remove resize observer: + else { + if (_supportResizeObserver) { + var element = targetElement.contents()[0]; + var resizeObserverObj = element[_strResizeObserverProperty]; + if (resizeObserverObj) { + resizeObserverObj.disconnect(); + delete element[_strResizeObserverProperty]; + } + } + else { + remove(targetElement.children(_strDot + _classNameResizeObserverElement).eq(0)); + } + } + } + } + + /** + * Freezes or unfreezes the given resize observer. + * @param targetElement The element to which the target resize observer is applied. + * @param freeze True if the resize observer shall be frozen, false otherwise. + + function freezeResizeObserver(targetElement, freeze) { + if (targetElement !== undefined) { + if(freeze) { + if (_supportResizeObserver) { + var element = targetElement.contents()[0]; + element[_strResizeObserverProperty].unobserve(element); + } + else { + targetElement = targetElement.children(_strDot + _classNameResizeObserverElement).eq(0); + var w = targetElement.css(_strWidth); + var h = targetElement.css(_strHeight); + var css = {}; + css[_strWidth] = w; + css[_strHeight] = h; + targetElement.css(css); + } + } + else { + if (_supportResizeObserver) { + var element = targetElement.contents()[0]; + element[_strResizeObserverProperty].observe(element); + } + else { + var css = { }; + css[_strHeight] = _strEmpty; + css[_strWidth] = _strEmpty; + targetElement.children(_strDot + _classNameResizeObserverElement).eq(0).css(css); + } + } + } + } + */ + + + //==== Mutation Observers ====// + + /** + * Creates MutationObservers for the host and content Element if they are supported. + */ + function createMutationObservers() { + if (_supportMutationObserver) { + var mutationObserverContentLag = 11; + var mutationObserver = COMPATIBILITY.mO(); + var contentLastUpdate = COMPATIBILITY.now(); + var mutationTarget; + var mutationAttrName; + var contentTimeout; + var now; + var sizeAuto; + var action; + + _mutationObserverHostCallback = function (mutations) { + var doUpdate = false; + var mutation; + var mutatedAttrs = []; + + if (_initialized && !_sleeping) { + each(mutations, function () { + mutation = this; + mutationTarget = mutation.target; + mutationAttrName = mutation.attributeName; + + if(!doUpdate) { + if (mutationAttrName === LEXICON.c) + doUpdate = hostClassNamesChanged(mutation.oldValue, mutationTarget.className); + else if (mutationAttrName === LEXICON.s) + doUpdate = mutation.oldValue !== mutationTarget[LEXICON.s].cssText; + else + doUpdate = true; + } + + mutatedAttrs.push(mutationAttrName); + }); + + updateViewportAttrsFromTarget(mutatedAttrs); + + if (doUpdate) + _base.update(_strAuto); + } + return doUpdate; + }; + _mutationObserverContentCallback = function (mutations) { + var doUpdate = false; + var mutation; + + if (_initialized && !_sleeping) { + each(mutations, function () { + mutation = this; + doUpdate = isUnknownMutation(mutation); + return !doUpdate; + }); + + if (doUpdate) { + now = COMPATIBILITY.now(); + sizeAuto = (_heightAutoCache || _widthAutoCache); + action = function () { + if (!_destroyed) { + contentLastUpdate = now; + + //if cols, rows or wrap attr was changed + if (_isTextarea) + textareaUpdate(); + + if (sizeAuto) + update(); + else + _base.update(_strAuto); + } + }; + clearTimeout(contentTimeout); + if (mutationObserverContentLag <= 0 || now - contentLastUpdate > mutationObserverContentLag || !sizeAuto) + action(); + else + contentTimeout = setTimeout(action, mutationObserverContentLag); + } + } + return doUpdate; + } + + _mutationObserverHost = new mutationObserver(_mutationObserverHostCallback); + _mutationObserverContent = new mutationObserver(_mutationObserverContentCallback); + } + } + + /** + * Connects the MutationObservers if they are supported. + */ + function connectMutationObservers() { + if (_supportMutationObserver && !_mutationObserversConnected) { + _mutationObserverHost.observe(_hostElementNative, { + attributes: true, + attributeOldValue: true, + attributeFilter: _mutationObserverAttrsHost + }); + + _mutationObserverContent.observe(_isTextarea ? _targetElementNative : _contentElementNative, { + attributes: true, + attributeOldValue: true, + subtree: !_isTextarea, + childList: !_isTextarea, + characterData: !_isTextarea, + attributeFilter: _isTextarea ? _mutationObserverAttrsTextarea : _mutationObserverAttrsHost + }); + + _mutationObserversConnected = true; + } + } + + /** + * Disconnects the MutationObservers if they are supported. + */ + function disconnectMutationObservers() { + if (_supportMutationObserver && _mutationObserversConnected) { + _mutationObserverHost.disconnect(); + _mutationObserverContent.disconnect(); + + _mutationObserversConnected = false; + } + } + + + //==== Events of elements ====// + + /** + * This method gets called every time the host element gets resized. IMPORTANT: Padding changes are detected too!! + * It refreshes the hostResizedEventArgs and the hostSizeResizeCache. + * If there are any size changes, the update method gets called. + */ + function hostOnResized() { + if (!_sleeping) { + var changed; + var hostSize = { + w: _sizeObserverElementNative[LEXICON.sW], + h: _sizeObserverElementNative[LEXICON.sH] + }; + + changed = checkCache(hostSize, _hostElementSizeChangeDetectedCache); + _hostElementSizeChangeDetectedCache = hostSize; + if (changed) + update({ _hostSizeChanged: true }); + } + } + + /** + * The mouse enter event of the host element. This event is only needed for the autoHide feature. + */ + function hostOnMouseEnter() { + if (_scrollbarsAutoHideLeave) + refreshScrollbarsAutoHide(true); + } + + /** + * The mouse leave event of the host element. This event is only needed for the autoHide feature. + */ + function hostOnMouseLeave() { + if (_scrollbarsAutoHideLeave && !_bodyElement.hasClass(_classNameDragging)) + refreshScrollbarsAutoHide(false); + } + + /** + * The mouse move event of the host element. This event is only needed for the autoHide "move" feature. + */ + function hostOnMouseMove() { + if (_scrollbarsAutoHideMove) { + refreshScrollbarsAutoHide(true); + clearTimeout(_scrollbarsAutoHideMoveTimeoutId); + _scrollbarsAutoHideMoveTimeoutId = setTimeout(function () { + if (_scrollbarsAutoHideMove && !_destroyed) + refreshScrollbarsAutoHide(false); + }, 100); + } + } + + /** + * Prevents text from deselection if attached to the document element on the mousedown event of a DOM element. + * @param event The select start event. + */ + function documentOnSelectStart(event) { + COMPATIBILITY.prvD(event); + return false; + } + + /** + * A callback which will be called after a img element has downloaded its src asynchronous. + */ + function imgOnLoad() { + update({ _contentSizeChanged: true }); + } + + /** + * Adds or removes mouse & touch events of the host element. (for handling auto-hiding of the scrollbars) + * @param destroy Indicates whether the events shall be added or removed. + */ + function setupHostMouseTouchEvents(destroy) { + setupResponsiveEventListener(_hostElement, + _strMouseTouchMoveEvent, + hostOnMouseMove, + (_scrollbarsAutoHideMove ? destroy : true), true); + setupResponsiveEventListener(_hostElement, + [_strMouseTouchEnter, _strMouseTouchLeave], + [hostOnMouseEnter, hostOnMouseLeave], + (_scrollbarsAutoHideMove ? true : destroy), true); + + //if the plugin is initialized and the mouse is over the host element, make the scrollbars visible + if (!_initialized && !destroy) + _hostElement.one('mouseover', hostOnMouseEnter); + } + + + //==== Update Detection ====// + + /** + * Measures the min width and min height of the body element and refreshes the related cache. + * @returns {boolean} True if the min width or min height has changed, false otherwise. + */ + function bodyMinSizeChanged() { + var bodyMinSize = {}; + if (_isBody && _contentArrangeElement) { + bodyMinSize.w = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strWidth)); + bodyMinSize.h = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strHeight)); + bodyMinSize.c = checkCache(bodyMinSize, _bodyMinSizeCache); + bodyMinSize.f = true; //flag for "measured at least once" + } + _bodyMinSizeCache = bodyMinSize; + return !!bodyMinSize.c; + } + + /** + * Returns true if the class names really changed (new class without plugin host prefix) + * @param oldCassNames The old ClassName string. + * @param newClassNames The new ClassName string. + * @returns {boolean} True if the class names has really changed, false otherwise. + */ + function hostClassNamesChanged(oldCassNames, newClassNames) { + var currClasses = (newClassNames !== undefined && newClassNames !== null) ? newClassNames.split(_strSpace) : _strEmpty; + var oldClasses = (oldCassNames !== undefined && oldCassNames !== null) ? oldCassNames.split(_strSpace) : _strEmpty; + if (currClasses === _strEmpty && oldClasses === _strEmpty) + return false; + var diff = getArrayDifferences(oldClasses, currClasses); + var changed = false; + var oldClassNames = _oldClassName !== undefined && _oldClassName !== null ? _oldClassName.split(_strSpace) : [_strEmpty]; + var currClassNames = _classNameCache !== undefined && _classNameCache !== null ? _classNameCache.split(_strSpace) : [_strEmpty]; + + //remove none theme from diff list to prevent update + var idx = inArray(_classNameThemeNone, diff); + var curr; + var i; + var v; + var o; + var c; + + if (idx > -1) + diff.splice(idx, 1); + + for (i = 0; i < diff.length; i++) { + curr = diff[i]; + if (curr.indexOf(_classNameHostElement) !== 0) { + o = true; + c = true; + for (v = 0; v < oldClassNames.length; v++) { + if (curr === oldClassNames[v]) { + o = false; + break; + } + } + for (v = 0; v < currClassNames.length; v++) { + if (curr === currClassNames[v]) { + c = false; + break; + } + } + if (o && c) { + changed = true; + break; + } + } + + } + return changed; + } + + /** + * 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. + * @param mutation The mutation which shall be checked. + * @returns {boolean} True if the mutation is from a unknown element, false otherwise. + */ + function isUnknownMutation(mutation) { + var attributeName = mutation.attributeName; + var mutationTarget = mutation.target; + var mutationType = mutation.type; + var strClosest = 'closest'; + + if (mutationTarget === _contentElementNative) + return attributeName === null; + if (mutationType === 'attributes' && (attributeName === LEXICON.c || attributeName === LEXICON.s) && !_isTextarea) { + //ignore className changes by the plugin + if (attributeName === LEXICON.c && FRAMEWORK(mutationTarget).hasClass(_classNameHostElement)) + return hostClassNamesChanged(mutation.oldValue, mutationTarget.getAttribute(LEXICON.c)); + + //only do it of browser support it natively + if (typeof mutationTarget[strClosest] != TYPES.f) + return true; + if (mutationTarget[strClosest](_strDot + _classNameResizeObserverElement) !== null || + mutationTarget[strClosest](_strDot + _classNameScrollbar) !== null || + mutationTarget[strClosest](_strDot + _classNameScrollbarCorner) !== null) + return false; + } + return true; + } + + /** + * Returns true if the content size was changed since the last time this method was called. + * @returns {boolean} True if the content size was changed, false otherwise. + */ + function updateAutoContentSizeChanged() { + if (_sleeping) + return false; + + var contentMeasureElement = getContentMeasureElement(); + var textareaValueLength = _isTextarea && _widthAutoCache && !_textareaAutoWrappingCache ? _targetElement.val().length : 0; + var setCSS = !_mutationObserversConnected && _widthAutoCache && !_isTextarea; + var css = {}; + var float; + var bodyMinSizeC; + var changed; + var contentElementScrollSize; + + if (setCSS) { + float = _contentElement.css(_strFloat); + css[_strFloat] = _isRTL ? _strRight : _strLeft; + css[_strWidth] = _strAuto; + _contentElement.css(css); + } + contentElementScrollSize = { + w: contentMeasureElement[LEXICON.sW] + textareaValueLength, + h: contentMeasureElement[LEXICON.sH] + textareaValueLength + }; + if (setCSS) { + css[_strFloat] = float; + css[_strWidth] = _strHundredPercent; + _contentElement.css(css); + } + + bodyMinSizeC = bodyMinSizeChanged(); + changed = checkCache(contentElementScrollSize, _contentElementScrollSizeChangeDetectedCache); + + _contentElementScrollSizeChangeDetectedCache = contentElementScrollSize; + + return changed || bodyMinSizeC; + } + + /** + * Returns true when a attribute which the MutationObserver would observe has changed. + * @returns {boolean} True if one of the attributes which a MutationObserver would observe has changed, false or undefined otherwise. + */ + function meaningfulAttrsChanged() { + if (_sleeping || _mutationObserversConnected) + return; + + var elem; + var curr; + var cache; + var changedAttrs = []; + var checks = [ + { + _elem: _hostElement, + _attrs: _mutationObserverAttrsHost.concat(':visible') + }, + { + _elem: _isTextarea ? _targetElement : undefined, + _attrs: _mutationObserverAttrsTextarea + } + ]; + + each(checks, function (index, check) { + elem = check._elem; + if (elem) { + each(check._attrs, function (index, attr) { + curr = attr.charAt(0) === ':' ? elem.is(attr) : elem.attr(attr); + cache = _updateAutoCache[attr]; + + if(checkCache(curr, cache)) { + changedAttrs.push(attr); + } + + _updateAutoCache[attr] = curr; + }); + } + }); + + updateViewportAttrsFromTarget(changedAttrs); + + return changedAttrs[LEXICON.l] > 0; + } + + /** + * Checks is a CSS Property of a child element is affecting the scroll size of the content. + * @param propertyName The CSS property name. + * @returns {boolean} True if the property is affecting the content scroll size, false otherwise. + */ + function isSizeAffectingCSSProperty(propertyName) { + if (!_initialized) + return true; + var flexGrow = 'flex-grow'; + var flexShrink = 'flex-shrink'; + var flexBasis = 'flex-basis'; + var affectingPropsX = [ + _strWidth, + _strMinMinus + _strWidth, + _strMaxMinus + _strWidth, + _strMarginMinus + _strLeft, + _strMarginMinus + _strRight, + _strLeft, + _strRight, + 'font-weight', + 'word-spacing', + flexGrow, + flexShrink, + flexBasis + ]; + var affectingPropsXContentBox = [ + _strPaddingMinus + _strLeft, + _strPaddingMinus + _strRight, + _strBorderMinus + _strLeft + _strWidth, + _strBorderMinus + _strRight + _strWidth + ]; + var affectingPropsY = [ + _strHeight, + _strMinMinus + _strHeight, + _strMaxMinus + _strHeight, + _strMarginMinus + _strTop, + _strMarginMinus + _strBottom, + _strTop, + _strBottom, + 'line-height', + flexGrow, + flexShrink, + flexBasis + ]; + var affectingPropsYContentBox = [ + _strPaddingMinus + _strTop, + _strPaddingMinus + _strBottom, + _strBorderMinus + _strTop + _strWidth, + _strBorderMinus + _strBottom + _strWidth + ]; + var _strS = 's'; + var _strVS = 'v-s'; + var checkX = _overflowBehaviorCache.x === _strS || _overflowBehaviorCache.x === _strVS; + var checkY = _overflowBehaviorCache.y === _strS || _overflowBehaviorCache.y === _strVS; + var sizeIsAffected = false; + var checkPropertyName = function (arr, name) { + for (var i = 0; i < arr[LEXICON.l]; i++) { + if (arr[i] === name) + return true; + } + return false; + }; + + if (checkY) { + sizeIsAffected = checkPropertyName(affectingPropsY, propertyName); + if (!sizeIsAffected && !_isBorderBox) + sizeIsAffected = checkPropertyName(affectingPropsYContentBox, propertyName); + } + if (checkX && !sizeIsAffected) { + sizeIsAffected = checkPropertyName(affectingPropsX, propertyName); + if (!sizeIsAffected && !_isBorderBox) + sizeIsAffected = checkPropertyName(affectingPropsXContentBox, propertyName); + } + return sizeIsAffected; + } + + + //==== Update ====// + + /** + * Sets the attribute values of the viewport element to the values from the target element. + * The value of a attribute is only set if the attribute is whitelisted. + * @attrs attrs The array of attributes which shall be set or undefined if all whitelisted shall be set. + */ + function updateViewportAttrsFromTarget(attrs) { + attrs = attrs || _viewportAttrsFromTarget; + each(attrs, function (index, attr) { + if (COMPATIBILITY.inA(attr, _viewportAttrsFromTarget) > -1) { + var targetAttr = _targetElement.attr(attr); + if(type(targetAttr) == TYPES.s) { + _viewportElement.attr(attr, targetAttr); + } + else { + _viewportElement.removeAttr(attr); + } + } + }); + } + + /** + * Updates the variables and size of the textarea element, and manages the scroll on new line or new character. + */ + function textareaUpdate() { + if (!_sleeping) { + var wrapAttrOff = !_textareaAutoWrappingCache; + var minWidth = _viewportSize.w; + var minHeight = _viewportSize.h; + var css = {}; + var doMeasure = _widthAutoCache || wrapAttrOff; + var origWidth; + var width; + var origHeight; + var height; + + //reset min size + css[_strMinMinus + _strWidth] = _strEmpty; + css[_strMinMinus + _strHeight] = _strEmpty; + + //set width auto + css[_strWidth] = _strAuto; + _targetElement.css(css); + + //measure width + origWidth = _targetElementNative[LEXICON.oW]; + width = doMeasure ? MATH.max(origWidth, _targetElementNative[LEXICON.sW] - 1) : 1; + /*width += (_widthAutoCache ? _marginX + (!_isBorderBox ? wrapAttrOff ? 0 : _paddingX + _borderX : 0) : 0);*/ + + //set measured width + css[_strWidth] = _widthAutoCache ? _strAuto /*width*/ : _strHundredPercent; + css[_strMinMinus + _strWidth] = _strHundredPercent; + + //set height auto + css[_strHeight] = _strAuto; + _targetElement.css(css); + + //measure height + origHeight = _targetElementNative[LEXICON.oH]; + height = MATH.max(origHeight, _targetElementNative[LEXICON.sH] - 1); + + //append correct size values + css[_strWidth] = width; + css[_strHeight] = height; + _textareaCoverElement.css(css); + + //apply min width / min height to prevent textarea collapsing + css[_strMinMinus + _strWidth] = minWidth /*+ (!_isBorderBox && _widthAutoCache ? _paddingX + _borderX : 0)*/; + css[_strMinMinus + _strHeight] = minHeight /*+ (!_isBorderBox && _heightAutoCache ? _paddingY + _borderY : 0)*/; + _targetElement.css(css); + + return { + _originalWidth: origWidth, + _originalHeight: origHeight, + _dynamicWidth: width, + _dynamicHeight: height + }; + } + } + + /** + * Updates the plugin and DOM to the current options. + * This method should only be called if a update is 100% required. + * @param updateHints A objects which contains hints for this update: + * { + * _hostSizeChanged : boolean, + * _contentSizeChanged : boolean, + * _force : boolean, == preventSwallowing + * _changedOptions : { }, == preventSwallowing && preventSleep + * } + */ + function update(updateHints) { + clearTimeout(_swallowedUpdateTimeout); + updateHints = updateHints || {}; + _swallowedUpdateHints._hostSizeChanged |= updateHints._hostSizeChanged; + _swallowedUpdateHints._contentSizeChanged |= updateHints._contentSizeChanged; + _swallowedUpdateHints._force |= updateHints._force; + + var now = COMPATIBILITY.now(); + var hostSizeChanged = !!_swallowedUpdateHints._hostSizeChanged; + var contentSizeChanged = !!_swallowedUpdateHints._contentSizeChanged; + var force = !!_swallowedUpdateHints._force; + var changedOptions = updateHints._changedOptions; + var swallow = _swallowUpdateLag > 0 && _initialized && !_destroyed && !force && !changedOptions && (now - _lastUpdateTime) < _swallowUpdateLag && (!_heightAutoCache && !_widthAutoCache); + var displayIsHidden; + + if (swallow) + _swallowedUpdateTimeout = setTimeout(update, _swallowUpdateLag); + + //abort update due to: + //destroyed + //swallowing + //sleeping + //host is hidden or has false display + if (_destroyed || swallow || (_sleeping && !changedOptions) || (_initialized && !force && (displayIsHidden = _hostElement.is(':hidden'))) || _hostElement.css('display') === 'inline') + return; + + _lastUpdateTime = now; + _swallowedUpdateHints = {}; + + //if scrollbar styling is possible and native scrollbars aren't overlaid the scrollbar styling will be applied which hides the native scrollbars completely. + if (_nativeScrollbarStyling && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { + //native scrollbars are hidden, so change the values to zero + _nativeScrollbarSize.x = 0; + _nativeScrollbarSize.y = 0; + } + else { + //refresh native scrollbar size (in case of zoom) + _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); + } + + // Scrollbar padding is needed for firefox, because firefox hides scrollbar automatically if the size of the div is too small. + // The calculation: [scrollbar size +3 *3] + // (+3 because of possible decoration e.g. borders, margins etc., but only if native scrollbar is NOT a overlaid scrollbar) + // (*3 because (1)increase / (2)decrease -button and (3)resize handle) + _nativeScrollbarMinSize = { + x: (_nativeScrollbarSize.x + (_nativeScrollbarIsOverlaid.x ? 0 : 3)) * 3, + y: (_nativeScrollbarSize.y + (_nativeScrollbarIsOverlaid.y ? 0 : 3)) * 3 + }; + + //changedOptions = changedOptions || { }; + //freezeResizeObserver(_sizeObserverElement, true); + //freezeResizeObserver(_sizeAutoObserverElement, true); + + var checkCacheAutoForce = function () { + return checkCache.apply(this, [].slice.call(arguments).concat([force])); + }; + + //save current scroll offset + var currScroll = { + x: _viewportElement[_strScrollLeft](), + y: _viewportElement[_strScrollTop]() + }; + + var currentPreparedOptionsScrollbars = _currentPreparedOptions.scrollbars; + var currentPreparedOptionsTextarea = _currentPreparedOptions.textarea; + + //scrollbars visibility: + var scrollbarsVisibility = currentPreparedOptionsScrollbars.visibility; + var scrollbarsVisibilityChanged = checkCacheAutoForce(scrollbarsVisibility, _scrollbarsVisibilityCache); + + //scrollbars autoHide: + var scrollbarsAutoHide = currentPreparedOptionsScrollbars.autoHide; + var scrollbarsAutoHideChanged = checkCacheAutoForce(scrollbarsAutoHide, _scrollbarsAutoHideCache); + + //scrollbars click scrolling + var scrollbarsClickScrolling = currentPreparedOptionsScrollbars.clickScrolling; + var scrollbarsClickScrollingChanged = checkCacheAutoForce(scrollbarsClickScrolling, _scrollbarsClickScrollingCache); + + //scrollbars drag scrolling + var scrollbarsDragScrolling = currentPreparedOptionsScrollbars.dragScrolling; + var scrollbarsDragScrollingChanged = checkCacheAutoForce(scrollbarsDragScrolling, _scrollbarsDragScrollingCache); + + //className + var className = _currentPreparedOptions.className; + var classNameChanged = checkCacheAutoForce(className, _classNameCache); + + //resize + var resize = _currentPreparedOptions.resize; + var resizeChanged = checkCacheAutoForce(resize, _resizeCache) && !_isBody; //body can't be resized since the window itself acts as resize possibility. + + //paddingAbsolute + var paddingAbsolute = _currentPreparedOptions.paddingAbsolute; + var paddingAbsoluteChanged = checkCacheAutoForce(paddingAbsolute, _paddingAbsoluteCache); + + //clipAlways + var clipAlways = _currentPreparedOptions.clipAlways; + var clipAlwaysChanged = checkCacheAutoForce(clipAlways, _clipAlwaysCache); + + //sizeAutoCapable + var sizeAutoCapable = _currentPreparedOptions.sizeAutoCapable && !_isBody; //body can never be size auto, because it shall be always as big as the viewport. + var sizeAutoCapableChanged = checkCacheAutoForce(sizeAutoCapable, _sizeAutoCapableCache); + + //showNativeScrollbars + var ignoreOverlayScrollbarHiding = _currentPreparedOptions.nativeScrollbarsOverlaid.showNativeScrollbars; + var ignoreOverlayScrollbarHidingChanged = checkCacheAutoForce(ignoreOverlayScrollbarHiding, _ignoreOverlayScrollbarHidingCache); + + //autoUpdate + var autoUpdate = _currentPreparedOptions.autoUpdate; + var autoUpdateChanged = checkCacheAutoForce(autoUpdate, _autoUpdateCache); + + //overflowBehavior + var overflowBehavior = _currentPreparedOptions.overflowBehavior; + var overflowBehaviorChanged = checkCacheAutoForce(overflowBehavior, _overflowBehaviorCache, force); + + //dynWidth: + var textareaDynWidth = currentPreparedOptionsTextarea.dynWidth; + var textareaDynWidthChanged = checkCacheAutoForce(_textareaDynWidthCache, textareaDynWidth); + + //dynHeight: + var textareaDynHeight = currentPreparedOptionsTextarea.dynHeight; + var textareaDynHeightChanged = checkCacheAutoForce(_textareaDynHeightCache, textareaDynHeight); + + //scrollbars visibility + _scrollbarsAutoHideNever = scrollbarsAutoHide === 'n'; + _scrollbarsAutoHideScroll = scrollbarsAutoHide === 's'; + _scrollbarsAutoHideMove = scrollbarsAutoHide === 'm'; + _scrollbarsAutoHideLeave = scrollbarsAutoHide === 'l'; + + //scrollbars autoHideDelay + _scrollbarsAutoHideDelay = currentPreparedOptionsScrollbars.autoHideDelay; + + //old className + _oldClassName = _classNameCache; + + //resize + _resizeNone = resize === 'n'; + _resizeBoth = resize === 'b'; + _resizeHorizontal = resize === 'h'; + _resizeVertical = resize === 'v'; + + //normalizeRTL + _normalizeRTLCache = _currentPreparedOptions.normalizeRTL; + + //ignore overlay scrollbar hiding + ignoreOverlayScrollbarHiding = ignoreOverlayScrollbarHiding && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y); + + //refresh options cache + _scrollbarsVisibilityCache = scrollbarsVisibility; + _scrollbarsAutoHideCache = scrollbarsAutoHide; + _scrollbarsClickScrollingCache = scrollbarsClickScrolling; + _scrollbarsDragScrollingCache = scrollbarsDragScrolling; + _classNameCache = className; + _resizeCache = resize; + _paddingAbsoluteCache = paddingAbsolute; + _clipAlwaysCache = clipAlways; + _sizeAutoCapableCache = sizeAutoCapable; + _ignoreOverlayScrollbarHidingCache = ignoreOverlayScrollbarHiding; + _autoUpdateCache = autoUpdate; + _overflowBehaviorCache = extendDeep({}, overflowBehavior); + _textareaDynWidthCache = textareaDynWidth; + _textareaDynHeightCache = textareaDynHeight; + _hasOverflowCache = _hasOverflowCache || { x: false, y: false }; + + //set correct class name to the host element + if (classNameChanged) { + removeClass(_hostElement, _oldClassName + _strSpace + _classNameThemeNone); + addClass(_hostElement, className !== undefined && className !== null && className.length > 0 ? className : _classNameThemeNone); + } + + //set correct auto Update + if (autoUpdateChanged) { + if (autoUpdate === true) { + disconnectMutationObservers(); + autoUpdateLoop.add(_base); + } + else if (autoUpdate === null) { + if (_autoUpdateRecommended) { + disconnectMutationObservers(); + autoUpdateLoop.add(_base); + } + else { + autoUpdateLoop.remove(_base); + connectMutationObservers(); + } + } + else { + autoUpdateLoop.remove(_base); + connectMutationObservers(); + } + } + + //activate or deactivate size auto capability + if (sizeAutoCapableChanged) { + if (sizeAutoCapable) { + if (!_contentGlueElement) { + _contentGlueElement = FRAMEWORK(generateDiv(_classNameContentGlueElement)); + _paddingElement.before(_contentGlueElement); + } + else { + _contentGlueElement.show(); + } + if (_sizeAutoObserverAdded) { + _sizeAutoObserverElement.show(); + } + else { + _sizeAutoObserverElement = FRAMEWORK(generateDiv(_classNameSizeAutoObserverElement)); + _sizeAutoObserverElementNative = _sizeAutoObserverElement[0]; + + _contentGlueElement.before(_sizeAutoObserverElement); + var oldSize = { w: -1, h: -1 }; + setupResizeObserver(_sizeAutoObserverElement, function () { + var newSize = { + w: _sizeAutoObserverElementNative[LEXICON.oW], + h: _sizeAutoObserverElementNative[LEXICON.oH] + }; + if (checkCache(newSize, oldSize)) { + if (_initialized && (_heightAutoCache && newSize.h > 0) || (_widthAutoCache && newSize.w > 0)) { + update(); + } + else if (_initialized && (!_heightAutoCache && newSize.h === 0) || (!_widthAutoCache && newSize.w === 0)) { + update(); + } + } + oldSize = newSize; + }); + _sizeAutoObserverAdded = true; + //fix heightAuto detector bug if height is fixed but contentHeight is 0. + //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. + if (_cssCalc !== null) + _sizeAutoObserverElement.css(_strHeight, _cssCalc + '(100% + 1px)'); + } + } + else { + if (_sizeAutoObserverAdded) + _sizeAutoObserverElement.hide(); + if (_contentGlueElement) + _contentGlueElement.hide(); + } + } + + //if force, update all resizeObservers too + if (force) { + _sizeObserverElement.find('*').trigger(_strScroll); + if (_sizeAutoObserverAdded) + _sizeAutoObserverElement.find('*').trigger(_strScroll); + } + + //display hidden: + displayIsHidden = displayIsHidden === undefined ? _hostElement.is(':hidden') : displayIsHidden; + var displayIsHiddenChanged = checkCacheAutoForce(displayIsHidden, _displayIsHiddenCache); + + //textarea AutoWrapping: + var textareaAutoWrapping = _isTextarea ? _targetElement.attr('wrap') !== 'off' : false; + var textareaAutoWrappingChanged = checkCacheAutoForce(textareaAutoWrapping, _textareaAutoWrappingCache); + + //detect direction: + var cssDirection = _hostElement.css('direction'); + var cssDirectionChanged = checkCacheAutoForce(cssDirection, _cssDirectionCache); + + //detect box-sizing: + var boxSizing = _hostElement.css('box-sizing'); + var boxSizingChanged = checkCacheAutoForce(boxSizing, _cssBoxSizingCache); + + //detect padding: + var padding = { + c: force, + t: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strTop)), + r: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strRight)), + b: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strBottom)), + l: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strLeft)) + }; + + //width + height auto detecting var: + var sizeAutoObserverElementBCRect; + //exception occurs in IE8 sometimes (unknown exception) + try { + sizeAutoObserverElementBCRect = _sizeAutoObserverAdded ? _sizeAutoObserverElementNative[LEXICON.bCR]() : null; + } catch (ex) { + return; + } + + _isRTL = cssDirection === 'rtl'; + _isBorderBox = (boxSizing === 'border-box'); + var isRTLLeft = _isRTL ? _strLeft : _strRight; + var isRTLRight = _isRTL ? _strRight : _strLeft; + + //detect width auto: + var widthAutoResizeDetection = false; + var widthAutoObserverDetection = (_sizeAutoObserverAdded && (_hostElement.css(_strFloat) !== 'none' /*|| _isTextarea */)) ? (MATH.round(sizeAutoObserverElementBCRect.right - sizeAutoObserverElementBCRect.left) === 0) && (!paddingAbsolute ? (_hostElementNative[LEXICON.cW] - _paddingX) > 0 : true) : false; + if (sizeAutoCapable && !widthAutoObserverDetection) { + var tmpCurrHostWidth = _hostElementNative[LEXICON.oW]; + var tmpCurrContentGlueWidth = _contentGlueElement.css(_strWidth); + _contentGlueElement.css(_strWidth, _strAuto); + + var tmpNewHostWidth = _hostElementNative[LEXICON.oW]; + _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); + widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; + if (!widthAutoResizeDetection) { + _contentGlueElement.css(_strWidth, tmpCurrHostWidth + 1); + tmpNewHostWidth = _hostElementNative[LEXICON.oW]; + _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); + widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; + } + } + var widthAuto = (widthAutoObserverDetection || widthAutoResizeDetection) && sizeAutoCapable && !displayIsHidden; + var widthAutoChanged = checkCacheAutoForce(widthAuto, _widthAutoCache); + var wasWidthAuto = !widthAuto && _widthAutoCache; + + //detect height auto: + var heightAuto = _sizeAutoObserverAdded && sizeAutoCapable && !displayIsHidden ? (MATH.round(sizeAutoObserverElementBCRect.bottom - sizeAutoObserverElementBCRect.top) === 0) /* && (!paddingAbsolute && (_msieVersion > 9 || !_msieVersion) ? true : true) */ : false; + var heightAutoChanged = checkCacheAutoForce(heightAuto, _heightAutoCache); + var wasHeightAuto = !heightAuto && _heightAutoCache; + + //detect border: + //we need the border only if border box and auto size + var strMinusWidth = '-' + _strWidth; + var updateBorderX = (widthAuto && _isBorderBox) || !_isBorderBox; + var updateBorderY = (heightAuto && _isBorderBox) || !_isBorderBox; + var border = { + c: force, + t: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strTop + strMinusWidth), true) : 0, + r: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strRight + strMinusWidth), true) : 0, + b: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strBottom + strMinusWidth), true) : 0, + l: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strLeft + strMinusWidth), true) : 0 + }; + + //detect margin: + var margin = { + c: force, + t: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strTop)), + r: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strRight)), + b: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strBottom)), + l: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strLeft)) + }; + + //detect css max width & height: + var cssMaxValue = { + h: String(_hostElement.css(_strMaxMinus + _strHeight)), + w: String(_hostElement.css(_strMaxMinus + _strWidth)) + }; + + //vars to apply correct css + var contentElementCSS = {}; + var contentGlueElementCSS = {}; + + //funcs + var getHostSize = function () { + //has to be clientSize because offsetSize respect borders + return { + w: _hostElementNative[LEXICON.cW], + h: _hostElementNative[LEXICON.cH] + }; + }; + var getViewportSize = function () { + //viewport size is padding container because it never has padding, margin and a border + //determine zoom rounding error -> sometimes scrollWidth/Height is smaller than clientWidth/Height + //if this happens add the difference to the viewportSize to compensate the rounding error + return { + w: _paddingElementNative[LEXICON.oW] + MATH.max(0, _contentElementNative[LEXICON.cW] - _contentElementNative[LEXICON.sW]), + h: _paddingElementNative[LEXICON.oH] + MATH.max(0, _contentElementNative[LEXICON.cH] - _contentElementNative[LEXICON.sH]) + }; + }; + + //set info for padding + var paddingAbsoluteX = _paddingX = padding.l + padding.r; + var paddingAbsoluteY = _paddingY = padding.t + padding.b; + paddingAbsoluteX *= paddingAbsolute ? 1 : 0; + paddingAbsoluteY *= paddingAbsolute ? 1 : 0; + padding.c = checkCacheAutoForce(padding, _cssPaddingCache); + + //set info for border + _borderX = border.l + border.r; + _borderY = border.t + border.b; + border.c = checkCacheAutoForce(border, _cssBorderCache); + + //set info for margin + _marginX = margin.l + margin.r; + _marginY = margin.t + margin.b; + margin.c = checkCacheAutoForce(margin, _cssMarginCache); + + //set info for css max value + cssMaxValue.ih = parseToZeroOrNumber(cssMaxValue.h); //ih = integer height + cssMaxValue.iw = parseToZeroOrNumber(cssMaxValue.w); //iw = integer width + cssMaxValue.ch = cssMaxValue.h.indexOf('px') > -1; //ch = correct height + cssMaxValue.cw = cssMaxValue.w.indexOf('px') > -1; //cw = correct width + cssMaxValue.c = checkCacheAutoForce(cssMaxValue, _cssMaxValueCache); + + //refresh cache + _displayIsHiddenCache = displayIsHidden; + _textareaAutoWrappingCache = textareaAutoWrapping; + _cssDirectionCache = cssDirection; + _cssBoxSizingCache = boxSizing; + _widthAutoCache = widthAuto; + _heightAutoCache = heightAuto; + _cssPaddingCache = padding; + _cssBorderCache = border; + _cssMarginCache = margin; + _cssMaxValueCache = cssMaxValue; + + //IEFix direction changed + if (cssDirectionChanged && _sizeAutoObserverAdded) + _sizeAutoObserverElement.css(_strFloat, isRTLRight); + + //apply padding: + if (padding.c || cssDirectionChanged || paddingAbsoluteChanged || widthAutoChanged || heightAutoChanged || boxSizingChanged || sizeAutoCapableChanged) { + var paddingElementCSS = {}; + var textareaCSS = {}; + setTopRightBottomLeft(contentGlueElementCSS, _strMarginMinus, [-padding.t, -padding.r, -padding.b, -padding.l]); + if (paddingAbsolute) { + setTopRightBottomLeft(paddingElementCSS, _strEmpty, [padding.t, padding.r, padding.b, padding.l]); + if (_isTextarea) + setTopRightBottomLeft(textareaCSS, _strPaddingMinus); + else + setTopRightBottomLeft(contentElementCSS, _strPaddingMinus); + } + else { + setTopRightBottomLeft(paddingElementCSS, _strEmpty); + if (_isTextarea) + setTopRightBottomLeft(textareaCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); + else + setTopRightBottomLeft(contentElementCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); + } + _paddingElement.css(paddingElementCSS); + _targetElement.css(textareaCSS); + } + + //viewport size is padding container because it never has padding, margin and a border. + _viewportSize = getViewportSize(); + + //update Textarea + var textareaSize = _isTextarea ? textareaUpdate() : false; + var textareaSizeChanged = _isTextarea && checkCacheAutoForce(textareaSize, _textareaSizeCache); + var textareaDynOrigSize = _isTextarea && textareaSize ? { + w: textareaDynWidth ? textareaSize._dynamicWidth : textareaSize._originalWidth, + h: textareaDynHeight ? textareaSize._dynamicHeight : textareaSize._originalHeight + } : {}; + _textareaSizeCache = textareaSize; + + //fix height auto / width auto in cooperation with current padding & boxSizing behavior: + if (heightAuto && (heightAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c)) { + /* + if (cssMaxValue.ch) + contentElementCSS[_strMaxMinus + _strHeight] = + (cssMaxValue.ch ? (cssMaxValue.ih - paddingAbsoluteY + (_isBorderBox ? -_borderY : _paddingY)) + : _strEmpty); + */ + contentElementCSS[_strHeight] = _strAuto; + } + else if (heightAutoChanged || paddingAbsoluteChanged) { + contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; + contentElementCSS[_strHeight] = _strHundredPercent; + } + if (widthAuto && (widthAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c || cssDirectionChanged)) { + /* + if (cssMaxValue.cw) + contentElementCSS[_strMaxMinus + _strWidth] = + (cssMaxValue.cw ? (cssMaxValue.iw - paddingAbsoluteX + (_isBorderBox ? -_borderX : _paddingX)) + + (_nativeScrollbarIsOverlaid.y ? _overlayScrollbarDummySize.y : 0) + : _strEmpty); + */ + contentElementCSS[_strWidth] = _strAuto; + contentGlueElementCSS[_strMaxMinus + _strWidth] = _strHundredPercent; //IE Fix + } + else if (widthAutoChanged || paddingAbsoluteChanged) { + contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; + contentElementCSS[_strWidth] = _strHundredPercent; + contentElementCSS[_strFloat] = _strEmpty; + contentGlueElementCSS[_strMaxMinus + _strWidth] = _strEmpty; //IE Fix + } + if (widthAuto) { + if (!cssMaxValue.cw) + contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; + //textareaDynOrigSize.w || _strAuto :: doesnt works because applied margin will shift width + contentGlueElementCSS[_strWidth] = _strAuto; + + contentElementCSS[_strWidth] = _strAuto; + contentElementCSS[_strFloat] = isRTLRight; + } + else { + contentGlueElementCSS[_strWidth] = _strEmpty; + } + if (heightAuto) { + if (!cssMaxValue.ch) + contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; + //textareaDynOrigSize.h || _contentElementNative[LEXICON.cH] :: use for anti scroll jumping + contentGlueElementCSS[_strHeight] = textareaDynOrigSize.h || _contentElementNative[LEXICON.cH]; + } + else { + contentGlueElementCSS[_strHeight] = _strEmpty; + } + if (sizeAutoCapable) + _contentGlueElement.css(contentGlueElementCSS); + _contentElement.css(contentElementCSS); + + //CHECKPOINT HERE ~ + contentElementCSS = {}; + contentGlueElementCSS = {}; + + //if [content(host) client / scroll size, or target element direction, or content(host) max-sizes] changed, or force is true + if (hostSizeChanged || contentSizeChanged || textareaSizeChanged || cssDirectionChanged || boxSizingChanged || paddingAbsoluteChanged || widthAutoChanged || widthAuto || heightAutoChanged || heightAuto || cssMaxValue.c || ignoreOverlayScrollbarHidingChanged || overflowBehaviorChanged || clipAlwaysChanged || resizeChanged || scrollbarsVisibilityChanged || scrollbarsAutoHideChanged || scrollbarsDragScrollingChanged || scrollbarsClickScrollingChanged || textareaDynWidthChanged || textareaDynHeightChanged || textareaAutoWrappingChanged) { + var strOverflow = 'overflow'; + var strOverflowX = strOverflow + '-x'; + var strOverflowY = strOverflow + '-y'; + var strHidden = 'hidden'; + var strVisible = 'visible'; + + //Reset the viewport (very important for natively overlaid scrollbars and zoom change + //don't change the overflow prop as it is very expensive and affects performance !A LOT! + if(!_nativeScrollbarStyling) { + var viewportElementResetCSS = {}; + var resetXTmp = _hasOverflowCache.y && _hideOverflowCache.ys && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.y ? _viewportElement.css(isRTLLeft) : -_nativeScrollbarSize.y) : 0; + var resetBottomTmp = _hasOverflowCache.x && _hideOverflowCache.xs && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.x ? _viewportElement.css(_strBottom) : -_nativeScrollbarSize.x) : 0; + setTopRightBottomLeft(viewportElementResetCSS, _strEmpty); + _viewportElement.css(viewportElementResetCSS); + } + + //measure several sizes: + var contentMeasureElement = getContentMeasureElement(); + //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 + var contentSize = { + //use clientSize because natively overlaidScrollbars add borders + w: textareaDynOrigSize.w || contentMeasureElement[LEXICON.cW], + h: textareaDynOrigSize.h || contentMeasureElement[LEXICON.cH] + }; + var scrollSize = { + w: contentMeasureElement[LEXICON.sW], + h: contentMeasureElement[LEXICON.sH] + }; + + //apply the correct viewport style and measure viewport size + if(!_nativeScrollbarStyling) { + viewportElementResetCSS[_strBottom] = wasHeightAuto ? _strEmpty : resetBottomTmp; + viewportElementResetCSS[isRTLLeft] = wasWidthAuto ? _strEmpty : resetXTmp; + _viewportElement.css(viewportElementResetCSS); + } + _viewportSize = getViewportSize(); + + //measure and correct several sizes + var hostSize = getHostSize(); + var contentGlueSize = { + //client/scrollSize + AbsolutePadding -> because padding is only applied to the paddingElement if its absolute, so you have to add it manually + //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 + w: MATH.max((widthAuto ? contentSize.w : scrollSize.w) + paddingAbsoluteX, hostSize.w), + h: MATH.max((heightAuto ? contentSize.h : scrollSize.h) + paddingAbsoluteY, hostSize.h) + }; + contentGlueSize.c = checkCacheAutoForce(contentGlueSize, _contentGlueSizeCache); + _contentGlueSizeCache = contentGlueSize; + + //apply correct contentGlue size + if (sizeAutoCapable) { + //size contentGlue correctly to make sure the element has correct size if the sizing switches to auto + if (contentGlueSize.c || (heightAuto || widthAuto)) { + contentGlueElementCSS[_strWidth] = contentGlueSize.w; + contentGlueElementCSS[_strHeight] = contentGlueSize.h; + + //textarea-sizes are already calculated correctly at this point + if (!_isTextarea) { + contentSize = { + //use clientSize because natively overlaidScrollbars add borders + w: contentMeasureElement[LEXICON.cW], + h: contentMeasureElement[LEXICON.cH] + }; + } + } + var textareaCoverCSS = {}; + var setContentGlueElementCSSfunction = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var wh = scrollbarVars._w_h; + var strWH = scrollbarVars._width_height; + var autoSize = horizontal ? widthAuto : heightAuto; + var borderSize = horizontal ? _borderX : _borderY; + var paddingSize = horizontal ? _paddingX : _paddingY; + var marginSize = horizontal ? _marginX : _marginY; + var maxSize = contentGlueElementCSS[strWH] + (_isBorderBox ? borderSize : -paddingSize); + + //make contentGlue size -1 if element is not auto sized, to make sure that a resize event happens when the element shrinks + if (!autoSize || (!autoSize && border.c)) + contentGlueElementCSS[strWH] = hostSize[wh] - (_isBorderBox ? 0 : paddingSize + borderSize) - 1 - marginSize; + + //if size is auto and host is same size as max size, make content glue size +1 to make sure size changes will be detected + if (autoSize && cssMaxValue['c' + wh] && cssMaxValue['i' + wh] === maxSize) + contentGlueElementCSS[strWH] = maxSize + (_isBorderBox ? 0 : paddingSize) + 1; + + //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) + if (autoSize && (contentSize[wh] < _viewportSize[wh]) && (horizontal && _isTextarea ? !textareaAutoWrapping : true)) { + if (_isTextarea) + textareaCoverCSS[strWH] = parseToZeroOrNumber(_textareaCoverElement.css(strWH)) - 1; + contentGlueElementCSS[strWH] -= 1; + } + + //make sure content glue size is at least 1 + if (contentSize[wh] > 0) + contentGlueElementCSS[strWH] = MATH.max(1, contentGlueElementCSS[strWH]); + }; + setContentGlueElementCSSfunction(true); + setContentGlueElementCSSfunction(false); + + if (_isTextarea) + _textareaCoverElement.css(textareaCoverCSS); + _contentGlueElement.css(contentGlueElementCSS); + } + if (widthAuto) + contentElementCSS[_strWidth] = _strHundredPercent; + if (widthAuto && !_isBorderBox && !_mutationObserversConnected) + contentElementCSS[_strFloat] = 'none'; + + //apply and reset content style + _contentElement.css(contentElementCSS); + contentElementCSS = {}; + + //measure again, but this time all correct sizes: + var contentScrollSize = { + w: contentMeasureElement[LEXICON.sW], + h: contentMeasureElement[LEXICON.sH], + }; + contentScrollSize.c = contentSizeChanged = checkCacheAutoForce(contentScrollSize, _contentScrollSizeCache); + _contentScrollSizeCache = contentScrollSize; + + //refresh viewport size after correct measuring + _viewportSize = getViewportSize(); + + hostSize = getHostSize(); + hostSizeChanged = checkCacheAutoForce(hostSize, _hostSizeCache); + _hostSizeCache = hostSize; + + var hideOverflowForceTextarea = _isTextarea && (_viewportSize.w === 0 || _viewportSize.h === 0); + var previousOverflowAmount = _overflowAmountCache; + var overflowBehaviorIsVS = {}; + var overflowBehaviorIsVH = {}; + var overflowBehaviorIsS = {}; + var overflowAmount = {}; + var hasOverflow = {}; + var hideOverflow = {}; + var canScroll = {}; + var viewportRect = _paddingElementNative[LEXICON.bCR](); + var setOverflowVariables = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var scrollbarVarsInverted = getScrollbarVars(!horizontal); + var xyI = scrollbarVarsInverted._x_y; + var xy = scrollbarVars._x_y; + var wh = scrollbarVars._w_h; + var widthHeight = scrollbarVars._width_height; + var scrollMax = _strScroll + scrollbarVars._Left_Top + 'Max'; + var fractionalOverflowAmount = viewportRect[widthHeight] ? MATH.abs(viewportRect[widthHeight] - _viewportSize[wh]) : 0; + var checkFractionalOverflowAmount = previousOverflowAmount && previousOverflowAmount[xy] > 0 && _viewportElementNative[scrollMax] === 0; + overflowBehaviorIsVS[xy] = overflowBehavior[xy] === 'v-s'; + overflowBehaviorIsVH[xy] = overflowBehavior[xy] === 'v-h'; + overflowBehaviorIsS[xy] = overflowBehavior[xy] === 's'; + overflowAmount[xy] = MATH.max(0, MATH.round((contentScrollSize[wh] - _viewportSize[wh]) * 100) / 100); + overflowAmount[xy] *= (hideOverflowForceTextarea || (checkFractionalOverflowAmount && fractionalOverflowAmount > 0 && fractionalOverflowAmount < 1)) ? 0 : 1; + hasOverflow[xy] = overflowAmount[xy] > 0; + + //hideOverflow: + //x || y : true === overflow is hidden by "overflow: scroll" OR "overflow: hidden" + //xs || ys : true === overflow is hidden by "overflow: scroll" + hideOverflow[xy] = overflowBehaviorIsVS[xy] || overflowBehaviorIsVH[xy] ? (hasOverflow[xyI] && !overflowBehaviorIsVS[xyI] && !overflowBehaviorIsVH[xyI]) : hasOverflow[xy]; + hideOverflow[xy + 's'] = hideOverflow[xy] ? (overflowBehaviorIsS[xy] || overflowBehaviorIsVS[xy]) : false; + + canScroll[xy] = hasOverflow[xy] && hideOverflow[xy + 's']; + }; + setOverflowVariables(true); + setOverflowVariables(false); + + overflowAmount.c = checkCacheAutoForce(overflowAmount, _overflowAmountCache); + _overflowAmountCache = overflowAmount; + hasOverflow.c = checkCacheAutoForce(hasOverflow, _hasOverflowCache); + _hasOverflowCache = hasOverflow; + hideOverflow.c = checkCacheAutoForce(hideOverflow, _hideOverflowCache); + _hideOverflowCache = hideOverflow; + + //if native scrollbar is overlay at x OR y axis, prepare DOM + if (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y) { + var borderDesign = 'px solid transparent'; + var contentArrangeElementCSS = {}; + var arrangeContent = {}; + var arrangeChanged = force; + var setContentElementCSS; + + if (hasOverflow.x || hasOverflow.y) { + arrangeContent.w = _nativeScrollbarIsOverlaid.y && hasOverflow.y ? contentScrollSize.w + _overlayScrollbarDummySize.y : _strEmpty; + arrangeContent.h = _nativeScrollbarIsOverlaid.x && hasOverflow.x ? contentScrollSize.h + _overlayScrollbarDummySize.x : _strEmpty; + arrangeChanged = checkCacheAutoForce(arrangeContent, _arrangeContentSizeCache); + _arrangeContentSizeCache = arrangeContent; + } + + if (hasOverflow.c || hideOverflow.c || contentScrollSize.c || cssDirectionChanged || widthAutoChanged || heightAutoChanged || widthAuto || heightAuto || ignoreOverlayScrollbarHidingChanged) { + contentElementCSS[_strMarginMinus + isRTLRight] = contentElementCSS[_strBorderMinus + isRTLRight] = _strEmpty; + setContentElementCSS = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var scrollbarVarsInverted = getScrollbarVars(!horizontal); + var xy = scrollbarVars._x_y; + var strDirection = horizontal ? _strBottom : isRTLLeft; + var invertedAutoSize = horizontal ? heightAuto : widthAuto; + + if (_nativeScrollbarIsOverlaid[xy] && hasOverflow[xy] && hideOverflow[xy + 's']) { + contentElementCSS[_strMarginMinus + strDirection] = invertedAutoSize ? (ignoreOverlayScrollbarHiding ? _strEmpty : _overlayScrollbarDummySize[xy]) : _strEmpty; + contentElementCSS[_strBorderMinus + strDirection] = ((horizontal ? !invertedAutoSize : true) && !ignoreOverlayScrollbarHiding) ? (_overlayScrollbarDummySize[xy] + borderDesign) : _strEmpty; + } + else { + arrangeContent[scrollbarVarsInverted._w_h] = + contentElementCSS[_strMarginMinus + strDirection] = + contentElementCSS[_strBorderMinus + strDirection] = _strEmpty; + arrangeChanged = true; + } + }; + + if (_nativeScrollbarStyling) { + if (ignoreOverlayScrollbarHiding) + removeClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); + else + addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); + } + else { + setContentElementCSS(true); + setContentElementCSS(false); + } + } + if (ignoreOverlayScrollbarHiding) { + arrangeContent.w = arrangeContent.h = _strEmpty; + arrangeChanged = true; + } + if (arrangeChanged && !_nativeScrollbarStyling) { + contentArrangeElementCSS[_strWidth] = hideOverflow.y ? arrangeContent.w : _strEmpty; + contentArrangeElementCSS[_strHeight] = hideOverflow.x ? arrangeContent.h : _strEmpty; + + if (!_contentArrangeElement) { + _contentArrangeElement = FRAMEWORK(generateDiv(_classNameContentArrangeElement)); + _viewportElement.prepend(_contentArrangeElement); + } + _contentArrangeElement.css(contentArrangeElementCSS); + } + _contentElement.css(contentElementCSS); + } + + var viewportElementCSS = {}; + var paddingElementCSS = {}; + var setViewportCSS; + if (hostSizeChanged || hasOverflow.c || hideOverflow.c || contentScrollSize.c || overflowBehaviorChanged || boxSizingChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged || clipAlwaysChanged || heightAutoChanged) { + viewportElementCSS[isRTLRight] = _strEmpty; + setViewportCSS = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var scrollbarVarsInverted = getScrollbarVars(!horizontal); + var xy = scrollbarVars._x_y; + var XY = scrollbarVars._X_Y; + var strDirection = horizontal ? _strBottom : isRTLLeft; + + var reset = function () { + viewportElementCSS[strDirection] = _strEmpty; + _contentBorderSize[scrollbarVarsInverted._w_h] = 0; + }; + if (hasOverflow[xy] && hideOverflow[xy + 's']) { + viewportElementCSS[strOverflow + XY] = _strScroll; + if (ignoreOverlayScrollbarHiding || _nativeScrollbarStyling) { + reset(); + } + else { + viewportElementCSS[strDirection] = -(_nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[xy] : _nativeScrollbarSize[xy]); + _contentBorderSize[scrollbarVarsInverted._w_h] = _nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[scrollbarVarsInverted._x_y] : 0; + } + } else { + viewportElementCSS[strOverflow + XY] = _strEmpty; + reset(); + } + }; + setViewportCSS(true); + setViewportCSS(false); + + // if the scroll container is too small and if there is any overflow with no overlay scrollbar (and scrollbar styling isn't possible), + // make viewport element greater in size (Firefox hide Scrollbars fix) + // because firefox starts hiding scrollbars on too small elements + // with this behavior the overflow calculation may be incorrect or the scrollbars would appear suddenly + // https://bugzilla.mozilla.org/show_bug.cgi?id=292284 + if (!_nativeScrollbarStyling + && (_viewportSize.h < _nativeScrollbarMinSize.x || _viewportSize.w < _nativeScrollbarMinSize.y) + && ((hasOverflow.x && hideOverflow.x && !_nativeScrollbarIsOverlaid.x) || (hasOverflow.y && hideOverflow.y && !_nativeScrollbarIsOverlaid.y))) { + viewportElementCSS[_strPaddingMinus + _strTop] = _nativeScrollbarMinSize.x; + viewportElementCSS[_strMarginMinus + _strTop] = -_nativeScrollbarMinSize.x; + + viewportElementCSS[_strPaddingMinus + isRTLRight] = _nativeScrollbarMinSize.y; + viewportElementCSS[_strMarginMinus + isRTLRight] = -_nativeScrollbarMinSize.y; + } + else { + viewportElementCSS[_strPaddingMinus + _strTop] = + viewportElementCSS[_strMarginMinus + _strTop] = + viewportElementCSS[_strPaddingMinus + isRTLRight] = + viewportElementCSS[_strMarginMinus + isRTLRight] = _strEmpty; + } + viewportElementCSS[_strPaddingMinus + isRTLLeft] = + viewportElementCSS[_strMarginMinus + isRTLLeft] = _strEmpty; + + //if there is any overflow (x OR y axis) and this overflow shall be hidden, make overflow hidden, else overflow visible + if ((hasOverflow.x && hideOverflow.x) || (hasOverflow.y && hideOverflow.y) || hideOverflowForceTextarea) { + //only hide if is Textarea + if (_isTextarea && hideOverflowForceTextarea) { + paddingElementCSS[strOverflowX] = + paddingElementCSS[strOverflowY] = strHidden; + } + } + else { + if (!clipAlways || (overflowBehaviorIsVH.x || overflowBehaviorIsVS.x || overflowBehaviorIsVH.y || overflowBehaviorIsVS.y)) { + //only un-hide if Textarea + if (_isTextarea) { + paddingElementCSS[strOverflowX] = + paddingElementCSS[strOverflowY] = _strEmpty; + } + viewportElementCSS[strOverflowX] = + viewportElementCSS[strOverflowY] = strVisible; + } + } + + _paddingElement.css(paddingElementCSS); + _viewportElement.css(viewportElementCSS); + viewportElementCSS = {}; + + //force soft redraw in webkit because without the scrollbars will may appear because DOM wont be redrawn under special conditions + if ((hasOverflow.c || boxSizingChanged || widthAutoChanged || heightAutoChanged) && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { + var elementStyle = _contentElementNative[LEXICON.s]; + var dump; + elementStyle.webkitTransform = 'scale(1)'; + elementStyle.display = 'run-in'; + dump = _contentElementNative[LEXICON.oH]; + elementStyle.display = _strEmpty; //|| dump; //use dump to prevent it from deletion if minify + elementStyle.webkitTransform = _strEmpty; + } + /* + //force hard redraw in webkit if native overlaid scrollbars shall appear + if (ignoreOverlayScrollbarHidingChanged && ignoreOverlayScrollbarHiding) { + _hostElement.hide(); + var dump = _hostElementNative[LEXICON.oH]; + _hostElement.show(); + } + */ + } + + //change to direction RTL and width auto Bugfix in Webkit + //without this fix, the DOM still thinks the scrollbar is LTR and thus the content is shifted to the left + contentElementCSS = {}; + if (cssDirectionChanged || widthAutoChanged || heightAutoChanged) { + if (_isRTL && widthAuto) { + var floatTmp = _contentElement.css(_strFloat); + var posLeftWithoutFloat = MATH.round(_contentElement.css(_strFloat, _strEmpty).css(_strLeft, _strEmpty).position().left); + _contentElement.css(_strFloat, floatTmp); + var posLeftWithFloat = MATH.round(_contentElement.position().left); + + if (posLeftWithoutFloat !== posLeftWithFloat) + contentElementCSS[_strLeft] = posLeftWithoutFloat; + } + else { + contentElementCSS[_strLeft] = _strEmpty; + } + } + _contentElement.css(contentElementCSS); + + //handle scroll position + if (_isTextarea && contentSizeChanged) { + var textareaInfo = getTextareaInfo(); + if (textareaInfo) { + var textareaRowsChanged = _textareaInfoCache === undefined ? true : textareaInfo._rows !== _textareaInfoCache._rows; + var cursorRow = textareaInfo._cursorRow; + var cursorCol = textareaInfo._cursorColumn; + var widestRow = textareaInfo._widestRow; + var lastRow = textareaInfo._rows; + var lastCol = textareaInfo._columns; + var cursorPos = textareaInfo._cursorPosition; + var cursorMax = textareaInfo._cursorMax; + var cursorIsLastPosition = (cursorPos >= cursorMax && _textareaHasFocus); + var textareaScrollAmount = { + x: (!textareaAutoWrapping && (cursorCol === lastCol && cursorRow === widestRow)) ? _overflowAmountCache.x : -1, + y: (textareaAutoWrapping ? cursorIsLastPosition || textareaRowsChanged && (previousOverflowAmount ? (currScroll.y === previousOverflowAmount.y) : false) : (cursorIsLastPosition || textareaRowsChanged) && cursorRow === lastRow) ? _overflowAmountCache.y : -1 + }; + currScroll.x = textareaScrollAmount.x > -1 ? (_isRTL && _normalizeRTLCache && _rtlScrollBehavior.i ? 0 : textareaScrollAmount.x) : currScroll.x; //if inverted, scroll to 0 -> normalized this means to max scroll offset. + currScroll.y = textareaScrollAmount.y > -1 ? textareaScrollAmount.y : currScroll.y; + } + _textareaInfoCache = textareaInfo; + } + if (_isRTL && _rtlScrollBehavior.i && _nativeScrollbarIsOverlaid.y && hasOverflow.x && _normalizeRTLCache) + currScroll.x += _contentBorderSize.w || 0; + if (widthAuto) + _hostElement[_strScrollLeft](0); + if (heightAuto) + _hostElement[_strScrollTop](0); + _viewportElement[_strScrollLeft](currScroll.x)[_strScrollTop](currScroll.y); + + //scrollbars management: + var scrollbarsVisibilityVisible = scrollbarsVisibility === 'v'; + var scrollbarsVisibilityHidden = scrollbarsVisibility === 'h'; + var scrollbarsVisibilityAuto = scrollbarsVisibility === 'a'; + + var showScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, true, canScroll.x); + var showScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, true, canScroll.y); + var hideScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, false, canScroll.x); + var hideScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, false, canScroll.y); + + //manage class name which indicates scrollable overflow + if (hideOverflow.x || hideOverflow.y) + addClass(_hostElement, _classNameHostOverflow); + else + removeClass(_hostElement, _classNameHostOverflow); + if (hideOverflow.x) + addClass(_hostElement, _classNameHostOverflowX); + else + removeClass(_hostElement, _classNameHostOverflowX); + if (hideOverflow.y) + addClass(_hostElement, _classNameHostOverflowY); + else + removeClass(_hostElement, _classNameHostOverflowY); + + //add or remove rtl class name for styling purposes + if (cssDirectionChanged) { + if (_isRTL) + addClass(_hostElement, _classNameHostRTL); + else + removeClass(_hostElement, _classNameHostRTL); + } + + //manage the resize feature (CSS3 resize "polyfill" for this plugin) + if (_isBody) + addClass(_hostElement, _classNameHostResizeDisabled); + if (resizeChanged) { + removeClass(_scrollbarCornerElement, [ + _classNameScrollbarCornerResize, + _classNameScrollbarCornerResizeB, + _classNameScrollbarCornerResizeH, + _classNameScrollbarCornerResizeV].join(_strSpace)); + if (_resizeNone) { + addClass(_hostElement, _classNameHostResizeDisabled); + } + else { + removeClass(_hostElement, _classNameHostResizeDisabled); + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResize); + if (_resizeBoth) + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeB); + else if (_resizeHorizontal) + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeH); + else if (_resizeVertical) + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeV); + } + } + + //manage the scrollbars general visibility + the scrollbar interactivity (unusable class name) + if (scrollbarsVisibilityChanged || overflowBehaviorChanged || hideOverflow.c || hasOverflow.c || ignoreOverlayScrollbarHidingChanged) { + if (ignoreOverlayScrollbarHiding) { + if (ignoreOverlayScrollbarHidingChanged) { + removeClass(_hostElement, _classNameHostScrolling); + if (ignoreOverlayScrollbarHiding) { + hideScrollbarH(); + hideScrollbarV(); + } + } + } + else if (scrollbarsVisibilityAuto) { + if (canScroll.x) + showScrollbarH(); + else + hideScrollbarH(); + + if (canScroll.y) + showScrollbarV(); + else + hideScrollbarV(); + } + else if (scrollbarsVisibilityVisible) { + showScrollbarH(); + showScrollbarV(); + } + else if (scrollbarsVisibilityHidden) { + hideScrollbarH(); + hideScrollbarV(); + } + } + + //manage the scrollbars auto hide feature (auto hide them after specific actions) + if (scrollbarsAutoHideChanged || ignoreOverlayScrollbarHidingChanged) { + if (_scrollbarsAutoHideLeave || _scrollbarsAutoHideMove) { + setupHostMouseTouchEvents(true); + setupHostMouseTouchEvents(); + } + else { + setupHostMouseTouchEvents(true); + } + + if (_scrollbarsAutoHideNever) + refreshScrollbarsAutoHide(true); + else + refreshScrollbarsAutoHide(false, true); + } + + //manage scrollbars handle length & offset - don't remove! + if (hostSizeChanged || overflowAmount.c || heightAutoChanged || widthAutoChanged || resizeChanged || boxSizingChanged || paddingAbsoluteChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged) { + refreshScrollbarHandleLength(true); + refreshScrollbarHandleOffset(true); + refreshScrollbarHandleLength(false); + refreshScrollbarHandleOffset(false); + } + + //manage interactivity + if (scrollbarsClickScrollingChanged) + refreshScrollbarsInteractive(true, scrollbarsClickScrolling); + if (scrollbarsDragScrollingChanged) + refreshScrollbarsInteractive(false, scrollbarsDragScrolling); + + //callbacks: + if (cssDirectionChanged) { + dispatchCallback('onDirectionChanged', { + isRTL: _isRTL, + dir: cssDirection + }); + } + if (hostSizeChanged) { + dispatchCallback('onHostSizeChanged', { + width: _hostSizeCache.w, + height: _hostSizeCache.h + }); + } + if (contentSizeChanged) { + dispatchCallback('onContentSizeChanged', { + width: _contentScrollSizeCache.w, + height: _contentScrollSizeCache.h + }); + } + if (hasOverflow.c || hideOverflow.c) { + dispatchCallback('onOverflowChanged', { + x: hasOverflow.x, + y: hasOverflow.y, + xScrollable: hideOverflow.xs, + yScrollable: hideOverflow.ys, + clipped: hideOverflow.x || hideOverflow.y + }); + } + if (overflowAmount.c) { + dispatchCallback('onOverflowAmountChanged', { + x: overflowAmount.x, + y: overflowAmount.y + }); + } + } + + //fix body min size + if (_isBody && _bodyMinSizeCache && (_hasOverflowCache.c || _bodyMinSizeCache.c)) { + //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. + if (!_bodyMinSizeCache.f) + bodyMinSizeChanged(); + if (_nativeScrollbarIsOverlaid.y && _hasOverflowCache.x) + _contentElement.css(_strMinMinus + _strWidth, _bodyMinSizeCache.w + _overlayScrollbarDummySize.y); + if (_nativeScrollbarIsOverlaid.x && _hasOverflowCache.y) + _contentElement.css(_strMinMinus + _strHeight, _bodyMinSizeCache.h + _overlayScrollbarDummySize.x); + _bodyMinSizeCache.c = false; + } + + //freezeResizeObserver(_sizeObserverElement, false); + //freezeResizeObserver(_sizeAutoObserverElement, false); + + dispatchCallback('onUpdated', { forced: force }); + } + + + //==== Options ====// + + /** + * Sets new options but doesn't call the update method. + * @param newOptions The object which contains the new options. + * @returns {*} A object which contains the changed options. + */ + function setOptions(newOptions) { + var validatedOpts = _pluginsOptions._validate(newOptions, _pluginsOptions._template, true, _currentOptions) + + _currentOptions = extendDeep({}, _currentOptions, validatedOpts._default); + _currentPreparedOptions = extendDeep({}, _currentPreparedOptions, validatedOpts._prepared); + + return validatedOpts._prepared; + } + + + //==== Structure ====// + + /** + * Builds or destroys the wrapper and helper DOM elements. + * @param destroy Indicates whether the DOM shall be build or destroyed. + */ + function setupStructureDOM(destroy) { + var strParent = 'parent'; + var classNameResizeObserverHost = 'os-resize-observer-host'; + var classNameTextareaElementFull = _classNameTextareaElement + _strSpace + _classNameTextInherit; + var textareaClass = _isTextarea ? _strSpace + _classNameTextInherit : _strEmpty; + var adoptAttrs = _currentPreparedOptions.textarea.inheritedAttrs; + var adoptAttrsMap = {}; + var applyAdoptedAttrs = function () { + var applyAdoptedAttrsElm = destroy ? _targetElement : _hostElement; + each(adoptAttrsMap, function (key, value) { + if (type(value) == TYPES.s) { + if (key == LEXICON.c) + applyAdoptedAttrsElm.addClass(value); + else + applyAdoptedAttrsElm.attr(key, value); + } + }); + }; + var hostElementClassNames = [ + _classNameHostElement, + _classNameHostTextareaElement, + _classNameHostResizeDisabled, + _classNameHostRTL, + _classNameHostScrollbarHorizontalHidden, + _classNameHostScrollbarVerticalHidden, + _classNameHostTransition, + _classNameHostScrolling, + _classNameHostOverflow, + _classNameHostOverflowX, + _classNameHostOverflowY, + _classNameThemeNone, + _classNameTextareaElement, + _classNameTextInherit, + _classNameCache].join(_strSpace); + var hostElementCSS = {}; + + //get host element as first element, because that's the most upper element and required for the other elements + _hostElement = _hostElement || (_isTextarea ? (_domExists ? _targetElement[strParent]()[strParent]()[strParent]()[strParent]() : FRAMEWORK(generateDiv(_classNameHostTextareaElement))) : _targetElement); + _contentElement = _contentElement || selectOrGenerateDivByClass(_classNameContentElement + textareaClass); + _viewportElement = _viewportElement || selectOrGenerateDivByClass(_classNameViewportElement + textareaClass); + _paddingElement = _paddingElement || selectOrGenerateDivByClass(_classNamePaddingElement + textareaClass); + _sizeObserverElement = _sizeObserverElement || selectOrGenerateDivByClass(classNameResizeObserverHost); + _textareaCoverElement = _textareaCoverElement || (_isTextarea ? selectOrGenerateDivByClass(_classNameTextareaCoverElement) : undefined); + + //on destroy, remove all generated class names from the host element before collecting the adopted attributes + //to prevent adopting generated class names + if (destroy) + removeClass(_hostElement, hostElementClassNames); + + //collect all adopted attributes + adoptAttrs = type(adoptAttrs) == TYPES.s ? adoptAttrs.split(_strSpace) : adoptAttrs; + if (type(adoptAttrs) == TYPES.a && _isTextarea) { + each(adoptAttrs, function (i, v) { + if (type(v) == TYPES.s) { + adoptAttrsMap[v] = destroy ? _hostElement.attr(v) : _targetElement.attr(v); + } + }); + } + + if (!destroy) { + if (_isTextarea) { + if (!_currentPreparedOptions.sizeAutoCapable) { + hostElementCSS[_strWidth] = _targetElement.css(_strWidth); + hostElementCSS[_strHeight] = _targetElement.css(_strHeight); + } + + if (!_domExists) + _targetElement.addClass(_classNameTextInherit).wrap(_hostElement); + + //jQuery clones elements in wrap functions, so we have to select them again + _hostElement = _targetElement[strParent]().css(hostElementCSS); + } + + if (!_domExists) { + //add the correct class to the target element + addClass(_targetElement, _isTextarea ? classNameTextareaElementFull : _classNameHostElement); + + //wrap the content into the generated elements to create the required DOM + _hostElement.wrapInner(_contentElement) + .wrapInner(_viewportElement) + .wrapInner(_paddingElement) + .prepend(_sizeObserverElement); + + //jQuery clones elements in wrap functions, so we have to select them again + _contentElement = findFirst(_hostElement, _strDot + _classNameContentElement); + _viewportElement = findFirst(_hostElement, _strDot + _classNameViewportElement); + _paddingElement = findFirst(_hostElement, _strDot + _classNamePaddingElement); + + if (_isTextarea) { + _contentElement.prepend(_textareaCoverElement); + applyAdoptedAttrs(); + } + } + + if (_nativeScrollbarStyling) + addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); + if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y) + addClass(_viewportElement, _classNameViewportNativeScrollbarsOverlaid); + if (_isBody) + addClass(_htmlElement, _classNameHTMLElement); + + _sizeObserverElementNative = _sizeObserverElement[0]; + _hostElementNative = _hostElement[0]; + _paddingElementNative = _paddingElement[0]; + _viewportElementNative = _viewportElement[0]; + _contentElementNative = _contentElement[0]; + + updateViewportAttrsFromTarget(); + } + else { + if (_domExists && _initialized) { + //clear size observer + _sizeObserverElement.children().remove(); + + //remove the style property and classes from already generated elements + each([_paddingElement, _viewportElement, _contentElement, _textareaCoverElement], function (i, elm) { + if (elm) { + removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); + } + }); + + //add classes to the host element which was removed previously to match the expected DOM + addClass(_hostElement, _isTextarea ? _classNameHostTextareaElement : _classNameHostElement); + } + else { + //remove size observer + remove(_sizeObserverElement); + + //unwrap the content to restore DOM + _contentElement.contents() + .unwrap() + .unwrap() + .unwrap(); + + if (_isTextarea) { + _targetElement.unwrap(); + remove(_hostElement); + remove(_textareaCoverElement); + applyAdoptedAttrs(); + } + } + + if (_isTextarea) + _targetElement.removeAttr(LEXICON.s); + + if (_isBody) + removeClass(_htmlElement, _classNameHTMLElement); + } + } + + /** + * Adds or removes all wrapper elements interactivity events. + * @param destroy Indicates whether the Events shall be added or removed. + */ + function setupStructureEvents() { + var textareaKeyDownRestrictedKeyCodes = [ + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 123, //F1 to F12 + 33, 34, //page up, page down + 37, 38, 39, 40, //left, up, right, down arrows + 16, 17, 18, 19, 20, 144 //Shift, Ctrl, Alt, Pause, CapsLock, NumLock + ]; + var textareaKeyDownKeyCodesList = []; + var textareaUpdateIntervalID; + var scrollStopTimeoutId; + var scrollStopDelay = 175; + var strFocus = 'focus'; + + function updateTextarea(doClearInterval) { + textareaUpdate(); + _base.update(_strAuto); + if (doClearInterval && _autoUpdateRecommended) + clearInterval(textareaUpdateIntervalID); + } + function textareaOnScroll(event) { + _targetElement[_strScrollLeft](_rtlScrollBehavior.i && _normalizeRTLCache ? 9999999 : 0); + _targetElement[_strScrollTop](0); + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + return false; + } + function textareaOnDrop(event) { + setTimeout(function () { + if (!_destroyed) + updateTextarea(); + }, 50); + } + function textareaOnFocus() { + _textareaHasFocus = true; + addClass(_hostElement, strFocus); + } + function textareaOnFocusout() { + _textareaHasFocus = false; + textareaKeyDownKeyCodesList = []; + removeClass(_hostElement, strFocus); + updateTextarea(true); + } + function textareaOnKeyDown(event) { + var keyCode = event.keyCode; + + if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { + if (!textareaKeyDownKeyCodesList[LEXICON.l]) { + updateTextarea(); + textareaUpdateIntervalID = setInterval(updateTextarea, 1000 / 60); + } + if (inArray(keyCode, textareaKeyDownKeyCodesList) < 0) + textareaKeyDownKeyCodesList.push(keyCode); + } + } + function textareaOnKeyUp(event) { + var keyCode = event.keyCode; + var index = inArray(keyCode, textareaKeyDownKeyCodesList); + + if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { + if (index > -1) + textareaKeyDownKeyCodesList.splice(index, 1); + if (!textareaKeyDownKeyCodesList[LEXICON.l]) + updateTextarea(true); + } + } + function contentOnTransitionEnd(event) { + if (_autoUpdateCache === true) + return; + event = event.originalEvent || event; + if (isSizeAffectingCSSProperty(event.propertyName)) + _base.update(_strAuto); + } + function viewportOnScroll(event) { + if (!_sleeping) { + if (scrollStopTimeoutId !== undefined) + clearTimeout(scrollStopTimeoutId); + else { + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(true); + + if (!nativeOverlayScrollbarsAreActive()) + addClass(_hostElement, _classNameHostScrolling); + + dispatchCallback('onScrollStart', event); + } + + //if a scrollbars handle gets dragged, the mousemove event is responsible for refreshing the handle offset + //because if CSS scroll-snap is used, the handle offset gets only refreshed on every snap point + //this looks laggy & clunky, it looks much better if the offset refreshes with the mousemove + if (!_scrollbarsHandlesDefineScrollPos) { + refreshScrollbarHandleOffset(true); + refreshScrollbarHandleOffset(false); + } + dispatchCallback('onScroll', event); + + scrollStopTimeoutId = setTimeout(function () { + if (!_destroyed) { + //OnScrollStop: + clearTimeout(scrollStopTimeoutId); + scrollStopTimeoutId = undefined; + + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(false); + + if (!nativeOverlayScrollbarsAreActive()) + removeClass(_hostElement, _classNameHostScrolling); + + dispatchCallback('onScrollStop', event); + } + }, scrollStopDelay); + } + } + + + if (_isTextarea) { + if (_msieVersion > 9 || !_autoUpdateRecommended) { + addDestroyEventListener(_targetElement, 'input', updateTextarea); + } + else { + addDestroyEventListener(_targetElement, + [_strKeyDownEvent, _strKeyUpEvent], + [textareaOnKeyDown, textareaOnKeyUp]); + } + + addDestroyEventListener(_targetElement, + [_strScroll, 'drop', strFocus, strFocus + 'out'], + [textareaOnScroll, textareaOnDrop, textareaOnFocus, textareaOnFocusout]); + } + else { + addDestroyEventListener(_contentElement, _strTransitionEndEvent, contentOnTransitionEnd); + } + addDestroyEventListener(_viewportElement, _strScroll, viewportOnScroll, true); + } + + + //==== Scrollbars ====// + + /** + * Builds or destroys all scrollbar DOM elements (scrollbar, track, handle) + * @param destroy Indicates whether the DOM shall be build or destroyed. + */ + function setupScrollbarsDOM(destroy) { + var selectOrGenerateScrollbarDOM = function (isHorizontal) { + var scrollbarClassName = isHorizontal ? _classNameScrollbarHorizontal : _classNameScrollbarVertical; + var scrollbar = selectOrGenerateDivByClass(_classNameScrollbar + _strSpace + scrollbarClassName, true); + var track = selectOrGenerateDivByClass(_classNameScrollbarTrack, scrollbar); + var handle = selectOrGenerateDivByClass(_classNameScrollbarHandle, scrollbar); + + if (!_domExists && !destroy) { + scrollbar.append(track); + track.append(handle); + } + + return { + _scrollbar: scrollbar, + _track: track, + _handle: handle + }; + }; + function resetScrollbarDOM(isHorizontal) { + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbar = scrollbarVars._scrollbar; + var track = scrollbarVars._track; + var handle = scrollbarVars._handle; + + if (_domExists && _initialized) { + each([scrollbar, track, handle], function (i, elm) { + removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); + }); + } + else { + remove(scrollbar || selectOrGenerateScrollbarDOM(isHorizontal)._scrollbar); + } + } + var horizontalElements; + var verticalElements; + + if (!destroy) { + horizontalElements = selectOrGenerateScrollbarDOM(true); + verticalElements = selectOrGenerateScrollbarDOM(); + + _scrollbarHorizontalElement = horizontalElements._scrollbar; + _scrollbarHorizontalTrackElement = horizontalElements._track; + _scrollbarHorizontalHandleElement = horizontalElements._handle; + _scrollbarVerticalElement = verticalElements._scrollbar; + _scrollbarVerticalTrackElement = verticalElements._track; + _scrollbarVerticalHandleElement = verticalElements._handle; + + if (!_domExists) { + _paddingElement.after(_scrollbarVerticalElement); + _paddingElement.after(_scrollbarHorizontalElement); + } + } + else { + resetScrollbarDOM(true); + resetScrollbarDOM(); + } + } + + /** + * Initializes all scrollbar interactivity events. (track and handle dragging, clicking, scrolling) + * @param isHorizontal True if the target scrollbar is the horizontal scrollbar, false if the target scrollbar is the vertical scrollbar. + */ + function setupScrollbarEvents(isHorizontal) { + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbarVarsInfo = scrollbarVars._info; + var insideIFrame = _windowElementNative.top !== _windowElementNative; + var xy = scrollbarVars._x_y; + var XY = scrollbarVars._X_Y; + var scroll = _strScroll + scrollbarVars._Left_Top; + var strActive = 'active'; + var strSnapHandle = 'snapHandle'; + var scrollDurationFactor = 1; + var increaseDecreaseScrollAmountKeyCodes = [16, 17]; //shift, ctrl + var trackTimeout; + var mouseDownScroll; + var mouseDownOffset; + var mouseDownInvertedScale; + + function getPointerPosition(event) { + return _msieVersion && insideIFrame ? event['screen' + XY] : COMPATIBILITY.page(event)[xy]; //use screen coordinates in EDGE & IE because the page values are incorrect in frames. + } + function getPreparedScrollbarsOption(name) { + return _currentPreparedOptions.scrollbars[name]; + } + function increaseTrackScrollAmount() { + scrollDurationFactor = 0.5; + } + function decreaseTrackScrollAmount() { + scrollDurationFactor = 1; + } + function documentKeyDown(event) { + if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) + increaseTrackScrollAmount(); + } + function documentKeyUp(event) { + if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) + decreaseTrackScrollAmount(); + } + function onMouseTouchDownContinue(event) { + var originalEvent = event.originalEvent || event; + var isTouchEvent = originalEvent.touches !== undefined; + return _sleeping || _destroyed || nativeOverlayScrollbarsAreActive() || !_scrollbarsDragScrollingCache || (isTouchEvent && !getPreparedScrollbarsOption('touchSupport')) ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; + } + function documentDragMove(event) { + if (onMouseTouchDownContinue(event)) { + var trackLength = scrollbarVarsInfo._trackLength; + var handleLength = scrollbarVarsInfo._handleLength; + var scrollRange = scrollbarVarsInfo._maxScroll; + var scrollRaw = (getPointerPosition(event) - mouseDownOffset) * mouseDownInvertedScale; + var scrollDeltaPercent = scrollRaw / (trackLength - handleLength); + var scrollDelta = (scrollRange * scrollDeltaPercent); + scrollDelta = isFinite(scrollDelta) ? scrollDelta : 0; + if (_isRTL && isHorizontal && !_rtlScrollBehavior.i) + scrollDelta *= -1; + + _viewportElement[scroll](MATH.round(mouseDownScroll + scrollDelta)); + + if (_scrollbarsHandlesDefineScrollPos) + refreshScrollbarHandleOffset(isHorizontal, mouseDownScroll + scrollDelta); + + if (!_supportPassiveEvents) + COMPATIBILITY.prvD(event); + } + else + documentMouseTouchUp(event); + } + function documentMouseTouchUp(event) { + event = event || event.originalEvent; + + setupResponsiveEventListener(_documentElement, + [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], + [documentDragMove, documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart], + true); + + if (_scrollbarsHandlesDefineScrollPos) + refreshScrollbarHandleOffset(isHorizontal, true); + + _scrollbarsHandlesDefineScrollPos = false; + removeClass(_bodyElement, _classNameDragging); + removeClass(scrollbarVars._handle, strActive); + removeClass(scrollbarVars._track, strActive); + removeClass(scrollbarVars._scrollbar, strActive); + + mouseDownScroll = undefined; + mouseDownOffset = undefined; + mouseDownInvertedScale = 1; + + decreaseTrackScrollAmount(); + + if (trackTimeout !== undefined) { + _base.scrollStop(); + clearTimeout(trackTimeout); + trackTimeout = undefined; + } + + if (event) { + var rect = _hostElementNative[LEXICON.bCR](); + var mouseInsideHost = event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom; + + //if mouse is outside host element + if (!mouseInsideHost) + hostOnMouseLeave(); + + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(false); + } + } + function onHandleMouseTouchDown(event) { + if (onMouseTouchDownContinue(event)) + onHandleMouseTouchDownAction(event); + } + function onHandleMouseTouchDownAction(event) { + mouseDownScroll = _viewportElement[scroll](); + mouseDownScroll = isNaN(mouseDownScroll) ? 0 : mouseDownScroll; + if (_isRTL && isHorizontal && !_rtlScrollBehavior.n || !_isRTL) + mouseDownScroll = mouseDownScroll < 0 ? 0 : mouseDownScroll; + + mouseDownInvertedScale = getHostElementInvertedScale()[xy]; + mouseDownOffset = getPointerPosition(event); + + _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); + addClass(_bodyElement, _classNameDragging); + addClass(scrollbarVars._handle, strActive); + addClass(scrollbarVars._scrollbar, strActive); + + setupResponsiveEventListener(_documentElement, + [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strSelectStartEvent], + [documentDragMove, documentMouseTouchUp, documentOnSelectStart]); + + if (_msieVersion || !_documentMixed) + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + function onTrackMouseTouchDown(event) { + if (onMouseTouchDownContinue(event)) { + var scrollDistance = MATH.round(_viewportSize[scrollbarVars._w_h]); + var trackOffset = scrollbarVars._track.offset()[scrollbarVars._left_top]; + var ctrlKey = event.ctrlKey; + var instantScroll = event.shiftKey; + var instantScrollTransition = instantScroll && ctrlKey; + var isFirstIteration = true; + var easing = 'linear'; + var decreaseScroll; + var finishedCondition; + var scrollActionFinsished = function (transition) { + if (_scrollbarsHandlesDefineScrollPos) + refreshScrollbarHandleOffset(isHorizontal, transition); + }; + var scrollActionInstantFinished = function () { + scrollActionFinsished(); + onHandleMouseTouchDownAction(event); + }; + var scrollAction = function () { + if (!_destroyed) { + var mouseOffset = (mouseDownOffset - trackOffset) * mouseDownInvertedScale; + var handleOffset = scrollbarVarsInfo._handleOffset; + var trackLength = scrollbarVarsInfo._trackLength; + var handleLength = scrollbarVarsInfo._handleLength; + var scrollRange = scrollbarVarsInfo._maxScroll; + var currScroll = scrollbarVarsInfo._currentScroll; + var scrollDuration = 270 * scrollDurationFactor; + var timeoutDelay = isFirstIteration ? MATH.max(400, scrollDuration) : scrollDuration; + var instantScrollPosition = scrollRange * ((mouseOffset - (handleLength / 2)) / (trackLength - handleLength)); // 100% * positionPercent + var rtlIsNormal = _isRTL && isHorizontal && ((!_rtlScrollBehavior.i && !_rtlScrollBehavior.n) || _normalizeRTLCache); + var decreaseScrollCondition = rtlIsNormal ? handleOffset < mouseOffset : handleOffset > mouseOffset; + var scrollObj = {}; + var animationObj = { + easing: easing, + step: function (now) { + if (_scrollbarsHandlesDefineScrollPos) { + _viewportElement[scroll](now); //https://github.com/jquery/jquery/issues/4340 + refreshScrollbarHandleOffset(isHorizontal, now); + } + } + }; + instantScrollPosition = isFinite(instantScrollPosition) ? instantScrollPosition : 0; + instantScrollPosition = _isRTL && isHorizontal && !_rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; + + //_base.scrollStop(); + + if (instantScroll) { + _viewportElement[scroll](instantScrollPosition); //scroll instantly to new position + if (instantScrollTransition) { + //get the scroll position after instant scroll (in case CSS Snap Points are used) to get the correct snapped scroll position + //and the animation stops at the correct point + instantScrollPosition = _viewportElement[scroll](); + //scroll back to the position before instant scrolling so animation can be performed + _viewportElement[scroll](currScroll); + + instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; + instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.n ? -instantScrollPosition : instantScrollPosition; + + scrollObj[xy] = instantScrollPosition; + _base.scroll(scrollObj, extendDeep(animationObj, { + duration: 130, + complete: scrollActionInstantFinished + })); + } + else + scrollActionInstantFinished(); + } + else { + decreaseScroll = isFirstIteration ? decreaseScrollCondition : decreaseScroll; + finishedCondition = rtlIsNormal + ? (decreaseScroll ? handleOffset + handleLength >= mouseOffset : handleOffset <= mouseOffset) + : (decreaseScroll ? handleOffset <= mouseOffset : handleOffset + handleLength >= mouseOffset); + + if (finishedCondition) { + clearTimeout(trackTimeout); + _base.scrollStop(); + trackTimeout = undefined; + scrollActionFinsished(true); + } + else { + trackTimeout = setTimeout(scrollAction, timeoutDelay); + + scrollObj[xy] = (decreaseScroll ? '-=' : '+=') + scrollDistance; + _base.scroll(scrollObj, extendDeep(animationObj, { + duration: scrollDuration + })); + } + isFirstIteration = false; + } + } + }; + if (ctrlKey) + increaseTrackScrollAmount(); + + mouseDownInvertedScale = getHostElementInvertedScale()[xy]; + mouseDownOffset = COMPATIBILITY.page(event)[xy]; + + _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); + addClass(_bodyElement, _classNameDragging); + addClass(scrollbarVars._track, strActive); + addClass(scrollbarVars._scrollbar, strActive); + + setupResponsiveEventListener(_documentElement, + [_strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], + [documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart]); + + scrollAction(); + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + } + function onTrackMouseTouchEnter(event) { + //make sure both scrollbars will stay visible if one scrollbar is hovered if autoHide is "scroll" or "move". + _scrollbarsHandleHovered = true; + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(true); + } + function onTrackMouseTouchLeave(event) { + _scrollbarsHandleHovered = false; + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(false); + } + function onScrollbarMouseTouchDown(event) { + COMPATIBILITY.stpP(event); + } + + addDestroyEventListener(scrollbarVars._handle, + _strMouseTouchDownEvent, + onHandleMouseTouchDown); + addDestroyEventListener(scrollbarVars._track, + [_strMouseTouchDownEvent, _strMouseTouchEnter, _strMouseTouchLeave], + [onTrackMouseTouchDown, onTrackMouseTouchEnter, onTrackMouseTouchLeave]); + addDestroyEventListener(scrollbarVars._scrollbar, + _strMouseTouchDownEvent, + onScrollbarMouseTouchDown); + + if (_supportTransition) { + addDestroyEventListener(scrollbarVars._scrollbar, _strTransitionEndEvent, function (event) { + if (event.target !== scrollbarVars._scrollbar[0]) + return; + refreshScrollbarHandleLength(isHorizontal); + refreshScrollbarHandleOffset(isHorizontal); + }); + } + } + + /** + * Shows or hides the given scrollbar and applied a class name which indicates if the scrollbar is scrollable or not. + * @param isHorizontal True if the horizontal scrollbar is the target, false if the vertical scrollbar is the target. + * @param shallBeVisible True if the scrollbar shall be shown, false if hidden. + * @param canScroll True if the scrollbar is scrollable, false otherwise. + */ + function refreshScrollbarAppearance(isHorizontal, shallBeVisible, canScroll) { + var scrollbarClassName = isHorizontal ? _classNameHostScrollbarHorizontalHidden : _classNameHostScrollbarVerticalHidden; + var scrollbarElement = isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement; + + if (shallBeVisible) + removeClass(_hostElement, scrollbarClassName); + else + addClass(_hostElement, scrollbarClassName); + + if (canScroll) + removeClass(scrollbarElement, _classNameScrollbarUnusable); + else + addClass(scrollbarElement, _classNameScrollbarUnusable); + } + + /** + * Autoshows / autohides both scrollbars with. + * @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. + * @param delayfree True if the scrollbars shall be hidden without a delay, false or undefined otherwise. + */ + function refreshScrollbarsAutoHide(shallBeVisible, delayfree) { + clearTimeout(_scrollbarsAutoHideTimeoutId); + if (shallBeVisible) { + //if(_hasOverflowCache.x && _hideOverflowCache.xs) + removeClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); + //if(_hasOverflowCache.y && _hideOverflowCache.ys) + removeClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); + } + else { + var anyActive; + var strActive = 'active'; + var hide = function () { + if (!_scrollbarsHandleHovered && !_destroyed) { + anyActive = _scrollbarHorizontalHandleElement.hasClass(strActive) || _scrollbarVerticalHandleElement.hasClass(strActive); + if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) + addClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); + if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) + addClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); + } + }; + if (_scrollbarsAutoHideDelay > 0 && delayfree !== true) + _scrollbarsAutoHideTimeoutId = setTimeout(hide, _scrollbarsAutoHideDelay); + else + hide(); + } + } + + /** + * Refreshes the handle length of the given scrollbar. + * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. + */ + function refreshScrollbarHandleLength(isHorizontal) { + var handleCSS = {}; + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbarVarsInfo = scrollbarVars._info; + var digit = 1000000; + //get and apply intended handle length + var handleRatio = MATH.min(1, (_hostSizeCache[scrollbarVars._w_h] - (_paddingAbsoluteCache ? (isHorizontal ? _paddingX : _paddingY) : 0)) / _contentScrollSizeCache[scrollbarVars._w_h]); + handleCSS[scrollbarVars._width_height] = (MATH.floor(handleRatio * 100 * digit) / digit) + '%'; //the last * digit / digit is for flooring to the 4th digit + + if (!nativeOverlayScrollbarsAreActive()) + scrollbarVars._handle.css(handleCSS); + + //measure the handle length to respect min & max length + scrollbarVarsInfo._handleLength = scrollbarVars._handle[0]['offset' + scrollbarVars._Width_Height]; + scrollbarVarsInfo._handleLengthRatio = handleRatio; + } + + /** + * Refreshes the handle offset of the given scrollbar. + * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. + * @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) + */ + function refreshScrollbarHandleOffset(isHorizontal, scrollOrTransition) { + var transition = type(scrollOrTransition) == TYPES.b; + var transitionDuration = 250; + var isRTLisHorizontal = _isRTL && isHorizontal; + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbarVarsInfo = scrollbarVars._info; + var strTranslateBrace = 'translate('; + var strTransform = VENDORS._cssProperty('transform'); + var strTransition = VENDORS._cssProperty('transition'); + var nativeScroll = isHorizontal ? _viewportElement[_strScrollLeft]() : _viewportElement[_strScrollTop](); + var currentScroll = scrollOrTransition === undefined || transition ? nativeScroll : scrollOrTransition; + + //measure the handle length to respect min & max length + var handleLength = scrollbarVarsInfo._handleLength; + var trackLength = scrollbarVars._track[0]['offset' + scrollbarVars._Width_Height]; + var handleTrackDiff = trackLength - handleLength; + var handleCSS = {}; + var transformOffset; + var translateValue; + + //DONT use the variable '_contentScrollSizeCache[scrollbarVars._w_h]' instead of '_viewportElement[0]['scroll' + scrollbarVars._Width_Height]' + // because its a bit behind during the small delay when content size updates + //(delay = mutationObserverContentLag, if its 0 then this var could be used) + var maxScroll = (_viewportElementNative[_strScroll + scrollbarVars._Width_Height] - _viewportElementNative['client' + scrollbarVars._Width_Height]) * (_rtlScrollBehavior.n && isRTLisHorizontal ? -1 : 1); //* -1 if rtl scroll max is negative + var getScrollRatio = function (base) { + return isNaN(base / maxScroll) ? 0 : MATH.max(0, MATH.min(1, base / maxScroll)); + }; + var getHandleOffset = function (scrollRatio) { + var offset = handleTrackDiff * scrollRatio; + offset = isNaN(offset) ? 0 : offset; + offset = (isRTLisHorizontal && !_rtlScrollBehavior.i) ? (trackLength - handleLength - offset) : offset; + offset = MATH.max(0, offset); + return offset; + }; + var scrollRatio = getScrollRatio(nativeScroll); + var unsnappedScrollRatio = getScrollRatio(currentScroll); + var handleOffset = getHandleOffset(unsnappedScrollRatio); + var snappedHandleOffset = getHandleOffset(scrollRatio); + + scrollbarVarsInfo._maxScroll = maxScroll; + scrollbarVarsInfo._currentScroll = nativeScroll; + scrollbarVarsInfo._currentScrollRatio = scrollRatio; + + if (_supportTransform) { + transformOffset = isRTLisHorizontal ? -(trackLength - handleLength - handleOffset) : handleOffset; //in px + //transformOffset = (transformOffset / trackLength * 100) * (trackLength / handleLength); //in % + translateValue = isHorizontal ? strTranslateBrace + transformOffset + 'px, 0)' : strTranslateBrace + '0, ' + transformOffset + 'px)'; + + handleCSS[strTransform] = translateValue; + + //apply or clear up transition + if (_supportTransition) + handleCSS[strTransition] = transition && MATH.abs(handleOffset - scrollbarVarsInfo._handleOffset) > 1 ? getCSSTransitionString(scrollbarVars._handle) + ', ' + (strTransform + _strSpace + transitionDuration + 'ms') : _strEmpty; + } + else + handleCSS[scrollbarVars._left_top] = handleOffset; + + + //only apply css if offset has changed and overflow exists. + if (!nativeOverlayScrollbarsAreActive()) { + scrollbarVars._handle.css(handleCSS); + + //clear up transition + if (_supportTransform && _supportTransition && transition) { + scrollbarVars._handle.one(_strTransitionEndEvent, function () { + if (!_destroyed) + scrollbarVars._handle.css(strTransition, _strEmpty); + }); + } + } + + scrollbarVarsInfo._handleOffset = handleOffset; + scrollbarVarsInfo._snappedHandleOffset = snappedHandleOffset; + scrollbarVarsInfo._trackLength = trackLength; + } + + /** + * Refreshes the interactivity of the given scrollbar element. + * @param isTrack True if the track element is the target, false if the handle element is the target. + * @param value True for interactivity false for no interactivity. + */ + function refreshScrollbarsInteractive(isTrack, value) { + var action = value ? 'removeClass' : 'addClass'; + var element1 = isTrack ? _scrollbarHorizontalTrackElement : _scrollbarHorizontalHandleElement; + var element2 = isTrack ? _scrollbarVerticalTrackElement : _scrollbarVerticalHandleElement; + var className = isTrack ? _classNameScrollbarTrackOff : _classNameScrollbarHandleOff; + + element1[action](className); + element2[action](className); + } + + /** + * Returns a object which is used for fast access for specific variables. + * @param isHorizontal True if the horizontal scrollbar vars shall be accessed, false if the vertical scrollbar vars shall be accessed. + * @returns {{wh: string, WH: string, lt: string, _wh: string, _lt: string, t: *, h: *, c: {}, s: *}} + */ + function getScrollbarVars(isHorizontal) { + return { + _width_height: isHorizontal ? _strWidth : _strHeight, + _Width_Height: isHorizontal ? 'Width' : 'Height', + _left_top: isHorizontal ? _strLeft : _strTop, + _Left_Top: isHorizontal ? 'Left' : 'Top', + _x_y: isHorizontal ? _strX : _strY, + _X_Y: isHorizontal ? 'X' : 'Y', + _w_h: isHorizontal ? 'w' : 'h', + _l_t: isHorizontal ? 'l' : 't', + _track: isHorizontal ? _scrollbarHorizontalTrackElement : _scrollbarVerticalTrackElement, + _handle: isHorizontal ? _scrollbarHorizontalHandleElement : _scrollbarVerticalHandleElement, + _scrollbar: isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement, + _info: isHorizontal ? _scrollHorizontalInfo : _scrollVerticalInfo + }; + } + + + //==== Scrollbar Corner ====// + + /** + * Builds or destroys the scrollbar corner DOM element. + * @param destroy Indicates whether the DOM shall be build or destroyed. + */ + function setupScrollbarCornerDOM(destroy) { + _scrollbarCornerElement = _scrollbarCornerElement || selectOrGenerateDivByClass(_classNameScrollbarCorner, true); + + if (!destroy) { + if (!_domExists) { + _hostElement.append(_scrollbarCornerElement); + } + } + else { + if (_domExists && _initialized) { + removeClass(_scrollbarCornerElement.removeAttr(LEXICON.s), _classNamesDynamicDestroy); + } + else { + remove(_scrollbarCornerElement); + } + } + } + + /** + * Initializes all scrollbar corner interactivity events. + */ + function setupScrollbarCornerEvents() { + var insideIFrame = _windowElementNative.top !== _windowElementNative; + var mouseDownPosition = {}; + var mouseDownSize = {}; + var mouseDownInvertedScale = {}; + var reconnectMutationObserver; + + function documentDragMove(event) { + if (onMouseTouchDownContinue(event)) { + var pageOffset = getCoordinates(event); + var hostElementCSS = {}; + if (_resizeHorizontal || _resizeBoth) + hostElementCSS[_strWidth] = (mouseDownSize.w + (pageOffset.x - mouseDownPosition.x) * mouseDownInvertedScale.x); + if (_resizeVertical || _resizeBoth) + hostElementCSS[_strHeight] = (mouseDownSize.h + (pageOffset.y - mouseDownPosition.y) * mouseDownInvertedScale.y); + _hostElement.css(hostElementCSS); + COMPATIBILITY.stpP(event); + } + else { + documentMouseTouchUp(event); + } + } + function documentMouseTouchUp(event) { + var eventIsTrusted = event !== undefined; + + setupResponsiveEventListener(_documentElement, + [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], + [documentOnSelectStart, documentDragMove, documentMouseTouchUp], + true); + + removeClass(_bodyElement, _classNameDragging); + if (_scrollbarCornerElement.releaseCapture) + _scrollbarCornerElement.releaseCapture(); + + if (eventIsTrusted) { + if (reconnectMutationObserver) + connectMutationObservers(); + _base.update(_strAuto); + } + reconnectMutationObserver = false; + } + function onMouseTouchDownContinue(event) { + var originalEvent = event.originalEvent || event; + var isTouchEvent = originalEvent.touches !== undefined; + return _sleeping || _destroyed ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; + } + function getCoordinates(event) { + return _msieVersion && insideIFrame ? { x: event.screenX, y: event.screenY } : COMPATIBILITY.page(event); + } + + addDestroyEventListener(_scrollbarCornerElement, _strMouseTouchDownEvent, function (event) { + if (onMouseTouchDownContinue(event) && !_resizeNone) { + if (_mutationObserversConnected) { + reconnectMutationObserver = true; + disconnectMutationObservers(); + } + + mouseDownPosition = getCoordinates(event); + + mouseDownSize.w = _hostElementNative[LEXICON.oW] - (!_isBorderBox ? _paddingX : 0); + mouseDownSize.h = _hostElementNative[LEXICON.oH] - (!_isBorderBox ? _paddingY : 0); + mouseDownInvertedScale = getHostElementInvertedScale(); + + setupResponsiveEventListener(_documentElement, + [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], + [documentOnSelectStart, documentDragMove, documentMouseTouchUp]); + + addClass(_bodyElement, _classNameDragging); + if (_scrollbarCornerElement.setCapture) + _scrollbarCornerElement.setCapture(); + + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + }); + } + + + //==== Utils ====// + + /** + * Calls the callback with the given name. The Context of this callback is always _base (this). + * @param name The name of the target which shall be called. + * @param args The args with which the callback shall be called. + */ + function dispatchCallback(name, args) { + if (_initialized) { + var callback = _currentPreparedOptions.callbacks[name]; + var extensionOnName = name; + var ext; + + if (extensionOnName.substr(0, 2) === 'on') + extensionOnName = extensionOnName.substr(2, 1).toLowerCase() + extensionOnName.substr(3); + + if (type(callback) == TYPES.f) + callback.call(_base, args); + + each(_extensions, function () { + ext = this; + if (type(ext.on) == TYPES.f) + ext.on(extensionOnName, args); + }); + } + else if (!_destroyed) + _callbacksInitQeueue.push({ n: name, a: args }); + } + + /** + * Sets the "top, right, bottom, left" properties, with a given prefix, of the given css object. + * @param targetCSSObject The css object to which the values shall be applied. + * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix) + * @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]. + * If this argument is undefined the value '' (empty string) will be applied to all properties. + */ + function setTopRightBottomLeft(targetCSSObject, prefix, values) { + if (values === undefined) + values = [_strEmpty, _strEmpty, _strEmpty, _strEmpty]; + + targetCSSObject[prefix + _strTop] = values[0]; + targetCSSObject[prefix + _strRight] = values[1]; + targetCSSObject[prefix + _strBottom] = values[2]; + targetCSSObject[prefix + _strLeft] = values[3]; + } + + /** + * Returns the computed CSS transition string from the given element. + * @param element The element from which the transition string shall be returned. + * @returns {string} The CSS transition string from the given element. + */ + function getCSSTransitionString(element) { + var transitionStr = VENDORS._cssProperty('transition'); + var assembledValue = element.css(transitionStr); + if (assembledValue) + return assembledValue; + var regExpString = '\\s*(' + '([^,(]+(\\(.+?\\))?)+' + ')[\\s,]*'; + var regExpMain = new RegExp(regExpString); + var regExpValidate = new RegExp('^(' + regExpString + ')+$'); + var properties = 'property duration timing-function delay'.split(' '); + var result = []; + var strResult; + var valueArray; + var i = 0; + var j; + var splitCssStyleByComma = function (str) { + strResult = []; + if (!str.match(regExpValidate)) + return str; + while (str.match(regExpMain)) { + strResult.push(RegExp.$1); + str = str.replace(regExpMain, _strEmpty); + } + + return strResult; + }; + for (; i < properties[LEXICON.l]; i++) { + valueArray = splitCssStyleByComma(element.css(transitionStr + '-' + properties[i])); + for (j = 0; j < valueArray[LEXICON.l]; j++) + result[j] = (result[j] ? result[j] + _strSpace : _strEmpty) + valueArray[j]; + } + return result.join(', '); + } + + /** + * Calculates the host-elements inverted scale. (invertedScale = 1 / scale) + * @returns {{x: number, y: number}} The scale of the host-element. + */ + function getHostElementInvertedScale() { + var rect = _paddingElementNative[LEXICON.bCR](); + return { + x: _supportTransform ? 1 / (MATH.round(rect.width) / _paddingElementNative[LEXICON.oW]) || 1 : 1, + y: _supportTransform ? 1 / (MATH.round(rect.height) / _paddingElementNative[LEXICON.oH]) || 1 : 1 + }; + } + + /** + * Checks whether the given object is a HTMLElement. + * @param o The object which shall be checked. + * @returns {boolean} True the given object is a HTMLElement, false otherwise. + */ + function isHTMLElement(o) { + var strOwnerDocument = 'ownerDocument'; + var strHTMLElement = 'HTMLElement'; + var wnd = o && o[strOwnerDocument] ? (o[strOwnerDocument].parentWindow || window) : window; + return ( + typeof wnd[strHTMLElement] == TYPES.o ? o instanceof wnd[strHTMLElement] : //DOM2 + o && typeof o == TYPES.o && o !== null && o.nodeType === 1 && typeof o.nodeName == TYPES.s + ); + } + + /** + * Compares 2 arrays and returns the differences between them as a array. + * @param a1 The first array which shall be compared. + * @param a2 The second array which shall be compared. + * @returns {Array} The differences between the two arrays. + */ + function getArrayDifferences(a1, a2) { + var a = []; + var diff = []; + var i; + var k; + for (i = 0; i < a1.length; i++) + a[a1[i]] = true; + for (i = 0; i < a2.length; i++) { + if (a[a2[i]]) + delete a[a2[i]]; + else + a[a2[i]] = true; + } + for (k in a) + diff.push(k); + return diff; + } + + /** + * Returns Zero or the number to which the value can be parsed. + * @param value The value which shall be parsed. + * @param toFloat Indicates whether the number shall be parsed to a float. + */ + function parseToZeroOrNumber(value, toFloat) { + var num = toFloat ? parseFloat(value) : parseInt(value, 10); + return isNaN(num) ? 0 : num; + } + + /** + * Gets several information of the textarea and returns them as a object or undefined if the browser doesn't support it. + * @returns {{cursorRow: Number, cursorCol, rows: Number, cols: number, wRow: number, pos: number, max : number}} or undefined if not supported. + */ + function getTextareaInfo() { + //read needed values + var textareaCursorPosition = _targetElementNative.selectionStart; + if (textareaCursorPosition === undefined) + return; + + var textareaValue = _targetElement.val(); + var textareaLength = textareaValue[LEXICON.l]; + var textareaRowSplit = textareaValue.split('\n'); + var textareaLastRow = textareaRowSplit[LEXICON.l]; + var textareaCurrentCursorRowSplit = textareaValue.substr(0, textareaCursorPosition).split('\n'); + var widestRow = 0; + var textareaLastCol = 0; + var cursorRow = textareaCurrentCursorRowSplit[LEXICON.l]; + var cursorCol = textareaCurrentCursorRowSplit[textareaCurrentCursorRowSplit[LEXICON.l] - 1][LEXICON.l]; + var rowCols; + var i; + + //get widest Row and the last column of the textarea + for (i = 0; i < textareaRowSplit[LEXICON.l]; i++) { + rowCols = textareaRowSplit[i][LEXICON.l]; + if (rowCols > textareaLastCol) { + widestRow = i + 1; + textareaLastCol = rowCols; + } + } + + return { + _cursorRow: cursorRow, //cursorRow + _cursorColumn: cursorCol, //cursorCol + _rows: textareaLastRow, //rows + _columns: textareaLastCol, //cols + _widestRow: widestRow, //wRow + _cursorPosition: textareaCursorPosition, //pos + _cursorMax: textareaLength //max + }; + } + + /** + * Determines whether native overlay scrollbars are active. + * @returns {boolean} True if native overlay scrollbars are active, false otherwise. + */ + function nativeOverlayScrollbarsAreActive() { + return (_ignoreOverlayScrollbarHidingCache && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)); + } + + /** + * Gets the element which is used to measure the content size. + * @returns {*} TextareaCover if target element is textarea else the ContentElement. + */ + function getContentMeasureElement() { + return _isTextarea ? _textareaCoverElement[0] : _contentElementNative; + } + + /** + * Generates a string which represents a HTML div with the given classes or attributes. + * @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".) + * @param content The content of the div as string. + * @returns {string} The concated string which represents a HTML div and its content. + */ + function generateDiv(classesOrAttrs, content) { + return '
' + + (content || _strEmpty) + + '
'; + } + + /** + * Selects or generates a div with the given class attribute. + * @param className The class names (divided by spaces) of the div which shall be selected or generated. + * @param selectParentOrOnlyChildren The parent element from which of the element shall be selected. (if undefined or boolean its hostElement) + * If its a boolean it decides whether only the children of the host element shall be selected. + * @returns {*} The generated or selected element. + */ + function selectOrGenerateDivByClass(className, selectParentOrOnlyChildren) { + var onlyChildren = type(selectParentOrOnlyChildren) == TYPES.b; + var selectParent = onlyChildren ? _hostElement : (selectParentOrOnlyChildren || _hostElement); + + return (_domExists && !selectParent[LEXICON.l]) + ? null + : _domExists + ? selectParent[onlyChildren ? 'children' : 'find'](_strDot + className.replace(/\s/g, _strDot)).eq(0) + : FRAMEWORK(generateDiv(className)) + } + + /** + * Gets the value of the given property from the given object. + * @param obj The object from which the property value shall be got. + * @param path The property of which the value shall be got. + * @returns {*} Returns the value of the searched property or undefined of the property wasn't found. + */ + function getObjectPropVal(obj, path) { + var splits = path.split(_strDot); + var i = 0; + var val; + for (; i < splits.length; i++) { + if (!obj[LEXICON.hOP](splits[i])) + return; + val = obj[splits[i]]; + if (i < splits.length && type(val) == TYPES.o) + obj = val; + } + return val; + } + + /** + * Sets the value of the given property from the given object. + * @param obj The object from which the property value shall be set. + * @param path The property of which the value shall be set. + * @param val The value of the property which shall be set. + */ + function setObjectPropVal(obj, path, val) { + var splits = path.split(_strDot); + var splitsLength = splits.length; + var i = 0; + var extendObj = {}; + var extendObjRoot = extendObj; + for (; i < splitsLength; i++) + extendObj = extendObj[splits[i]] = i + 1 < splitsLength ? {} : val; + FRAMEWORK.extend(obj, extendObjRoot, true); + } + + + //==== Utils Cache ====// + + /** + * Compares two values or objects and returns true if they aren't equal. + * @param current The first value or object which shall be compared. + * @param cache The second value or object which shall be compared. + * @param force If true the returned value is always true. + * @returns {boolean} True if both values or objects aren't equal or force is true, false otherwise. + */ + function checkCache(current, cache, force) { + if (force) + return force; + if (type(current) == TYPES.o && type(cache) == TYPES.o) { + for (var prop in current) { + if (prop !== 'c') { + if (current[LEXICON.hOP](prop) && cache[LEXICON.hOP](prop)) { + if (checkCache(current[prop], cache[prop])) + return true; + } + else { + return true; + } + } + } + } + else { + return current !== cache; + } + return false; + } + + + //==== Shortcuts ====// + + /** + * jQuery extend method shortcut with a appended "true" as first argument. + */ + function extendDeep() { + return FRAMEWORK.extend.apply(this, [true].concat([].slice.call(arguments))); + } + + /** + * jQuery addClass method shortcut. + */ + function addClass(el, classes) { + return _frameworkProto.addClass.call(el, classes); + } + + /** + * jQuery removeClass method shortcut. + */ + function removeClass(el, classes) { + return _frameworkProto.removeClass.call(el, classes); + } + + /** + * jQuery remove method shortcut. + */ + function remove(el) { + return _frameworkProto.remove.call(el); + } + + /** + * Finds the first child element with the given selector of the given element. + * @param el The root element from which the selector shall be valid. + * @param selector The selector of the searched element. + * @returns {*} The first element which is a child of the given element and matches the givens selector. + */ + function findFirst(el, selector) { + return _frameworkProto.find.call(el, selector).eq(0); + } + + + //==== API ====// + + /** + * 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. + * This behavior can be reset by calling the update method. + */ + _base.sleep = function () { + _sleeping = true; + }; + + /** + * Updates the plugin and DOM to the current options. + * This method should only be called if a update is 100% required. + * @param force True if every property shall be updated and the cache shall be ignored. + * !INTERNAL USAGE! : force can be a string "auto", "sync" or "zoom" too + * 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. + * 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. + * if "zoom" then a update takes place where it's assumed that content and host size changed + * @returns {boolean|undefined} + * If force is "sync" then a boolean is returned which indicates whether a update was needed due to pending changes. + * If force is "auto" then a boolean is returned whether a update was needed due to attribute or size changes. + * undefined otherwise. + */ + _base.update = function (force) { + if (_destroyed) + return; + + var attrsChanged; + var contentSizeC; + var isString = type(force) == TYPES.s; + var imgElementSelector = 'img'; + var imgElementLoadEvent = 'load'; + var doUpdateAuto; + var mutHost; + var mutContent; + + if (isString) { + if (force === _strAuto) { + attrsChanged = meaningfulAttrsChanged(); + contentSizeC = updateAutoContentSizeChanged(); + doUpdateAuto = attrsChanged || contentSizeC; + if (doUpdateAuto) { + update({ + _contentSizeChanged: contentSizeC, + _changedOptions: _initialized ? undefined : _currentPreparedOptions + }); + } + } + else if (force === _strSync) { + if (_mutationObserversConnected) { + mutHost = _mutationObserverHostCallback(_mutationObserverHost.takeRecords()); + mutContent = _mutationObserverContentCallback(_mutationObserverContent.takeRecords()); + } + else { + mutHost = _base.update(_strAuto); + } + } + else if (force === 'zoom') { + update({ + _hostSizeChanged: true, + _contentSizeChanged: true + }); + } + } + else { + force = _sleeping || force; + _sleeping = false; + if (!_base.update(_strSync) || force) + update({ _force: force }); + } + if (!_isTextarea) { + _contentElement.find(imgElementSelector).each(function (i, el) { + var index = COMPATIBILITY.inA(el, _imgs); + if (index === -1) + FRAMEWORK(el).off(imgElementLoadEvent, imgOnLoad).on(imgElementLoadEvent, imgOnLoad); + }); + } + return doUpdateAuto || mutHost || mutContent; + }; + + /** + Gets or sets the current options. The update method will be called automatically if new options were set. + * @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. + * @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. + * @returns {*} + */ + _base.options = function (newOptions, value) { + var option = {}; + var changedOps; + + //return current options if newOptions are undefined or empty + if (FRAMEWORK.isEmptyObject(newOptions) || !FRAMEWORK.isPlainObject(newOptions)) { + if (type(newOptions) == TYPES.s) { + if (arguments.length > 1) { + setObjectPropVal(option, newOptions, value); + changedOps = setOptions(option); + } + else + return getObjectPropVal(_currentOptions, newOptions); + } + else + return _currentOptions; + } + else { + changedOps = setOptions(newOptions); + } + + if (!FRAMEWORK.isEmptyObject(changedOps)) { + update({ _changedOptions: changedOps }); + } + }; + + /** + * Restore the DOM, disconnects all observers, remove all resize observers and put the instance to sleep. + */ + _base.destroy = function () { + if (_destroyed) + return; + + //remove this instance from auto update loop + autoUpdateLoop.remove(_base); + + //disconnect all mutation observers + disconnectMutationObservers(); + + //remove all resize observers + setupResizeObserver(_sizeObserverElement); + setupResizeObserver(_sizeAutoObserverElement); + + //remove all extensions + for (var extName in _extensions) + _base.removeExt(extName); + + //remove all 'destroy' events + while (_destroyEvents[LEXICON.l] > 0) + _destroyEvents.pop()(); + + //remove all events from host element + setupHostMouseTouchEvents(true); + + //remove all helper / detection elements + if (_contentGlueElement) + remove(_contentGlueElement); + if (_contentArrangeElement) + remove(_contentArrangeElement); + if (_sizeAutoObserverAdded) + remove(_sizeAutoObserverElement); + + //remove all generated DOM + setupScrollbarsDOM(true); + setupScrollbarCornerDOM(true); + setupStructureDOM(true); + + //remove all generated image load events + for (var i = 0; i < _imgs[LEXICON.l]; i++) + FRAMEWORK(_imgs[i]).off('load', imgOnLoad); + _imgs = undefined; + + _destroyed = true; + _sleeping = true; + + //remove this instance from the instances list + INSTANCES(pluginTargetElement, 0); + dispatchCallback('onDestroyed'); + + //remove all properties and methods + //for (var property in _base) + // delete _base[property]; + //_base = undefined; + }; + + /** + * Scrolls to a given position or element. + * @param coordinates + * 1. Can be "coordinates" which looks like: + * { x : ?, y : ? } OR Object with x and y properties + * { left : ?, top : ? } OR Object with left and top properties + * { l : ?, t : ? } OR Object with l and t properties + * [ ?, ? ] OR Array where the first two element are the coordinates (first is x, second is y) + * ? A single value which stays for both axis + * A value can be a number, a string or a calculation. + * + * Operators: + * [NONE] The current scroll will be overwritten by the value. + * '+=' The value will be added to the current scroll offset + * '-=' The value will be subtracted from the current scroll offset + * '*=' The current scroll wil be multiplicated by the value. + * '/=' The current scroll wil be divided by the value. + * + * Units: + * [NONE] The value is the final scroll amount. final = (value * 1) + * 'px' Same as none + * '%' The value is dependent on the current scroll value. final = ((currentScrollValue / 100) * value) + * 'vw' The value is multiplicated by the viewport width. final = (value * viewportWidth) + * 'vh' The value is multiplicated by the viewport height. final = (value * viewportHeight) + * + * example final values: + * 200, '200px', '50%', '1vw', '1vh', '+=200', '/=1vw', '*=2px', '-=5vh', '+=33%', '+= 50% - 2px', '-= 1vw - 50%' + * + * 2. Can be a HTML or jQuery element: + * The final scroll offset is the offset (without margin) of the given HTML / jQuery element. + * + * 3. Can be a object with a HTML or jQuery element with additional settings: + * { + * el : [HTMLElement, jQuery element], MUST be specified, else this object isn't valid. + * scroll : [string, array, object], Default value is 'always'. + * block : [string, array, object], Default value is 'begin'. + * margin : [number, boolean, array, object] Default value is false. + * } + * + * Possible scroll settings are: + * 'always' Scrolls always. + * 'ifneeded' Scrolls only if the element isnt fully in view. + * 'never' Scrolls never. + * + * Possible block settings are: + * 'begin' Both axis shall be docked to the "begin" edge. - The element will be docked to the top and left edge of the viewport. + * '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.) + * 'center' Both axis shall be docked to "center". - The element will be centered in the viewport. + * 'nearest' The element will be docked to the nearest edge(s). + * + * Possible margin settings are: -- The actual margin of the element wont be affect, this option affects only the final scroll offset. + * [BOOLEAN] If true the css margin of the element will be used, if false no margin will be used. + * [NUMBER] The margin will be used for all edges. + * + * @param duration The duration of the scroll animation, OR a jQuery animation configuration object. + * @param easing The animation easing. + * @param complete The animation complete callback. + * @returns {{ + * position: {x: number, y: number}, + * ratio: {x: number, y: number}, + * max: {x: number, y: number}, + * handleOffset: {x: number, y: number}, + * handleLength: {x: number, y: number}, + * handleLengthRatio: {x: number, y: number}, t + * rackLength: {x: number, y: number}, + * isRTL: boolean, + * isRTLNormalized: boolean + * }} + */ + _base.scroll = function (coordinates, duration, easing, complete) { + if (arguments.length === 0 || coordinates === undefined) { + var infoX = _scrollHorizontalInfo; + var infoY = _scrollVerticalInfo; + var normalizeInvert = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.i; + var normalizeNegate = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.n; + var scrollX = infoX._currentScroll; + var scrollXRatio = infoX._currentScrollRatio; + var maxScrollX = infoX._maxScroll; + scrollXRatio = normalizeInvert ? 1 - scrollXRatio : scrollXRatio; + scrollX = normalizeInvert ? maxScrollX - scrollX : scrollX; + scrollX *= normalizeNegate ? -1 : 1; + maxScrollX *= normalizeNegate ? -1 : 1; + + return { + position: { + x: scrollX, + y: infoY._currentScroll + }, + ratio: { + x: scrollXRatio, + y: infoY._currentScrollRatio + }, + max: { + x: maxScrollX, + y: infoY._maxScroll + }, + handleOffset: { + x: infoX._handleOffset, + y: infoY._handleOffset + }, + handleLength: { + x: infoX._handleLength, + y: infoY._handleLength + }, + handleLengthRatio: { + x: infoX._handleLengthRatio, + y: infoY._handleLengthRatio + }, + trackLength: { + x: infoX._trackLength, + y: infoY._trackLength + }, + snappedHandleOffset: { + x: infoX._snappedHandleOffset, + y: infoY._snappedHandleOffset + }, + isRTL: _isRTL, + isRTLNormalized: _normalizeRTLCache + }; + } + + _base.update(_strSync); + + var normalizeRTL = _normalizeRTLCache; + var coordinatesXAxisProps = [_strX, _strLeft, 'l']; + var coordinatesYAxisProps = [_strY, _strTop, 't']; + var coordinatesOperators = ['+=', '-=', '*=', '/=']; + var durationIsObject = type(duration) == TYPES.o; + var completeCallback = durationIsObject ? duration.complete : complete; + var i; + var finalScroll = {}; + var specialEasing = {}; + var doScrollLeft; + var doScrollTop; + var animationOptions; + var strEnd = 'end'; + var strBegin = 'begin'; + var strCenter = 'center'; + var strNearest = 'nearest'; + var strAlways = 'always'; + var strNever = 'never'; + var strIfNeeded = 'ifneeded'; + var strLength = LEXICON.l; + var settingsAxis; + var settingsScroll; + var settingsBlock; + var settingsMargin; + var finalElement; + var elementObjSettingsAxisValues = [_strX, _strY, 'xy', 'yx']; + var elementObjSettingsBlockValues = [strBegin, strEnd, strCenter, strNearest]; + var elementObjSettingsScrollValues = [strAlways, strNever, strIfNeeded]; + var coordinatesIsElementObj = coordinates[LEXICON.hOP]('el'); + var possibleElement = coordinatesIsElementObj ? coordinates.el : coordinates; + var possibleElementIsJQuery = possibleElement instanceof FRAMEWORK || JQUERY ? possibleElement instanceof JQUERY : false; + var possibleElementIsHTMLElement = possibleElementIsJQuery ? false : isHTMLElement(possibleElement); + var updateScrollbarInfos = function () { + if (doScrollLeft) + refreshScrollbarHandleOffset(true); + if (doScrollTop) + refreshScrollbarHandleOffset(false); + }; + var proxyCompleteCallback = type(completeCallback) != TYPES.f ? undefined : function () { + updateScrollbarInfos(); + completeCallback(); + }; + function checkSettingsStringValue(currValue, allowedValues) { + for (i = 0; i < allowedValues[strLength]; i++) { + if (currValue === allowedValues[i]) + return true; + } + return false; + } + function getRawScroll(isX, coordinates) { + var coordinateProps = isX ? coordinatesXAxisProps : coordinatesYAxisProps; + coordinates = type(coordinates) == TYPES.s || type(coordinates) == TYPES.n ? [coordinates, coordinates] : coordinates; + + if (type(coordinates) == TYPES.a) + return isX ? coordinates[0] : coordinates[1]; + else if (type(coordinates) == TYPES.o) { + //decides RTL normalization "hack" with .n + //normalizeRTL = type(coordinates.n) == TYPES.b ? coordinates.n : normalizeRTL; + for (i = 0; i < coordinateProps[strLength]; i++) + if (coordinateProps[i] in coordinates) + return coordinates[coordinateProps[i]]; + } + } + function getFinalScroll(isX, rawScroll) { + var isString = type(rawScroll) == TYPES.s; + var operator; + var amount; + var scrollInfo = isX ? _scrollHorizontalInfo : _scrollVerticalInfo; + var currScroll = scrollInfo._currentScroll; + var maxScroll = scrollInfo._maxScroll; + var mult = ' * '; + var finalValue; + var isRTLisX = _isRTL && isX; + var normalizeShortcuts = isRTLisX && _rtlScrollBehavior.n && !normalizeRTL; + var strReplace = 'replace'; + var evalFunc = eval; + var possibleOperator; + if (isString) { + //check operator + if (rawScroll[strLength] > 2) { + possibleOperator = rawScroll.substr(0, 2); + if (inArray(possibleOperator, coordinatesOperators) > -1) + operator = possibleOperator; + } + + //calculate units and shortcuts + rawScroll = operator ? rawScroll.substr(2) : rawScroll; + rawScroll = rawScroll + [strReplace](/min/g, 0) //'min' = 0% + [strReplace](//g, (normalizeShortcuts ? '-' : _strEmpty) + _strHundredPercent) //'>' = 100% + [strReplace](/px/g, _strEmpty) + [strReplace](/%/g, mult + (maxScroll * (isRTLisX && _rtlScrollBehavior.n ? -1 : 1) / 100.0)) + [strReplace](/vw/g, mult + _viewportSize.w) + [strReplace](/vh/g, mult + _viewportSize.h); + amount = parseToZeroOrNumber(isNaN(rawScroll) ? parseToZeroOrNumber(evalFunc(rawScroll), true).toFixed() : rawScroll); + } + else { + amount = rawScroll; + } + + if (amount !== undefined && !isNaN(amount) && type(amount) == TYPES.n) { + var normalizeIsRTLisX = normalizeRTL && isRTLisX; + var operatorCurrScroll = currScroll * (normalizeIsRTLisX && _rtlScrollBehavior.n ? -1 : 1); + var invert = normalizeIsRTLisX && _rtlScrollBehavior.i; + var negate = normalizeIsRTLisX && _rtlScrollBehavior.n; + operatorCurrScroll = invert ? (maxScroll - operatorCurrScroll) : operatorCurrScroll; + switch (operator) { + case '+=': + finalValue = operatorCurrScroll + amount; + break; + case '-=': + finalValue = operatorCurrScroll - amount; + break; + case '*=': + finalValue = operatorCurrScroll * amount; + break; + case '/=': + finalValue = operatorCurrScroll / amount; + break; + default: + finalValue = amount; + break; + } + finalValue = invert ? maxScroll - finalValue : finalValue; + finalValue *= negate ? -1 : 1; + finalValue = isRTLisX && _rtlScrollBehavior.n ? MATH.min(0, MATH.max(maxScroll, finalValue)) : MATH.max(0, MATH.min(maxScroll, finalValue)); + } + return finalValue === currScroll ? undefined : finalValue; + } + function getPerAxisValue(value, valueInternalType, defaultValue, allowedValues) { + var resultDefault = [defaultValue, defaultValue]; + var valueType = type(value); + var valueArrLength; + var valueArrItem; + + //value can be [ string, or array of two strings ] + if (valueType == valueInternalType) { + value = [value, value]; + } + else if (valueType == TYPES.a) { + valueArrLength = value[strLength]; + if (valueArrLength > 2 || valueArrLength < 1) + value = resultDefault; + else { + if (valueArrLength === 1) + value[1] = defaultValue; + for (i = 0; i < valueArrLength; i++) { + valueArrItem = value[i]; + if (type(valueArrItem) != valueInternalType || !checkSettingsStringValue(valueArrItem, allowedValues)) { + value = resultDefault; + break; + } + } + } + } + else if (valueType == TYPES.o) + value = [value[_strX] || defaultValue, value[_strY] || defaultValue]; + else + value = resultDefault; + return { x: value[0], y: value[1] }; + } + function generateMargin(marginTopRightBottomLeftArray) { + var result = []; + var currValue; + var currValueType; + var valueDirections = [_strTop, _strRight, _strBottom, _strLeft]; + for (i = 0; i < marginTopRightBottomLeftArray[strLength]; i++) { + if (i === valueDirections[strLength]) + break; + currValue = marginTopRightBottomLeftArray[i]; + currValueType = type(currValue); + if (currValueType == TYPES.b) + result.push(currValue ? parseToZeroOrNumber(finalElement.css(_strMarginMinus + valueDirections[i])) : 0); + else + result.push(currValueType == TYPES.n ? currValue : 0); + } + return result; + } + + if (possibleElementIsJQuery || possibleElementIsHTMLElement) { + //get settings + var margin = coordinatesIsElementObj ? coordinates.margin : 0; + var axis = coordinatesIsElementObj ? coordinates.axis : 0; + var scroll = coordinatesIsElementObj ? coordinates.scroll : 0; + var block = coordinatesIsElementObj ? coordinates.block : 0; + var marginDefault = [0, 0, 0, 0]; + var marginType = type(margin); + var marginLength; + finalElement = possibleElementIsJQuery ? possibleElement : FRAMEWORK(possibleElement); + + if (finalElement[strLength] > 0) { + //margin can be [ boolean, number, array of 2, array of 4, object ] + if (marginType == TYPES.n || marginType == TYPES.b) + margin = generateMargin([margin, margin, margin, margin]); + else if (marginType == TYPES.a) { + marginLength = margin[strLength]; + if (marginLength === 2) + margin = generateMargin([margin[0], margin[1], margin[0], margin[1]]); + else if (marginLength >= 4) + margin = generateMargin(margin); + else + margin = marginDefault; + } + else if (marginType == TYPES.o) + margin = generateMargin([margin[_strTop], margin[_strRight], margin[_strBottom], margin[_strLeft]]); + else + margin = marginDefault; + + //block = type(block) === TYPES.b ? block ? [ strNearest, strBegin ] : [ strNearest, strEnd ] : block; + settingsAxis = checkSettingsStringValue(axis, elementObjSettingsAxisValues) ? axis : 'xy'; + settingsScroll = getPerAxisValue(scroll, TYPES.s, strAlways, elementObjSettingsScrollValues); + settingsBlock = getPerAxisValue(block, TYPES.s, strBegin, elementObjSettingsBlockValues); + settingsMargin = margin; + + var viewportScroll = { + l: _scrollHorizontalInfo._currentScroll, + t: _scrollVerticalInfo._currentScroll + }; + // use padding element instead of viewport element because padding element has never padding, margin or position applied. + var viewportOffset = _paddingElement.offset(); + + //get coordinates + var elementOffset = finalElement.offset(); + var doNotScroll = { + x: settingsScroll.x == strNever || settingsAxis == _strY, + y: settingsScroll.y == strNever || settingsAxis == _strX + }; + elementOffset[_strTop] -= settingsMargin[0]; + elementOffset[_strLeft] -= settingsMargin[3]; + var elementScrollCoordinates = { + x: MATH.round(elementOffset[_strLeft] - viewportOffset[_strLeft] + viewportScroll.l), + y: MATH.round(elementOffset[_strTop] - viewportOffset[_strTop] + viewportScroll.t) + }; + if (_isRTL) { + if (!_rtlScrollBehavior.n && !_rtlScrollBehavior.i) + elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + viewportScroll.l); + if (_rtlScrollBehavior.n && normalizeRTL) + elementScrollCoordinates.x *= -1; + if (_rtlScrollBehavior.i && normalizeRTL) + elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + (_scrollHorizontalInfo._maxScroll - viewportScroll.l)); + } + + //measuring is required + if (settingsBlock.x != strBegin || settingsBlock.y != strBegin || settingsScroll.x == strIfNeeded || settingsScroll.y == strIfNeeded || _isRTL) { + var measuringElm = finalElement[0]; + var rawElementSize = _supportTransform ? measuringElm[LEXICON.bCR]() : { + width: measuringElm[LEXICON.oW], + height: measuringElm[LEXICON.oH] + }; + var elementSize = { + w: rawElementSize[_strWidth] + settingsMargin[3] + settingsMargin[1], + h: rawElementSize[_strHeight] + settingsMargin[0] + settingsMargin[2] + }; + var finalizeBlock = function (isX) { + var vars = getScrollbarVars(isX); + var wh = vars._w_h; + var lt = vars._left_top; + var xy = vars._x_y; + var blockIsEnd = settingsBlock[xy] == (isX ? _isRTL ? strBegin : strEnd : strEnd); + var blockIsCenter = settingsBlock[xy] == strCenter; + var blockIsNearest = settingsBlock[xy] == strNearest; + var scrollNever = settingsScroll[xy] == strNever; + var scrollIfNeeded = settingsScroll[xy] == strIfNeeded; + var vpSize = _viewportSize[wh]; + var vpOffset = viewportOffset[lt]; + var elSize = elementSize[wh]; + var elOffset = elementOffset[lt]; + var divide = blockIsCenter ? 2 : 1; + var elementCenterOffset = elOffset + (elSize / 2); + var viewportCenterOffset = vpOffset + (vpSize / 2); + var isInView = + elSize <= vpSize + && elOffset >= vpOffset + && elOffset + elSize <= vpOffset + vpSize; + + if (scrollNever) + doNotScroll[xy] = true; + else if (!doNotScroll[xy]) { + if (blockIsNearest || scrollIfNeeded) { + doNotScroll[xy] = scrollIfNeeded ? isInView : false; + blockIsEnd = elSize < vpSize ? elementCenterOffset > viewportCenterOffset : elementCenterOffset < viewportCenterOffset; + } + elementScrollCoordinates[xy] -= blockIsEnd || blockIsCenter ? ((vpSize / divide) - (elSize / divide)) * (isX && _isRTL && normalizeRTL ? -1 : 1) : 0; + } + }; + finalizeBlock(true); + finalizeBlock(false); + } + + if (doNotScroll.y) + delete elementScrollCoordinates.y; + if (doNotScroll.x) + delete elementScrollCoordinates.x; + + coordinates = elementScrollCoordinates; + } + } + + finalScroll[_strScrollLeft] = getFinalScroll(true, getRawScroll(true, coordinates)); + finalScroll[_strScrollTop] = getFinalScroll(false, getRawScroll(false, coordinates)); + doScrollLeft = finalScroll[_strScrollLeft] !== undefined; + doScrollTop = finalScroll[_strScrollTop] !== undefined; + + if ((doScrollLeft || doScrollTop) && (duration > 0 || durationIsObject)) { + if (durationIsObject) { + duration.complete = proxyCompleteCallback; + _viewportElement.animate(finalScroll, duration); + } + else { + animationOptions = { + duration: duration, + complete: proxyCompleteCallback + }; + if (type(easing) == TYPES.a || FRAMEWORK.isPlainObject(easing)) { + specialEasing[_strScrollLeft] = easing[0] || easing.x; + specialEasing[_strScrollTop] = easing[1] || easing.y; + animationOptions.specialEasing = specialEasing; + } + else { + animationOptions.easing = easing; + } + _viewportElement.animate(finalScroll, animationOptions); + } + } + else { + if (doScrollLeft) + _viewportElement[_strScrollLeft](finalScroll[_strScrollLeft]); + if (doScrollTop) + _viewportElement[_strScrollTop](finalScroll[_strScrollTop]); + updateScrollbarInfos(); + } + }; + + /** + * Stops all scroll animations. + * @returns {*} The current OverlayScrollbars instance (for chaining). + */ + _base.scrollStop = function (param1, param2, param3) { + _viewportElement.stop(param1, param2, param3); + return _base; + }; + + /** + * Returns all relevant elements. + * @param elementName The name of the element which shall be returned. + * @returns {{target: *, host: *, padding: *, viewport: *, content: *, scrollbarHorizontal: {scrollbar: *, track: *, handle: *}, scrollbarVertical: {scrollbar: *, track: *, handle: *}, scrollbarCorner: *} | *} + */ + _base.getElements = function (elementName) { + var obj = { + target: _targetElementNative, + host: _hostElementNative, + padding: _paddingElementNative, + viewport: _viewportElementNative, + content: _contentElementNative, + scrollbarHorizontal: { + scrollbar: _scrollbarHorizontalElement[0], + track: _scrollbarHorizontalTrackElement[0], + handle: _scrollbarHorizontalHandleElement[0] + }, + scrollbarVertical: { + scrollbar: _scrollbarVerticalElement[0], + track: _scrollbarVerticalTrackElement[0], + handle: _scrollbarVerticalHandleElement[0] + }, + scrollbarCorner: _scrollbarCornerElement[0] + }; + return type(elementName) == TYPES.s ? getObjectPropVal(obj, elementName) : obj; + }; + + /** + * Returns a object which describes the current state of this instance. + * @param stateProperty A specific property from the state object which shall be returned. + * @returns {{widthAuto, heightAuto, overflowAmount, hideOverflow, hasOverflow, contentScrollSize, viewportSize, hostSize, autoUpdate} | *} + */ + _base.getState = function (stateProperty) { + function prepare(obj) { + if (!FRAMEWORK.isPlainObject(obj)) + return obj; + var extended = extendDeep({}, obj); + var changePropertyName = function (from, to) { + if (extended[LEXICON.hOP](from)) { + extended[to] = extended[from]; + delete extended[from]; + } + }; + changePropertyName('w', _strWidth); //change w to width + changePropertyName('h', _strHeight); //change h to height + delete extended.c; //delete c (the 'changed' prop) + return extended; + }; + var obj = { + destroyed: !!prepare(_destroyed), + sleeping: !!prepare(_sleeping), + autoUpdate: prepare(!_mutationObserversConnected), + widthAuto: prepare(_widthAutoCache), + heightAuto: prepare(_heightAutoCache), + padding: prepare(_cssPaddingCache), + overflowAmount: prepare(_overflowAmountCache), + hideOverflow: prepare(_hideOverflowCache), + hasOverflow: prepare(_hasOverflowCache), + contentScrollSize: prepare(_contentScrollSizeCache), + viewportSize: prepare(_viewportSize), + hostSize: prepare(_hostSizeCache), + documentMixed: prepare(_documentMixed) + }; + return type(stateProperty) == TYPES.s ? getObjectPropVal(obj, stateProperty) : obj; + }; + + /** + * Gets all or specific extension instance. + * @param extName The name of the extension from which the instance shall be got. + * @returns {{}} The instance of the extension with the given name or undefined if the instance couldn't be found. + */ + _base.ext = function (extName) { + var result; + var privateMethods = _extensionsPrivateMethods.split(' '); + var i = 0; + if (type(extName) == TYPES.s) { + if (_extensions[LEXICON.hOP](extName)) { + result = extendDeep({}, _extensions[extName]); + for (; i < privateMethods.length; i++) + delete result[privateMethods[i]]; + } + } + else { + result = {}; + for (i in _extensions) + result[i] = extendDeep({}, _base.ext(i)); + } + return result; + }; + + /** + * Adds a extension to this instance. + * @param extName The name of the extension which shall be added. + * @param extensionOptions The extension options which shall be used. + * @returns {{}} The instance of the added extension or undefined if the extension couldn't be added properly. + */ + _base.addExt = function (extName, extensionOptions) { + var registeredExtensionObj = _plugin.extension(extName); + var instance; + var instanceAdded; + var instanceContract; + var contractResult; + var contractFulfilled = true; + if (registeredExtensionObj) { + if (!_extensions[LEXICON.hOP](extName)) { + instance = registeredExtensionObj.extensionFactory.call(_base, + extendDeep({}, registeredExtensionObj.defaultOptions), + FRAMEWORK, + COMPATIBILITY); + + if (instance) { + instanceContract = instance.contract; + if (type(instanceContract) == TYPES.f) { + contractResult = instanceContract(window); + contractFulfilled = type(contractResult) == TYPES.b ? contractResult : contractFulfilled; + } + if (contractFulfilled) { + _extensions[extName] = instance; + instanceAdded = instance.added; + if (type(instanceAdded) == TYPES.f) + instanceAdded(extensionOptions); + + return _base.ext(extName); + } + } + } + else + return _base.ext(extName); + } + else + console.warn("A extension with the name \"" + extName + "\" isn't registered."); + }; + + /** + * Removes a extension from this instance. + * @param extName The name of the extension which shall be removed. + * @returns {boolean} True if the extension was removed, false otherwise e.g. if the extension wasn't added before. + */ + _base.removeExt = function (extName) { + var instance = _extensions[extName]; + var instanceRemoved; + if (instance) { + delete _extensions[extName]; + + instanceRemoved = instance.removed; + if (type(instanceRemoved) == TYPES.f) + instanceRemoved(); + + return true; + } + return false; + }; + + /** + * Constructs the plugin. + * @param targetElement The element to which the plugin shall be applied. + * @param options The initial options of the plugin. + * @param extensions The extension(s) which shall be added right after the initialization. + * @returns {boolean} True if the plugin was successfully initialized, false otherwise. + */ + function construct(targetElement, options, extensions) { + _defaultOptions = globals.defaultOptions; + _nativeScrollbarStyling = globals.nativeScrollbarStyling; + _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); + _nativeScrollbarIsOverlaid = extendDeep({}, globals.nativeScrollbarIsOverlaid); + _overlayScrollbarDummySize = extendDeep({}, globals.overlayScrollbarDummySize); + _rtlScrollBehavior = extendDeep({}, globals.rtlScrollBehavior); + + //parse & set options but don't update + setOptions(extendDeep({}, _defaultOptions, options)); + + _cssCalc = globals.cssCalc; + _msieVersion = globals.msie; + _autoUpdateRecommended = globals.autoUpdateRecommended; + _supportTransition = globals.supportTransition; + _supportTransform = globals.supportTransform; + _supportPassiveEvents = globals.supportPassiveEvents; + _supportResizeObserver = globals.supportResizeObserver; + _supportMutationObserver = globals.supportMutationObserver; + _restrictedMeasuring = globals.restrictedMeasuring; + _documentElement = FRAMEWORK(targetElement.ownerDocument); + _documentElementNative = _documentElement[0]; + _windowElement = FRAMEWORK(_documentElementNative.defaultView || _documentElementNative.parentWindow); + _windowElementNative = _windowElement[0]; + _htmlElement = findFirst(_documentElement, 'html'); + _bodyElement = findFirst(_htmlElement, 'body'); + _targetElement = FRAMEWORK(targetElement); + _targetElementNative = _targetElement[0]; + _isTextarea = _targetElement.is('textarea'); + _isBody = _targetElement.is('body'); + _documentMixed = _documentElementNative !== document; + + /* On a div Element The if checks only whether: + * - the targetElement has the class "os-host" + * - the targetElement has a a child with the class "os-padding" + * + * If that's the case, its assumed the DOM has already the following structure: + * (The ".os-host" element is the targetElement) + * + *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * + * ===================================================================================== + * + * On a Textarea Element The if checks only whether: + * - the targetElement has the class "os-textarea" + * - the targetElement is inside a element with the class "os-content" + * + * If that's the case, its assumed the DOM has already the following structure: + * (The ".os-textarea" (textarea) element is the targetElement) + * + *
+ *
+ *
+ *
+ *
+ *
+ * + *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */ + _domExists = _isTextarea + ? _targetElement.hasClass(_classNameTextareaElement) && _targetElement.parent().hasClass(_classNameContentElement) + : _targetElement.hasClass(_classNameHostElement) && _targetElement.children(_strDot + _classNamePaddingElement)[LEXICON.l]; + + var initBodyScroll; + var bodyMouseTouchDownListener; + + //check if the plugin hasn't to be initialized + if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y && !_currentPreparedOptions.nativeScrollbarsOverlaid.initialize) { + dispatchCallback('onInitializationWithdrawn'); + if (_domExists) { + setupStructureDOM(true); + setupScrollbarsDOM(true); + setupScrollbarCornerDOM(true); + } + + _destroyed = true; + _sleeping = true; + + return _base; + } + + if (_isBody) { + initBodyScroll = {}; + initBodyScroll.l = MATH.max(_targetElement[_strScrollLeft](), _htmlElement[_strScrollLeft](), _windowElement[_strScrollLeft]()); + initBodyScroll.t = MATH.max(_targetElement[_strScrollTop](), _htmlElement[_strScrollTop](), _windowElement[_strScrollTop]()); + + bodyMouseTouchDownListener = function () { + _viewportElement.removeAttr(LEXICON.ti); + setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, true, true); + } + } + + //build OverlayScrollbars DOM + setupStructureDOM(); + setupScrollbarsDOM(); + setupScrollbarCornerDOM(); + + //create OverlayScrollbars events + setupStructureEvents(); + setupScrollbarEvents(true); + setupScrollbarEvents(false); + setupScrollbarCornerEvents(); + + //create mutation observers + createMutationObservers(); + + //build resize observer for the host element + setupResizeObserver(_sizeObserverElement, hostOnResized); + + if (_isBody) { + //apply the body scroll to handle it right in the update method + _viewportElement[_strScrollLeft](initBodyScroll.l)[_strScrollTop](initBodyScroll.t); + + //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 + if (document.activeElement == targetElement && _viewportElementNative.focus) { + //set a tabindex to make the viewportElement focusable + _viewportElement.attr(LEXICON.ti, '-1'); + _viewportElementNative.focus(); + + /* the tabindex has to be removed due to; + * If you set the tabindex attribute on an
, then its child content cannot be scrolled with the arrow keys unless you set tabindex on the content, too + * https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex + */ + setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, false, true); + } + } + + //update for the first time & initialize cache + _base.update(_strAuto); + + //the plugin is initialized now! + _initialized = true; + dispatchCallback('onInitialized'); + + //call all callbacks which would fire before the initialized was complete + each(_callbacksInitQeueue, function (index, value) { dispatchCallback(value.n, value.a); }); + _callbacksInitQeueue = []; + + //add extensions + if (type(extensions) == TYPES.s) + extensions = [extensions]; + if (COMPATIBILITY.isA(extensions)) + each(extensions, function (index, value) { _base.addExt(value); }); + else if (FRAMEWORK.isPlainObject(extensions)) + each(extensions, function (key, value) { _base.addExt(key, value); }); + + //add the transition class for transitions AFTER the first update & AFTER the applied extensions (for preventing unwanted transitions) + setTimeout(function () { + if (_supportTransition && !_destroyed) + addClass(_hostElement, _classNameHostTransition); + }, 333); + + return _base; + } + + if (_plugin.valid(construct(pluginTargetElement, options, extensions))) { + INSTANCES(pluginTargetElement, _base); + } + + return _base; + } + + /** + * Initializes a new OverlayScrollbarsInstance object or changes options if already initialized or returns the current instance. + * @param pluginTargetElements The elements to which the Plugin shall be initialized. + * @param options The custom options with which the plugin shall be initialized. + * @param extensions The extension(s) which shall be added right after initialization. + * @returns {*} + */ + _plugin = window[PLUGINNAME] = function (pluginTargetElements, options, extensions) { + if (arguments[LEXICON.l] === 0) + return this; + + var arr = []; + var optsIsPlainObj = FRAMEWORK.isPlainObject(options); + var inst; + var result; + + //pluginTargetElements is null or undefined + if (!pluginTargetElements) + return optsIsPlainObj || !options ? result : arr; + + /* + pluginTargetElements will be converted to: + 1. A jQueryElement Array + 2. A HTMLElement Array + 3. A Array with a single HTML Element + so pluginTargetElements is always a array. + */ + pluginTargetElements = pluginTargetElements[LEXICON.l] != undefined ? pluginTargetElements : [pluginTargetElements[0] || pluginTargetElements]; + initOverlayScrollbarsStatics(); + + if (pluginTargetElements[LEXICON.l] > 0) { + if (optsIsPlainObj) { + FRAMEWORK.each(pluginTargetElements, function (i, v) { + inst = v; + if (inst !== undefined) + arr.push(OverlayScrollbarsInstance(inst, options, extensions, _pluginsGlobals, _pluginsAutoUpdateLoop)); + }); + } + else { + FRAMEWORK.each(pluginTargetElements, function (i, v) { + inst = INSTANCES(v); + if ((options === '!' && _plugin.valid(inst)) || (COMPATIBILITY.type(options) == TYPES.f && options(v, inst))) + arr.push(inst); + else if (options === undefined) + arr.push(inst); + }); + } + result = arr[LEXICON.l] === 1 ? arr[0] : arr; + } + return result; + }; + + /** + * Returns a object which contains global information about the plugin and each instance of it. + * The returned object is just a copy, that means that changes to the returned object won't have any effect to the original object. + */ + _plugin.globals = function () { + initOverlayScrollbarsStatics(); + var globals = FRAMEWORK.extend(true, {}, _pluginsGlobals); + delete globals['msie']; + return globals; + }; + + /** + * Gets or Sets the default options for each new plugin initialization. + * @param newDefaultOptions The object with which the default options shall be extended. + */ + _plugin.defaultOptions = function (newDefaultOptions) { + initOverlayScrollbarsStatics(); + var currDefaultOptions = _pluginsGlobals.defaultOptions; + if (newDefaultOptions === undefined) + return FRAMEWORK.extend(true, {}, currDefaultOptions); + + //set the new default options + _pluginsGlobals.defaultOptions = FRAMEWORK.extend(true, {}, currDefaultOptions, _pluginsOptions._validate(newDefaultOptions, _pluginsOptions._template, true, currDefaultOptions)._default); + }; + + /** + * Checks whether the passed instance is a non-destroyed OverlayScrollbars instance. + * @param osInstance The potential OverlayScrollbars instance which shall be checked. + * @returns {boolean} True if the passed value is a non-destroyed OverlayScrollbars instance, false otherwise. + */ + _plugin.valid = function (osInstance) { + return osInstance instanceof _plugin && !osInstance.getState().destroyed; + }; + + /** + * Registers, Unregisters or returns a extension. + * Register: Pass the name and the extension. (defaultOptions is optional) + * Unregister: Pass the name and anything except a function as extension parameter. + * Get extension: Pass the name of the extension which shall be got. + * Get all extensions: Pass no arguments. + * @param extensionName The name of the extension which shall be registered, unregistered or returned. + * @param extension A function which generates the instance of the extension or anything other to remove a already registered extension. + * @param defaultOptions The default options which shall be used for the registered extension. + */ + _plugin.extension = function (extensionName, extension, defaultOptions) { + var extNameTypeString = COMPATIBILITY.type(extensionName) == TYPES.s; + var argLen = arguments[LEXICON.l]; + var i = 0; + if (argLen < 1 || !extNameTypeString) { + //return a copy of all extension objects + return FRAMEWORK.extend(true, { length: _pluginsExtensions[LEXICON.l] }, _pluginsExtensions); + } + else if (extNameTypeString) { + if (COMPATIBILITY.type(extension) == TYPES.f) { + //register extension + _pluginsExtensions.push({ + name: extensionName, + extensionFactory: extension, + defaultOptions: defaultOptions + }); + } + else { + for (; i < _pluginsExtensions[LEXICON.l]; i++) { + if (_pluginsExtensions[i].name === extensionName) { + if (argLen > 1) + _pluginsExtensions.splice(i, 1); //remove extension + else + return FRAMEWORK.extend(true, {}, _pluginsExtensions[i]); //return extension with the given name + } + } + } + } + }; + + return _plugin; + })(); + + if (JQUERY && JQUERY.fn) { + /** + * The jQuery initialization interface. + * @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. + * @param extensions The extension(s) which shall be added right after initialization. + * @returns {*} After initialization it returns the jQuery element array, else it returns the instance(s) of the elements which are selected. + */ + JQUERY.fn.overlayScrollbars = function (options, extensions) { + var _elements = this; + if (JQUERY.isPlainObject(options)) { + JQUERY.each(_elements, function () { PLUGIN(this, options, extensions); }); + return _elements; + } + else + return PLUGIN(_elements, options); + }; + } + return PLUGIN; + } )); \ No newline at end of file diff --git a/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js b/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js index 3d876f741..4383b712d 100644 --- a/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js +++ b/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js @@ -1,5571 +1,5571 @@ -/*! - * OverlayScrollbars - * https://github.com/KingSora/OverlayScrollbars - * - * Version: 1.11.0 - * - * Copyright KingSora | Rene Haas. - * https://github.com/KingSora - * - * Released under the MIT license. - * Date: 29.02.2020 - */ - -(function (global, factory) { - if (typeof define === 'function' && define.amd) - define(['jquery'], function(framework) { return factory(global, global.document, undefined, framework); }); - else if (typeof module === 'object' && typeof module.exports === 'object') - module.exports = factory(global, global.document, undefined, require('jquery')); - else - factory(global, global.document, undefined, global.jQuery); -}(typeof window !== 'undefined' ? window : this, - function(window, document, undefined, framework) { - 'use strict'; - var PLUGINNAME = 'OverlayScrollbars'; - var TYPES = { - o : 'object', - f : 'function', - a : 'array', - s : 'string', - b : 'boolean', - n : 'number', - u : 'undefined', - z : 'null' - //d : 'date', - //e : 'error', - //r : 'regexp', - //y : 'symbol' - }; - var LEXICON = { - c: 'class', - s: 'style', - i: 'id', - l: 'length', - p: 'prototype', - ti: 'tabindex', - oH: 'offsetHeight', - cH: 'clientHeight', - sH: 'scrollHeight', - oW: 'offsetWidth', - cW: 'clientWidth', - sW: 'scrollWidth', - hOP: 'hasOwnProperty', - bCR: 'getBoundingClientRect' - }; - var VENDORS = (function() { - //https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix - var jsCache = { }; - var cssCache = { }; - var cssPrefixes = ['-webkit-', '-moz-', '-o-', '-ms-']; - var jsPrefixes = ['WebKit', 'Moz', 'O', 'MS']; - function firstLetterToUpper(str) { - return str.charAt(0).toUpperCase() + str.slice(1); - } - - return { - _cssPrefixes: cssPrefixes, - _jsPrefixes: jsPrefixes, - _cssProperty : function(name) { - var result = cssCache[name]; - - if(cssCache[LEXICON.hOP](name)) - return result; - - var uppercasedName = firstLetterToUpper(name); - var elmStyle = document.createElement('div')[LEXICON.s]; - var resultPossibilities; - var i = 0; - var v; - var currVendorWithoutDashes; - - for (; i < cssPrefixes.length; i++) { - currVendorWithoutDashes = cssPrefixes[i].replace(/-/g, ''); - resultPossibilities = [ - name, //transition - cssPrefixes[i] + name, //-webkit-transition - currVendorWithoutDashes + uppercasedName, //webkitTransition - firstLetterToUpper(currVendorWithoutDashes) + uppercasedName //WebkitTransition - ]; - for(v = 0; v < resultPossibilities[LEXICON.l]; v++) { - if(elmStyle[resultPossibilities[v]] !== undefined) { - result = resultPossibilities[v]; - break; - } - } - } - - cssCache[name] = result; - return result; - }, - _jsAPI : function(name, isInterface, fallback) { - var i = 0; - var result = jsCache[name]; - - if(!jsCache[LEXICON.hOP](name)) { - result = window[name]; - for(; i < jsPrefixes[LEXICON.l]; i++) - result = result || window[(isInterface ? jsPrefixes[i] : jsPrefixes[i].toLowerCase()) + firstLetterToUpper(name)]; - jsCache[name] = result; - } - return result || fallback; - } - - } - })(); - var COMPATIBILITY = (function() { - function windowSize(x) { - return x ? window.innerWidth || document.documentElement[LEXICON.cW] || document.body[LEXICON.cW] : window.innerHeight || document.documentElement[LEXICON.cH] || document.body[LEXICON.cH]; - } - function bind(func, thisObj) { - if (typeof func != TYPES.f) { - throw "Can't bind function!"; - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - //throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - var proto = LEXICON.p; - var aArgs = Array[proto].slice.call(arguments, 2); - var fNOP = function() {}; - var fBound = function() { return func.apply(this instanceof fNOP ? this : thisObj, aArgs.concat(Array[proto].slice.call(arguments))); }; - - if (func[proto]) - fNOP[proto] = func[proto]; // Function.prototype doesn't have a prototype property - fBound[proto] = new fNOP(); - - return fBound; - } - - return { - /** - * Gets the current window width. - * @returns {Number|number} The current window width in pixel. - */ - wW: bind(windowSize, 0, true), - - /** - * Gets the current window height. - * @returns {Number|number} The current window height in pixel. - */ - wH: bind(windowSize, 0), - - /** - * Gets the MutationObserver Object or undefined if not supported. - * @returns {MutationObserver|*|undefined} The MutationsObserver Object or undefined. - */ - mO: bind(VENDORS._jsAPI, 0, 'MutationObserver', true), - - /** - * Gets the ResizeObserver Object or undefined if not supported. - * @returns {MutationObserver|*|undefined} The ResizeObserver Object or undefined. - */ - rO: bind(VENDORS._jsAPI, 0, 'ResizeObserver', true), - - /** - * Gets the RequestAnimationFrame method or it's corresponding polyfill. - * @returns {*|Function} The RequestAnimationFrame method or it's corresponding polyfill. - */ - rAF: bind(VENDORS._jsAPI, 0, 'requestAnimationFrame', false, function (func) { return window.setTimeout(func, 1000 / 60); }), - - /** - * Gets the CancelAnimationFrame method or it's corresponding polyfill. - * @returns {*|Function} The CancelAnimationFrame method or it's corresponding polyfill. - */ - cAF: bind(VENDORS._jsAPI, 0, 'cancelAnimationFrame', false, function (id) { return window.clearTimeout(id); }), - - /** - * Gets the current time. - * @returns {number} The current time. - */ - now: function() { - return Date.now && Date.now() || new Date().getTime(); - }, - - /** - * Stops the propagation of the given event. - * @param event The event of which the propagation shall be stoped. - */ - stpP: function(event) { - if(event.stopPropagation) - event.stopPropagation(); - else - event.cancelBubble = true; - }, - - /** - * Prevents the default action of the given event. - * @param event The event of which the default action shall be prevented. - */ - prvD: function(event) { - if(event.preventDefault && event.cancelable) - event.preventDefault(); - else - event.returnValue = false; - }, - - /** - * Gets the pageX and pageY values of the given mouse event. - * @param event The mouse event of which the pageX and pageX shall be got. - * @returns {{x: number, y: number}} x = pageX value, y = pageY value. - */ - page: function(event) { - event = event.originalEvent || event; - - var strPage = 'page'; - var strClient = 'client'; - var strX = 'X'; - var strY = 'Y'; - var target = event.target || event.srcElement || document; - var eventDoc = target.ownerDocument || document; - var doc = eventDoc.documentElement; - var body = eventDoc.body; - - //if touch event return return pageX/Y of it - if(event.touches !== undefined) { - var touch = event.touches[0]; - return { - x : touch[strPage + strX], - y : touch[strPage + strY] - } - } - - // Calculate pageX/Y if not native supported - if (!event[strPage + strX] && event[strClient + strX] && event[strClient + strX] != null) { - - return { - x : event[strClient + strX] + - (doc && doc.scrollLeft || body && body.scrollLeft || 0) - - (doc && doc.clientLeft || body && body.clientLeft || 0), - y : event[strClient + strY] + - (doc && doc.scrollTop || body && body.scrollTop || 0) - - (doc && doc.clientTop || body && body.clientTop || 0) - } - } - return { - x : event[strPage + strX], - y : event[strPage + strY] - }; - }, - - /** - * Gets the clicked mouse button of the given mouse event. - * @param event The mouse event of which the clicked button shal be got. - * @returns {number} The number of the clicked mouse button. (0 : none | 1 : leftButton | 2 : middleButton | 3 : rightButton) - */ - mBtn: function(event) { - var button = event.button; - if (!event.which && button !== undefined) - return (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); - else - return event.which; - }, - - /** - * Checks whether a item is in the given array and returns its index. - * @param item The item of which the position in the array shall be determined. - * @param arr The array. - * @returns {number} The zero based index of the item or -1 if the item isn't in the array. - */ - inA : function(item, arr) { - for (var i = 0; i < arr[LEXICON.l]; i++) - //Sometiems in IE a "SCRIPT70" Permission denied error occurs if HTML elements in a iFrame are compared - try { - if (arr[i] === item) - return i; - } - catch(e) { } - return -1; - }, - - /** - * Returns true if the given value is a array. - * @param arr The potential array. - * @returns {boolean} True if the given value is a array, false otherwise. - */ - isA: function(arr) { - var def = Array.isArray; - return def ? def(arr) : this.type(arr) == TYPES.a; - }, - - /** - * Determine the internal JavaScript [[Class]] of the given object. - * @param obj The object of which the type shall be determined. - * @returns {string} The type of the given object. - */ - type: function(obj) { - if (obj === undefined) - return obj + ''; - if (obj === null) - return obj + ''; - return Object[LEXICON.p].toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase(); - }, - - - bind: bind - - /** - * Gets the vendor-prefixed CSS property by the given name. - * For example the given name is "transform" and you're using a old Firefox browser then the returned value would be "-moz-transform". - * If the browser doesn't need a vendor-prefix, then the returned string is the given name. - * If the browser doesn't support the given property name at all (not even with a vendor-prefix) the returned value is null. - * @param propName The unprefixed CSS property name. - * @returns {string|null} The vendor-prefixed CSS property or null if the browser doesn't support the given CSS property. - - cssProp: function(propName) { - return VENDORS._cssProperty(propName); - } - */ - } - })(); - - var MATH = Math; - var JQUERY = framework; - var EASING = framework.easing; - var FRAMEWORK = framework; - var INSTANCES = (function () { - var _targets = []; - var _instancePropertyString = '__overlayScrollbars__'; - - /** - * Register, unregister or get a certain (or all) instances. - * Register: Pass the target and the instance. - * Unregister: Pass the target and null. - * Get Instance: Pass the target from which the instance shall be got. - * Get Targets: Pass no arguments. - * @param target The target to which the instance shall be registered / from which the instance shall be unregistered / the instance shall be got - * @param instance The instance. - * @returns {*|void} Returns the instance from the given target. - */ - return function (target, instance) { - var argLen = arguments[LEXICON.l]; - if (argLen < 1) { - //return all targets - return _targets; - } - else { - if (instance) { - //register instance - target[_instancePropertyString] = instance; - _targets.push(target); - } - else { - var index = COMPATIBILITY.inA(target, _targets); - if (index > -1) { - if (argLen > 1) { - //unregister instance - delete target[_instancePropertyString]; - _targets.splice(index, 1); - } - else { - //get instance from target - return _targets[index][_instancePropertyString]; - } - } - } - } - } - })(); - var PLUGIN = (function () { - var _plugin; - var _pluginsGlobals; - var _pluginsAutoUpdateLoop; - var _pluginsExtensions = []; - var _pluginsOptions = (function () { - var type = COMPATIBILITY.type; - var possibleTemplateTypes = [ - TYPES.b, //boolean - TYPES.n, //number - TYPES.s, //string - TYPES.a, //array - TYPES.o, //object - TYPES.f, //function - TYPES.z //null - ]; - var restrictedStringsSplit = ' '; - var restrictedStringsPossibilitiesSplit = ':'; - var classNameAllowedValues = [TYPES.z, TYPES.s]; - var numberAllowedValues = TYPES.n; - var booleanNullAllowedValues = [TYPES.z, TYPES.b]; - var booleanTrueTemplate = [true, TYPES.b]; - var booleanFalseTemplate = [false, TYPES.b]; - var callbackTemplate = [null, [TYPES.z, TYPES.f]]; - var inheritedAttrsTemplate = [['style', 'class'], [TYPES.s, TYPES.a, TYPES.z]]; - var resizeAllowedValues = 'n:none b:both h:horizontal v:vertical'; - var overflowBehaviorAllowedValues = 'v-h:visible-hidden v-s:visible-scroll s:scroll h:hidden'; - var scrollbarsVisibilityAllowedValues = 'v:visible h:hidden a:auto'; - var scrollbarsAutoHideAllowedValues = 'n:never s:scroll l:leave m:move'; - var optionsDefaultsAndTemplate = { - className: ['os-theme-dark', classNameAllowedValues], //null || string - resize: ['none', resizeAllowedValues], //none || both || horizontal || vertical || n || b || h || v - sizeAutoCapable: booleanTrueTemplate, //true || false - clipAlways: booleanTrueTemplate, //true || false - normalizeRTL: booleanTrueTemplate, //true || false - paddingAbsolute: booleanFalseTemplate, //true || false - autoUpdate: [null, booleanNullAllowedValues], //true || false || null - autoUpdateInterval: [33, numberAllowedValues], //number - nativeScrollbarsOverlaid: { - showNativeScrollbars: booleanFalseTemplate, //true || false - initialize: booleanTrueTemplate //true || false - }, - overflowBehavior: { - x: ['scroll', overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s - y: ['scroll', overflowBehaviorAllowedValues] //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s - }, - scrollbars: { - visibility: ['auto', scrollbarsVisibilityAllowedValues], //visible || hidden || auto || v || h || a - autoHide: ['never', scrollbarsAutoHideAllowedValues], //never || scroll || leave || move || n || s || l || m - autoHideDelay: [800, numberAllowedValues], //number - dragScrolling: booleanTrueTemplate, //true || false - clickScrolling: booleanFalseTemplate, //true || false - touchSupport: booleanTrueTemplate, //true || false - snapHandle: booleanFalseTemplate //true || false - }, - textarea: { - dynWidth: booleanFalseTemplate, //true || false - dynHeight: booleanFalseTemplate, //true || false - inheritedAttrs: inheritedAttrsTemplate //string || array || null - }, - callbacks: { - onInitialized: callbackTemplate, //null || function - onInitializationWithdrawn: callbackTemplate, //null || function - onDestroyed: callbackTemplate, //null || function - onScrollStart: callbackTemplate, //null || function - onScroll: callbackTemplate, //null || function - onScrollStop: callbackTemplate, //null || function - onOverflowChanged: callbackTemplate, //null || function - onOverflowAmountChanged: callbackTemplate, //null || function - onDirectionChanged: callbackTemplate, //null || function - onContentSizeChanged: callbackTemplate, //null || function - onHostSizeChanged: callbackTemplate, //null || function - onUpdated: callbackTemplate //null || function - } - }; - var convert = function (template) { - var recursive = function (obj) { - var key; - var val; - var valType; - for (key in obj) { - if (!obj[LEXICON.hOP](key)) - continue; - val = obj[key]; - valType = type(val); - if (valType == TYPES.a) - obj[key] = val[template ? 1 : 0]; - else if (valType == TYPES.o) - obj[key] = recursive(val); - } - return obj; - }; - return recursive(FRAMEWORK.extend(true, {}, optionsDefaultsAndTemplate)); - }; - - return { - _defaults: convert(), - - _template: convert(true), - - /** - * Validates the passed object by the passed template. - * @param obj The object which shall be validated. - * @param template The template which defines the allowed values and types. - * @param writeErrors True if errors shall be logged to the console. - * @param diffObj If a object is passed then only valid differences to this object will be returned. - * @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. - */ - _validate: function (obj, template, writeErrors, diffObj) { - var validatedOptions = {}; - var validatedOptionsPrepared = {}; - var objectCopy = FRAMEWORK.extend(true, {}, obj); - var inArray = FRAMEWORK.inArray; - var isEmptyObj = FRAMEWORK.isEmptyObject; - var checkObjectProps = function (data, template, diffData, validatedOptions, validatedOptionsPrepared, prevPropName) { - for (var prop in template) { - if (template[LEXICON.hOP](prop) && data[LEXICON.hOP](prop)) { - var isValid = false; - var isDiff = false; - var templateValue = template[prop]; - var templateValueType = type(templateValue); - var templateIsComplex = templateValueType == TYPES.o; - var templateTypes = type(templateValue) != TYPES.a ? [templateValue] : templateValue; - var dataDiffValue = diffData[prop]; - var dataValue = data[prop]; - var dataValueType = type(dataValue); - var propPrefix = prevPropName ? prevPropName + '.' : ''; - var error = "The option \"" + propPrefix + prop + "\" wasn't set, because"; - var errorPossibleTypes = []; - var errorRestrictedStrings = []; - var restrictedStringValuesSplit; - var restrictedStringValuesPossibilitiesSplit; - var isRestrictedValue; - var mainPossibility; - var currType; - var i; - var v; - var j; - - dataDiffValue = dataDiffValue === undefined ? {} : dataDiffValue; - - //if the template has a object as value, it means that the options are complex (verschachtelt) - if (templateIsComplex && dataValueType == TYPES.o) { - validatedOptions[prop] = {}; - validatedOptionsPrepared[prop] = {}; - checkObjectProps(dataValue, templateValue, dataDiffValue, validatedOptions[prop], validatedOptionsPrepared[prop], propPrefix + prop); - FRAMEWORK.each([data, validatedOptions, validatedOptionsPrepared], function (index, value) { - if (isEmptyObj(value[prop])) { - delete value[prop]; - } - }); - } - else if (!templateIsComplex) { - for (i = 0; i < templateTypes[LEXICON.l]; i++) { - currType = templateTypes[i]; - templateValueType = type(currType); - //if currtype is string and starts with restrictedStringPrefix and end with restrictedStringSuffix - isRestrictedValue = templateValueType == TYPES.s && inArray(currType, possibleTemplateTypes) === -1; - if (isRestrictedValue) { - errorPossibleTypes.push(TYPES.s); - - //split it into a array which contains all possible values for example: ["y:yes", "n:no", "m:maybe"] - restrictedStringValuesSplit = currType.split(restrictedStringsSplit); - errorRestrictedStrings = errorRestrictedStrings.concat(restrictedStringValuesSplit); - for (v = 0; v < restrictedStringValuesSplit[LEXICON.l]; v++) { - //split the possible values into their possibiliteis for example: ["y", "yes"] -> the first is always the mainPossibility - restrictedStringValuesPossibilitiesSplit = restrictedStringValuesSplit[v].split(restrictedStringsPossibilitiesSplit); - mainPossibility = restrictedStringValuesPossibilitiesSplit[0]; - for (j = 0; j < restrictedStringValuesPossibilitiesSplit[LEXICON.l]; j++) { - //if any possibility matches with the dataValue, its valid - if (dataValue === restrictedStringValuesPossibilitiesSplit[j]) { - isValid = true; - break; - } - } - if (isValid) - break; - } - } - else { - errorPossibleTypes.push(currType); - - if (dataValueType === currType) { - isValid = true; - break; - } - } - } - - if (isValid) { - isDiff = dataValue !== dataDiffValue; - - if (isDiff) - validatedOptions[prop] = dataValue; - - if (isRestrictedValue ? inArray(dataDiffValue, restrictedStringValuesPossibilitiesSplit) < 0 : isDiff) - validatedOptionsPrepared[prop] = isRestrictedValue ? mainPossibility : dataValue; - } - else if (writeErrors) { - console.warn(error + " it doesn't accept the type [ " + dataValueType.toUpperCase() + " ] with the value of \"" + dataValue + "\".\r\n" + - "Accepted types are: [ " + errorPossibleTypes.join(', ').toUpperCase() + " ]." + - (errorRestrictedStrings[length] > 0 ? "\r\nValid strings are: [ " + errorRestrictedStrings.join(', ').split(restrictedStringsPossibilitiesSplit).join(', ') + " ]." : '')); - } - delete data[prop]; - } - } - } - }; - checkObjectProps(objectCopy, template, diffObj || {}, validatedOptions, validatedOptionsPrepared); - - //add values which aren't specified in the template to the finished validated object to prevent them from being discarded - /* - if(keepForeignProps) { - FRAMEWORK.extend(true, validatedOptions, objectCopy); - FRAMEWORK.extend(true, validatedOptionsPrepared, objectCopy); - } - */ - - if (!isEmptyObj(objectCopy) && writeErrors) - console.warn('The following options are discarded due to invalidity:\r\n' + window.JSON.stringify(objectCopy, null, 2)); - - return { - _default: validatedOptions, - _prepared: validatedOptionsPrepared - }; - } - } - }()); - - /** - * Initializes the object which contains global information about the plugin and each instance of it. - */ - function initOverlayScrollbarsStatics() { - if (!_pluginsGlobals) - _pluginsGlobals = new OverlayScrollbarsGlobals(_pluginsOptions._defaults); - if (!_pluginsAutoUpdateLoop) - _pluginsAutoUpdateLoop = new OverlayScrollbarsAutoUpdateLoop(_pluginsGlobals); - } - - /** - * 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. - * @param defaultOptions - * @constructor - */ - function OverlayScrollbarsGlobals(defaultOptions) { - var _base = this; - var strOverflow = 'overflow'; - var strHidden = 'hidden'; - var strScroll = 'scroll'; - var bodyElement = FRAMEWORK('body'); - var scrollbarDummyElement = FRAMEWORK('
'); - var scrollbarDummyElement0 = scrollbarDummyElement[0]; - var dummyContainerChild = FRAMEWORK(scrollbarDummyElement.children('div').eq(0)); - - bodyElement.append(scrollbarDummyElement); - scrollbarDummyElement.hide().show(); //fix IE8 bug (incorrect measuring) - - var nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement0); - var nativeScrollbarIsOverlaid = { - x: nativeScrollbarSize.x === 0, - y: nativeScrollbarSize.y === 0 - }; - var msie = (function () { - var ua = window.navigator.userAgent; - var strIndexOf = 'indexOf'; - var strSubString = 'substring'; - var msie = ua[strIndexOf]('MSIE '); - var trident = ua[strIndexOf]('Trident/'); - var edge = ua[strIndexOf]('Edge/'); - var rv = ua[strIndexOf]('rv:'); - var result; - var parseIntFunc = parseInt; - - // IE 10 or older => return version number - if (msie > 0) - result = parseIntFunc(ua[strSubString](msie + 5, ua[strIndexOf]('.', msie)), 10); - - // IE 11 => return version number - else if (trident > 0) - result = parseIntFunc(ua[strSubString](rv + 3, ua[strIndexOf]('.', rv)), 10); - - // Edge (IE 12+) => return version number - else if (edge > 0) - result = parseIntFunc(ua[strSubString](edge + 5, ua[strIndexOf]('.', edge)), 10); - - // other browser - return result; - })(); - - FRAMEWORK.extend(_base, { - defaultOptions: defaultOptions, - msie: msie, - autoUpdateLoop: false, - autoUpdateRecommended: !COMPATIBILITY.mO(), - nativeScrollbarSize: nativeScrollbarSize, - nativeScrollbarIsOverlaid: nativeScrollbarIsOverlaid, - nativeScrollbarStyling: (function () { - var result = false; - scrollbarDummyElement.addClass('os-viewport-native-scrollbars-invisible'); - try { - result = (scrollbarDummyElement.css('scrollbar-width') === 'none' && (msie > 9 || !msie)) || window.getComputedStyle(scrollbarDummyElement0, '::-webkit-scrollbar').getPropertyValue('display') === 'none'; - } catch (ex) { } - - //fix opera bug: scrollbar styles will only appear if overflow value is scroll or auto during the activation of the style. - //and set overflow to scroll - //scrollbarDummyElement.css(strOverflow, strHidden).hide().css(strOverflow, strScroll).show(); - //return (scrollbarDummyElement0[LEXICON.oH] - scrollbarDummyElement0[LEXICON.cH]) === 0 && (scrollbarDummyElement0[LEXICON.oW] - scrollbarDummyElement0[LEXICON.cW]) === 0; - - return result; - })(), - overlayScrollbarDummySize: { x: 30, y: 30 }, - cssCalc: (function () { - var dummyStyle = document.createElement('div')[LEXICON.s]; - var strCalc = 'calc'; - var i = -1; - var prop; - - for (; i < VENDORS._cssPrefixes[LEXICON.l]; i++) { - prop = i < 0 ? strCalc : VENDORS._cssPrefixes[i] + strCalc; - dummyStyle.cssText = 'width:' + prop + '(1px);'; - if (dummyStyle[LEXICON.l]) - return prop; - } - return null; - })(), - restrictedMeasuring: (function () { - //https://bugzilla.mozilla.org/show_bug.cgi?id=1439305 - //since 1.11.0 always false -> fixed via CSS (hopefully) - scrollbarDummyElement.css(strOverflow, strHidden); - var scrollSize = { - w: scrollbarDummyElement0[LEXICON.sW], - h: scrollbarDummyElement0[LEXICON.sH] - }; - scrollbarDummyElement.css(strOverflow, 'visible'); - var scrollSize2 = { - w: scrollbarDummyElement0[LEXICON.sW], - h: scrollbarDummyElement0[LEXICON.sH] - }; - return (scrollSize.w - scrollSize2.w) !== 0 || (scrollSize.h - scrollSize2.h) !== 0; - })(), - rtlScrollBehavior: (function () { - scrollbarDummyElement.css({ 'overflow-y': strHidden, 'overflow-x': strScroll, 'direction': 'rtl' }).scrollLeft(0); - var dummyContainerOffset = scrollbarDummyElement.offset(); - var dummyContainerChildOffset = dummyContainerChild.offset(); - //https://github.com/KingSora/OverlayScrollbars/issues/187 - scrollbarDummyElement.scrollLeft(-999); - var dummyContainerChildOffsetAfterScroll = dummyContainerChild.offset(); - return { - //origin direction = determines if the zero scroll position is on the left or right side - //'i' means 'invert' (i === true means that the axis must be inverted to be correct) - //true = on the left side - //false = on the right side - i: dummyContainerOffset.left === dummyContainerChildOffset.left, - //negative = determines if the maximum scroll is positive or negative - //'n' means 'negate' (n === true means that the axis must be negated to be correct) - //true = negative - //false = positive - n: dummyContainerChildOffset.left !== dummyContainerChildOffsetAfterScroll.left - }; - })(), - supportTransform: VENDORS._cssProperty('transform') !== undefined, - supportTransition: VENDORS._cssProperty('transition') !== undefined, - supportPassiveEvents: (function () { - var supportsPassive = false; - try { - window.addEventListener('test', null, Object.defineProperty({}, 'passive', { - get: function () { - supportsPassive = true; - } - })); - } catch (e) { } - return supportsPassive; - })(), - supportResizeObserver: !!COMPATIBILITY.rO(), - supportMutationObserver: !!COMPATIBILITY.mO() - }); - - scrollbarDummyElement.removeAttr(LEXICON.s).remove(); - - //Catch zoom event: - (function () { - if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) - return; - - var abs = MATH.abs; - var windowWidth = COMPATIBILITY.wW(); - var windowHeight = COMPATIBILITY.wH(); - var windowDpr = getWindowDPR(); - var onResize = function () { - if (INSTANCES().length > 0) { - var newW = COMPATIBILITY.wW(); - var newH = COMPATIBILITY.wH(); - var deltaW = newW - windowWidth; - var deltaH = newH - windowHeight; - - if (deltaW === 0 && deltaH === 0) - return; - - var deltaWRatio = MATH.round(newW / (windowWidth / 100.0)); - var deltaHRatio = MATH.round(newH / (windowHeight / 100.0)); - var absDeltaW = abs(deltaW); - var absDeltaH = abs(deltaH); - var absDeltaWRatio = abs(deltaWRatio); - var absDeltaHRatio = abs(deltaHRatio); - var newDPR = getWindowDPR(); - - var deltaIsBigger = absDeltaW > 2 && absDeltaH > 2; - var difference = !differenceIsBiggerThanOne(absDeltaWRatio, absDeltaHRatio); - var dprChanged = newDPR !== windowDpr && windowDpr > 0; - var isZoom = deltaIsBigger && difference && dprChanged; - var oldScrollbarSize = _base.nativeScrollbarSize; - var newScrollbarSize; - - if (isZoom) { - bodyElement.append(scrollbarDummyElement); - newScrollbarSize = _base.nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement[0]); - scrollbarDummyElement.remove(); - if (oldScrollbarSize.x !== newScrollbarSize.x || oldScrollbarSize.y !== newScrollbarSize.y) { - FRAMEWORK.each(INSTANCES(), function () { - if (INSTANCES(this)) - INSTANCES(this).update('zoom'); - }); - } - } - - windowWidth = newW; - windowHeight = newH; - windowDpr = newDPR; - } - }; - - function differenceIsBiggerThanOne(valOne, valTwo) { - var absValOne = abs(valOne); - var absValTwo = abs(valTwo); - return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo); - } - - function getWindowDPR() { - var dDPI = window.screen.deviceXDPI || 0; - var sDPI = window.screen.logicalXDPI || 1; - return window.devicePixelRatio || (dDPI / sDPI); - } - - FRAMEWORK(window).on('resize', onResize); - })(); - - function calcNativeScrollbarSize(measureElement) { - return { - x: measureElement[LEXICON.oH] - measureElement[LEXICON.cH], - y: measureElement[LEXICON.oW] - measureElement[LEXICON.cW] - }; - } - } - - /** - * 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. - * @constructor - */ - function OverlayScrollbarsAutoUpdateLoop(globals) { - var _base = this; - var _inArray = FRAMEWORK.inArray; - var _getNow = COMPATIBILITY.now; - var _strAutoUpdate = 'autoUpdate'; - var _strAutoUpdateInterval = _strAutoUpdate + 'Interval'; - var _strLength = LEXICON.l; - var _loopingInstances = []; - var _loopingInstancesIntervalCache = []; - var _loopIsActive = false; - var _loopIntervalDefault = 33; - var _loopInterval = _loopIntervalDefault; - var _loopTimeOld = _getNow(); - var _loopID; - - - /** - * The auto update loop which will run every 50 milliseconds or less if the update interval of a instance is lower than 50 milliseconds. - */ - var loop = function () { - if (_loopingInstances[_strLength] > 0 && _loopIsActive) { - _loopID = COMPATIBILITY.rAF()(function () { - loop(); - }); - var timeNew = _getNow(); - var timeDelta = timeNew - _loopTimeOld; - var lowestInterval; - var instance; - var instanceOptions; - var instanceAutoUpdateAllowed; - var instanceAutoUpdateInterval; - var now; - - if (timeDelta > _loopInterval) { - _loopTimeOld = timeNew - (timeDelta % _loopInterval); - lowestInterval = _loopIntervalDefault; - for (var i = 0; i < _loopingInstances[_strLength]; i++) { - instance = _loopingInstances[i]; - if (instance !== undefined) { - instanceOptions = instance.options(); - instanceAutoUpdateAllowed = instanceOptions[_strAutoUpdate]; - instanceAutoUpdateInterval = MATH.max(1, instanceOptions[_strAutoUpdateInterval]); - now = _getNow(); - - if ((instanceAutoUpdateAllowed === true || instanceAutoUpdateAllowed === null) && (now - _loopingInstancesIntervalCache[i]) > instanceAutoUpdateInterval) { - instance.update('auto'); - _loopingInstancesIntervalCache[i] = new Date(now += instanceAutoUpdateInterval); - } - - lowestInterval = MATH.max(1, MATH.min(lowestInterval, instanceAutoUpdateInterval)); - } - } - _loopInterval = lowestInterval; - } - } else { - _loopInterval = _loopIntervalDefault; - } - }; - - /** - * Add OverlayScrollbars instance to the auto update loop. Only successful if the instance isn't already added. - * @param instance The instance which shall be updated in a loop automatically. - */ - _base.add = function (instance) { - if (_inArray(instance, _loopingInstances) === -1) { - _loopingInstances.push(instance); - _loopingInstancesIntervalCache.push(_getNow()); - if (_loopingInstances[_strLength] > 0 && !_loopIsActive) { - _loopIsActive = true; - globals.autoUpdateLoop = _loopIsActive; - loop(); - } - } - }; - - /** - * Remove OverlayScrollbars instance from the auto update loop. Only successful if the instance was added before. - * @param instance The instance which shall be updated in a loop automatically. - */ - _base.remove = function (instance) { - var index = _inArray(instance, _loopingInstances); - if (index > -1) { - //remove from loopingInstances list - _loopingInstancesIntervalCache.splice(index, 1); - _loopingInstances.splice(index, 1); - - //correct update loop behavior - if (_loopingInstances[_strLength] === 0 && _loopIsActive) { - _loopIsActive = false; - globals.autoUpdateLoop = _loopIsActive; - if (_loopID !== undefined) { - COMPATIBILITY.cAF()(_loopID); - _loopID = -1; - } - } - } - }; - } - - /** - * A object which manages the scrollbars visibility of the target element. - * @param pluginTargetElement The element from which the scrollbars shall be hidden. - * @param options The custom options. - * @param extensions The custom extensions. - * @param globals - * @param autoUpdateLoop - * @returns {*} - * @constructor - */ - function OverlayScrollbarsInstance(pluginTargetElement, options, extensions, globals, autoUpdateLoop) { - //shortcuts - var type = COMPATIBILITY.type; - var inArray = FRAMEWORK.inArray; - var each = FRAMEWORK.each; - - //make correct instanceof - var _base = new _plugin(); - var _frameworkProto = FRAMEWORK[LEXICON.p]; - - //if passed element is no HTML element: skip and return - if (!isHTMLElement(pluginTargetElement)) - return; - - //if passed element is already initialized: set passed options if there are any and return its instance - if (INSTANCES(pluginTargetElement)) { - var inst = INSTANCES(pluginTargetElement); - inst.options(options); - return inst; - } - - //globals: - var _nativeScrollbarIsOverlaid; - var _overlayScrollbarDummySize; - var _rtlScrollBehavior; - var _autoUpdateRecommended; - var _msieVersion; - var _nativeScrollbarStyling; - var _cssCalc; - var _nativeScrollbarSize; - var _supportTransition; - var _supportTransform; - var _supportPassiveEvents; - var _supportResizeObserver; - var _supportMutationObserver; - var _restrictedMeasuring; - - //general readonly: - var _initialized; - var _destroyed; - var _isTextarea; - var _isBody; - var _documentMixed; - var _domExists; - - //general: - var _isBorderBox; - var _sizeAutoObserverAdded; - var _paddingX; - var _paddingY; - var _borderX; - var _borderY; - var _marginX; - var _marginY; - var _isRTL; - var _sleeping; - var _contentBorderSize = {}; - var _scrollHorizontalInfo = {}; - var _scrollVerticalInfo = {}; - var _viewportSize = {}; - var _nativeScrollbarMinSize = {}; - - //naming: - var _strMinusHidden = '-hidden'; - var _strMarginMinus = 'margin-'; - var _strPaddingMinus = 'padding-'; - var _strBorderMinus = 'border-'; - var _strTop = 'top'; - var _strRight = 'right'; - var _strBottom = 'bottom'; - var _strLeft = 'left'; - var _strMinMinus = 'min-'; - var _strMaxMinus = 'max-'; - var _strWidth = 'width'; - var _strHeight = 'height'; - var _strFloat = 'float'; - var _strEmpty = ''; - var _strAuto = 'auto'; - var _strSync = 'sync'; - var _strScroll = 'scroll'; - var _strHundredPercent = '100%'; - var _strX = 'x'; - var _strY = 'y'; - var _strDot = '.'; - var _strSpace = ' '; - var _strScrollbar = 'scrollbar'; - var _strMinusHorizontal = '-horizontal'; - var _strMinusVertical = '-vertical'; - var _strScrollLeft = _strScroll + 'Left'; - var _strScrollTop = _strScroll + 'Top'; - var _strMouseTouchDownEvent = 'mousedown touchstart'; - var _strMouseTouchUpEvent = 'mouseup touchend touchcancel'; - var _strMouseTouchMoveEvent = 'mousemove touchmove'; - var _strMouseTouchEnter = 'mouseenter'; - var _strMouseTouchLeave = 'mouseleave'; - var _strKeyDownEvent = 'keydown'; - var _strKeyUpEvent = 'keyup'; - var _strSelectStartEvent = 'selectstart'; - var _strTransitionEndEvent = 'transitionend webkitTransitionEnd oTransitionEnd'; - var _strResizeObserverProperty = '__overlayScrollbarsRO__'; - - //class names: - var _cassNamesPrefix = 'os-'; - var _classNameHTMLElement = _cassNamesPrefix + 'html'; - var _classNameHostElement = _cassNamesPrefix + 'host'; - var _classNameHostTextareaElement = _classNameHostElement + '-textarea'; - var _classNameHostScrollbarHorizontalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusHorizontal + _strMinusHidden; - var _classNameHostScrollbarVerticalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusVertical + _strMinusHidden; - var _classNameHostTransition = _classNameHostElement + '-transition'; - var _classNameHostRTL = _classNameHostElement + '-rtl'; - var _classNameHostResizeDisabled = _classNameHostElement + '-resize-disabled'; - var _classNameHostScrolling = _classNameHostElement + '-scrolling'; - var _classNameHostOverflow = _classNameHostElement + '-overflow'; - var _classNameHostOverflowX = _classNameHostOverflow + '-x'; - var _classNameHostOverflowY = _classNameHostOverflow + '-y'; - var _classNameTextareaElement = _cassNamesPrefix + 'textarea'; - var _classNameTextareaCoverElement = _classNameTextareaElement + '-cover'; - var _classNamePaddingElement = _cassNamesPrefix + 'padding'; - var _classNameViewportElement = _cassNamesPrefix + 'viewport'; - var _classNameViewportNativeScrollbarsInvisible = _classNameViewportElement + '-native-scrollbars-invisible'; - var _classNameViewportNativeScrollbarsOverlaid = _classNameViewportElement + '-native-scrollbars-overlaid'; - var _classNameContentElement = _cassNamesPrefix + 'content'; - var _classNameContentArrangeElement = _cassNamesPrefix + 'content-arrange'; - var _classNameContentGlueElement = _cassNamesPrefix + 'content-glue'; - var _classNameSizeAutoObserverElement = _cassNamesPrefix + 'size-auto-observer'; - var _classNameResizeObserverElement = _cassNamesPrefix + 'resize-observer'; - var _classNameResizeObserverItemElement = _cassNamesPrefix + 'resize-observer-item'; - var _classNameResizeObserverItemFinalElement = _classNameResizeObserverItemElement + '-final'; - var _classNameTextInherit = _cassNamesPrefix + 'text-inherit'; - var _classNameScrollbar = _cassNamesPrefix + _strScrollbar; - var _classNameScrollbarTrack = _classNameScrollbar + '-track'; - var _classNameScrollbarTrackOff = _classNameScrollbarTrack + '-off'; - var _classNameScrollbarHandle = _classNameScrollbar + '-handle'; - var _classNameScrollbarHandleOff = _classNameScrollbarHandle + '-off'; - var _classNameScrollbarUnusable = _classNameScrollbar + '-unusable'; - var _classNameScrollbarAutoHidden = _classNameScrollbar + '-' + _strAuto + _strMinusHidden; - var _classNameScrollbarCorner = _classNameScrollbar + '-corner'; - var _classNameScrollbarCornerResize = _classNameScrollbarCorner + '-resize'; - var _classNameScrollbarCornerResizeB = _classNameScrollbarCornerResize + '-both'; - var _classNameScrollbarCornerResizeH = _classNameScrollbarCornerResize + _strMinusHorizontal; - var _classNameScrollbarCornerResizeV = _classNameScrollbarCornerResize + _strMinusVertical; - var _classNameScrollbarHorizontal = _classNameScrollbar + _strMinusHorizontal; - var _classNameScrollbarVertical = _classNameScrollbar + _strMinusVertical; - var _classNameDragging = _cassNamesPrefix + 'dragging'; - var _classNameThemeNone = _cassNamesPrefix + 'theme-none'; - var _classNamesDynamicDestroy = [ - _classNameViewportNativeScrollbarsInvisible, - _classNameViewportNativeScrollbarsOverlaid, - _classNameScrollbarTrackOff, - _classNameScrollbarHandleOff, - _classNameScrollbarUnusable, - _classNameScrollbarAutoHidden, - _classNameScrollbarCornerResize, - _classNameScrollbarCornerResizeB, - _classNameScrollbarCornerResizeH, - _classNameScrollbarCornerResizeV, - _classNameDragging].join(_strSpace); - - //callbacks: - var _callbacksInitQeueue = []; - - //attrs viewport shall inherit from target - var _viewportAttrsFromTarget = [LEXICON.ti]; - - //options: - var _defaultOptions; - var _currentOptions; - var _currentPreparedOptions; - - //extensions: - var _extensions = {}; - var _extensionsPrivateMethods = 'added removed on contract'; - - //update - var _lastUpdateTime; - var _swallowedUpdateHints = {}; - var _swallowedUpdateTimeout; - var _swallowUpdateLag = 42; - var _imgs = []; - - //DOM elements: - var _windowElement; - var _documentElement; - var _htmlElement; - var _bodyElement; - var _targetElement; //the target element of this OverlayScrollbars object - var _hostElement; //the host element of this OverlayScrollbars object -> may be the same as targetElement - var _sizeAutoObserverElement; //observes size auto changes - var _sizeObserverElement; //observes size and padding changes - var _paddingElement; //manages the padding - var _viewportElement; //is the viewport of our scrollbar model - var _contentElement; //the element which holds the content - var _contentArrangeElement; //is needed for correct sizing of the content element (only if native scrollbars are overlays) - var _contentGlueElement; //has always the size of the content element - var _textareaCoverElement; //only applied if target is a textarea element. Used for correct size calculation and for prevention of uncontrolled scrolling - var _scrollbarCornerElement; - var _scrollbarHorizontalElement; - var _scrollbarHorizontalTrackElement; - var _scrollbarHorizontalHandleElement; - var _scrollbarVerticalElement; - var _scrollbarVerticalTrackElement; - var _scrollbarVerticalHandleElement; - var _windowElementNative; - var _documentElementNative; - var _targetElementNative; - var _hostElementNative; - var _sizeAutoObserverElementNative; - var _sizeObserverElementNative; - var _paddingElementNative; - var _viewportElementNative; - var _contentElementNative; - - //Cache: - var _hostSizeCache; - var _contentScrollSizeCache; - var _arrangeContentSizeCache; - var _hasOverflowCache; - var _hideOverflowCache; - var _widthAutoCache; - var _heightAutoCache; - var _cssMaxValueCache; - var _cssBoxSizingCache; - var _cssPaddingCache; - var _cssBorderCache; - var _cssMarginCache; - var _cssDirectionCache; - var _cssDirectionDetectedCache; - var _paddingAbsoluteCache; - var _clipAlwaysCache; - var _contentGlueSizeCache; - var _overflowBehaviorCache; - var _overflowAmountCache; - var _ignoreOverlayScrollbarHidingCache; - var _autoUpdateCache; - var _sizeAutoCapableCache; - var _contentElementScrollSizeChangeDetectedCache; - var _hostElementSizeChangeDetectedCache; - var _scrollbarsVisibilityCache; - var _scrollbarsAutoHideCache; - var _scrollbarsClickScrollingCache; - var _scrollbarsDragScrollingCache; - var _resizeCache; - var _normalizeRTLCache; - var _classNameCache; - var _oldClassName; - var _textareaAutoWrappingCache; - var _textareaInfoCache; - var _textareaSizeCache; - var _textareaDynHeightCache; - var _textareaDynWidthCache; - var _bodyMinSizeCache; - var _displayIsHiddenCache; - var _updateAutoCache = {}; - - //MutationObserver: - var _mutationObserverHost; - var _mutationObserverContent; - var _mutationObserverHostCallback; - var _mutationObserverContentCallback; - var _mutationObserversConnected; - var _mutationObserverAttrsTextarea = ['wrap', 'cols', 'rows']; - var _mutationObserverAttrsHost = [LEXICON.i, LEXICON.c, LEXICON.s, 'open'].concat(_viewportAttrsFromTarget); - - //events: - var _destroyEvents = []; - - //textarea: - var _textareaHasFocus; - - //scrollbars: - var _scrollbarsAutoHideTimeoutId; - var _scrollbarsAutoHideMoveTimeoutId; - var _scrollbarsAutoHideDelay; - var _scrollbarsAutoHideNever; - var _scrollbarsAutoHideScroll; - var _scrollbarsAutoHideMove; - var _scrollbarsAutoHideLeave; - var _scrollbarsHandleHovered; - var _scrollbarsHandlesDefineScrollPos; - - //resize - var _resizeNone; - var _resizeBoth; - var _resizeHorizontal; - var _resizeVertical; - - - //==== Event Listener ====// - - /** - * Adds or removes a event listener from the given element. - * @param element The element to which the event listener shall be applied or removed. - * @param eventNames The name(s) of the events. - * @param listener The method which shall be called. - * @param remove True if the handler shall be removed, false or undefined if the handler shall be added. - */ - function setupResponsiveEventListener(element, eventNames, listener, remove, passive) { - var collected = type(eventNames) == TYPES.a && type(listener) == TYPES.a; - var method = remove ? 'removeEventListener' : 'addEventListener'; - var onOff = remove ? 'off' : 'on'; - var events = collected ? false : eventNames.split(_strSpace) - var i = 0; - - if (collected) { - for (; i < eventNames[LEXICON.l]; i++) - setupResponsiveEventListener(element, eventNames[i], listener[i], remove); - } - else { - for (; i < events[LEXICON.l]; i++) { - if (_supportPassiveEvents) - element[0][method](events[i], listener, { passive: passive || false }); - else - element[onOff](events[i], listener); - } - } - } - - - function addDestroyEventListener(element, eventNames, listener, passive) { - setupResponsiveEventListener(element, eventNames, listener, false, passive); - _destroyEvents.push(COMPATIBILITY.bind(setupResponsiveEventListener, 0, element, eventNames, listener, true, passive)); - } - - //==== Resize Observer ====// - - /** - * Adds or removes a resize observer from the given element. - * @param targetElement The element to which the resize observer shall be added or removed. - * @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. - */ - function setupResizeObserver(targetElement, onElementResizedCallback) { - if (targetElement) { - var resizeObserver = COMPATIBILITY.rO(); - var strAnimationStartEvent = 'animationstart mozAnimationStart webkitAnimationStart MSAnimationStart'; - var strChildNodes = 'childNodes'; - var constScroll = 3333333; - var callback = function () { - targetElement[_strScrollTop](constScroll)[_strScrollLeft](_isRTL ? _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll : constScroll); - onElementResizedCallback(); - }; - //add resize observer: - if (onElementResizedCallback) { - if (_supportResizeObserver) { - var element = targetElement.addClass('observed').append(generateDiv(_classNameResizeObserverElement)).contents()[0]; - var observer = element[_strResizeObserverProperty] = new resizeObserver(callback); - observer.observe(element); - } - else { - if (_msieVersion > 9 || !_autoUpdateRecommended) { - targetElement.prepend( - generateDiv(_classNameResizeObserverElement, - generateDiv({ c: _classNameResizeObserverItemElement, dir: 'ltr' }, - generateDiv(_classNameResizeObserverItemElement, - generateDiv(_classNameResizeObserverItemFinalElement) - ) + - generateDiv(_classNameResizeObserverItemElement, - generateDiv({ c: _classNameResizeObserverItemFinalElement, style: 'width: 200%; height: 200%' }) - ) - ) - ) - ); - - var observerElement = targetElement[0][strChildNodes][0][strChildNodes][0]; - var shrinkElement = FRAMEWORK(observerElement[strChildNodes][1]); - var expandElement = FRAMEWORK(observerElement[strChildNodes][0]); - var expandElementChild = FRAMEWORK(expandElement[0][strChildNodes][0]); - var widthCache = observerElement[LEXICON.oW]; - var heightCache = observerElement[LEXICON.oH]; - var isDirty; - var rAFId; - var currWidth; - var currHeight; - var factor = 2; - var nativeScrollbarSize = globals.nativeScrollbarSize; //care don't make changes to this object!!! - var reset = function () { - /* - var sizeResetWidth = observerElement[LEXICON.oW] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; - var sizeResetHeight = observerElement[LEXICON.oH] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; - var expandChildCSS = {}; - expandChildCSS[_strWidth] = sizeResetWidth; - expandChildCSS[_strHeight] = sizeResetHeight; - expandElementChild.css(expandChildCSS); - - - expandElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); - shrinkElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); - */ - expandElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); - shrinkElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); - }; - var onResized = function () { - rAFId = 0; - if (!isDirty) - return; - - widthCache = currWidth; - heightCache = currHeight; - callback(); - }; - var onScroll = function (event) { - currWidth = observerElement[LEXICON.oW]; - currHeight = observerElement[LEXICON.oH]; - isDirty = currWidth != widthCache || currHeight != heightCache; - - if (event && isDirty && !rAFId) { - COMPATIBILITY.cAF()(rAFId); - rAFId = COMPATIBILITY.rAF()(onResized); - } - else if (!event) - onResized(); - - reset(); - if (event) { - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - return false; - }; - var expandChildCSS = {}; - var observerElementCSS = {}; - - setTopRightBottomLeft(observerElementCSS, _strEmpty, [ - -((nativeScrollbarSize.y + 1) * factor), - nativeScrollbarSize.x * -factor, - nativeScrollbarSize.y * -factor, - -((nativeScrollbarSize.x + 1) * factor) - ]); - - FRAMEWORK(observerElement).css(observerElementCSS); - expandElement.on(_strScroll, onScroll); - shrinkElement.on(_strScroll, onScroll); - targetElement.on(strAnimationStartEvent, function () { - onScroll(false); - }); - //lets assume that the divs will never be that large and a constant value is enough - expandChildCSS[_strWidth] = constScroll; - expandChildCSS[_strHeight] = constScroll; - expandElementChild.css(expandChildCSS); - - reset(); - } - else { - var attachEvent = _documentElementNative.attachEvent; - var isIE = _msieVersion !== undefined; - if (attachEvent) { - targetElement.prepend(generateDiv(_classNameResizeObserverElement)); - findFirst(targetElement, _strDot + _classNameResizeObserverElement)[0].attachEvent('onresize', callback); - } - else { - var obj = _documentElementNative.createElement(TYPES.o); - obj.setAttribute(LEXICON.ti, '-1'); - obj.setAttribute(LEXICON.c, _classNameResizeObserverElement); - obj.onload = function () { - var wnd = this.contentDocument.defaultView; - wnd.addEventListener('resize', callback); - wnd.document.documentElement.style.display = 'none'; - }; - obj.type = 'text/html'; - if (isIE) - targetElement.prepend(obj); - obj.data = 'about:blank'; - if (!isIE) - targetElement.prepend(obj); - targetElement.on(strAnimationStartEvent, callback); - } - } - } - - if (targetElement[0] === _sizeObserverElementNative) { - var directionChanged = function () { - var dir = _hostElement.css('direction'); - var css = {}; - var scrollLeftValue = 0; - var result = false; - if (dir !== _cssDirectionDetectedCache) { - if (dir === 'ltr') { - css[_strLeft] = 0; - css[_strRight] = _strAuto; - scrollLeftValue = constScroll; - } - else { - css[_strLeft] = _strAuto; - css[_strRight] = 0; - scrollLeftValue = _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll; - } - //execution order is important for IE!!! - _sizeObserverElement.children().eq(0).css(css); - _sizeObserverElement[_strScrollLeft](scrollLeftValue)[_strScrollTop](constScroll); - _cssDirectionDetectedCache = dir; - result = true; - } - return result; - }; - directionChanged(); - addDestroyEventListener(targetElement, _strScroll, function (event) { - if (directionChanged()) - update(); - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - return false; - }); - } - } - //remove resize observer: - else { - if (_supportResizeObserver) { - var element = targetElement.contents()[0]; - var resizeObserverObj = element[_strResizeObserverProperty]; - if (resizeObserverObj) { - resizeObserverObj.disconnect(); - delete element[_strResizeObserverProperty]; - } - } - else { - remove(targetElement.children(_strDot + _classNameResizeObserverElement).eq(0)); - } - } - } - } - - /** - * Freezes or unfreezes the given resize observer. - * @param targetElement The element to which the target resize observer is applied. - * @param freeze True if the resize observer shall be frozen, false otherwise. - - function freezeResizeObserver(targetElement, freeze) { - if (targetElement !== undefined) { - if(freeze) { - if (_supportResizeObserver) { - var element = targetElement.contents()[0]; - element[_strResizeObserverProperty].unobserve(element); - } - else { - targetElement = targetElement.children(_strDot + _classNameResizeObserverElement).eq(0); - var w = targetElement.css(_strWidth); - var h = targetElement.css(_strHeight); - var css = {}; - css[_strWidth] = w; - css[_strHeight] = h; - targetElement.css(css); - } - } - else { - if (_supportResizeObserver) { - var element = targetElement.contents()[0]; - element[_strResizeObserverProperty].observe(element); - } - else { - var css = { }; - css[_strHeight] = _strEmpty; - css[_strWidth] = _strEmpty; - targetElement.children(_strDot + _classNameResizeObserverElement).eq(0).css(css); - } - } - } - } - */ - - - //==== Mutation Observers ====// - - /** - * Creates MutationObservers for the host and content Element if they are supported. - */ - function createMutationObservers() { - if (_supportMutationObserver) { - var mutationObserverContentLag = 11; - var mutationObserver = COMPATIBILITY.mO(); - var contentLastUpdate = COMPATIBILITY.now(); - var mutationTarget; - var mutationAttrName; - var contentTimeout; - var now; - var sizeAuto; - var action; - - _mutationObserverHostCallback = function (mutations) { - var doUpdate = false; - var mutation; - var mutatedAttrs = []; - - if (_initialized && !_sleeping) { - each(mutations, function () { - mutation = this; - mutationTarget = mutation.target; - mutationAttrName = mutation.attributeName; - - if(!doUpdate) { - if (mutationAttrName === LEXICON.c) - doUpdate = hostClassNamesChanged(mutation.oldValue, mutationTarget.className); - else if (mutationAttrName === LEXICON.s) - doUpdate = mutation.oldValue !== mutationTarget[LEXICON.s].cssText; - else - doUpdate = true; - } - - mutatedAttrs.push(mutationAttrName); - }); - - updateViewportAttrsFromTarget(mutatedAttrs); - - if (doUpdate) - _base.update(_strAuto); - } - return doUpdate; - }; - _mutationObserverContentCallback = function (mutations) { - var doUpdate = false; - var mutation; - - if (_initialized && !_sleeping) { - each(mutations, function () { - mutation = this; - doUpdate = isUnknownMutation(mutation); - return !doUpdate; - }); - - if (doUpdate) { - now = COMPATIBILITY.now(); - sizeAuto = (_heightAutoCache || _widthAutoCache); - action = function () { - if (!_destroyed) { - contentLastUpdate = now; - - //if cols, rows or wrap attr was changed - if (_isTextarea) - textareaUpdate(); - - if (sizeAuto) - update(); - else - _base.update(_strAuto); - } - }; - clearTimeout(contentTimeout); - if (mutationObserverContentLag <= 0 || now - contentLastUpdate > mutationObserverContentLag || !sizeAuto) - action(); - else - contentTimeout = setTimeout(action, mutationObserverContentLag); - } - } - return doUpdate; - } - - _mutationObserverHost = new mutationObserver(_mutationObserverHostCallback); - _mutationObserverContent = new mutationObserver(_mutationObserverContentCallback); - } - } - - /** - * Connects the MutationObservers if they are supported. - */ - function connectMutationObservers() { - if (_supportMutationObserver && !_mutationObserversConnected) { - _mutationObserverHost.observe(_hostElementNative, { - attributes: true, - attributeOldValue: true, - attributeFilter: _mutationObserverAttrsHost - }); - - _mutationObserverContent.observe(_isTextarea ? _targetElementNative : _contentElementNative, { - attributes: true, - attributeOldValue: true, - subtree: !_isTextarea, - childList: !_isTextarea, - characterData: !_isTextarea, - attributeFilter: _isTextarea ? _mutationObserverAttrsTextarea : _mutationObserverAttrsHost - }); - - _mutationObserversConnected = true; - } - } - - /** - * Disconnects the MutationObservers if they are supported. - */ - function disconnectMutationObservers() { - if (_supportMutationObserver && _mutationObserversConnected) { - _mutationObserverHost.disconnect(); - _mutationObserverContent.disconnect(); - - _mutationObserversConnected = false; - } - } - - - //==== Events of elements ====// - - /** - * This method gets called every time the host element gets resized. IMPORTANT: Padding changes are detected too!! - * It refreshes the hostResizedEventArgs and the hostSizeResizeCache. - * If there are any size changes, the update method gets called. - */ - function hostOnResized() { - if (!_sleeping) { - var changed; - var hostSize = { - w: _sizeObserverElementNative[LEXICON.sW], - h: _sizeObserverElementNative[LEXICON.sH] - }; - - changed = checkCache(hostSize, _hostElementSizeChangeDetectedCache); - _hostElementSizeChangeDetectedCache = hostSize; - if (changed) - update({ _hostSizeChanged: true }); - } - } - - /** - * The mouse enter event of the host element. This event is only needed for the autoHide feature. - */ - function hostOnMouseEnter() { - if (_scrollbarsAutoHideLeave) - refreshScrollbarsAutoHide(true); - } - - /** - * The mouse leave event of the host element. This event is only needed for the autoHide feature. - */ - function hostOnMouseLeave() { - if (_scrollbarsAutoHideLeave && !_bodyElement.hasClass(_classNameDragging)) - refreshScrollbarsAutoHide(false); - } - - /** - * The mouse move event of the host element. This event is only needed for the autoHide "move" feature. - */ - function hostOnMouseMove() { - if (_scrollbarsAutoHideMove) { - refreshScrollbarsAutoHide(true); - clearTimeout(_scrollbarsAutoHideMoveTimeoutId); - _scrollbarsAutoHideMoveTimeoutId = setTimeout(function () { - if (_scrollbarsAutoHideMove && !_destroyed) - refreshScrollbarsAutoHide(false); - }, 100); - } - } - - /** - * Prevents text from deselection if attached to the document element on the mousedown event of a DOM element. - * @param event The select start event. - */ - function documentOnSelectStart(event) { - COMPATIBILITY.prvD(event); - return false; - } - - /** - * A callback which will be called after a img element has downloaded its src asynchronous. - */ - function imgOnLoad() { - update({ _contentSizeChanged: true }); - } - - /** - * Adds or removes mouse & touch events of the host element. (for handling auto-hiding of the scrollbars) - * @param destroy Indicates whether the events shall be added or removed. - */ - function setupHostMouseTouchEvents(destroy) { - setupResponsiveEventListener(_hostElement, - _strMouseTouchMoveEvent, - hostOnMouseMove, - (_scrollbarsAutoHideMove ? destroy : true), true); - setupResponsiveEventListener(_hostElement, - [_strMouseTouchEnter, _strMouseTouchLeave], - [hostOnMouseEnter, hostOnMouseLeave], - (_scrollbarsAutoHideMove ? true : destroy), true); - - //if the plugin is initialized and the mouse is over the host element, make the scrollbars visible - if (!_initialized && !destroy) - _hostElement.one('mouseover', hostOnMouseEnter); - } - - - //==== Update Detection ====// - - /** - * Measures the min width and min height of the body element and refreshes the related cache. - * @returns {boolean} True if the min width or min height has changed, false otherwise. - */ - function bodyMinSizeChanged() { - var bodyMinSize = {}; - if (_isBody && _contentArrangeElement) { - bodyMinSize.w = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strWidth)); - bodyMinSize.h = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strHeight)); - bodyMinSize.c = checkCache(bodyMinSize, _bodyMinSizeCache); - bodyMinSize.f = true; //flag for "measured at least once" - } - _bodyMinSizeCache = bodyMinSize; - return !!bodyMinSize.c; - } - - /** - * Returns true if the class names really changed (new class without plugin host prefix) - * @param oldCassNames The old ClassName string. - * @param newClassNames The new ClassName string. - * @returns {boolean} True if the class names has really changed, false otherwise. - */ - function hostClassNamesChanged(oldCassNames, newClassNames) { - var currClasses = (newClassNames !== undefined && newClassNames !== null) ? newClassNames.split(_strSpace) : _strEmpty; - var oldClasses = (oldCassNames !== undefined && oldCassNames !== null) ? oldCassNames.split(_strSpace) : _strEmpty; - if (currClasses === _strEmpty && oldClasses === _strEmpty) - return false; - var diff = getArrayDifferences(oldClasses, currClasses); - var changed = false; - var oldClassNames = _oldClassName !== undefined && _oldClassName !== null ? _oldClassName.split(_strSpace) : [_strEmpty]; - var currClassNames = _classNameCache !== undefined && _classNameCache !== null ? _classNameCache.split(_strSpace) : [_strEmpty]; - - //remove none theme from diff list to prevent update - var idx = inArray(_classNameThemeNone, diff); - var curr; - var i; - var v; - var o; - var c; - - if (idx > -1) - diff.splice(idx, 1); - - for (i = 0; i < diff.length; i++) { - curr = diff[i]; - if (curr.indexOf(_classNameHostElement) !== 0) { - o = true; - c = true; - for (v = 0; v < oldClassNames.length; v++) { - if (curr === oldClassNames[v]) { - o = false; - break; - } - } - for (v = 0; v < currClassNames.length; v++) { - if (curr === currClassNames[v]) { - c = false; - break; - } - } - if (o && c) { - changed = true; - break; - } - } - - } - return changed; - } - - /** - * 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. - * @param mutation The mutation which shall be checked. - * @returns {boolean} True if the mutation is from a unknown element, false otherwise. - */ - function isUnknownMutation(mutation) { - var attributeName = mutation.attributeName; - var mutationTarget = mutation.target; - var mutationType = mutation.type; - var strClosest = 'closest'; - - if (mutationTarget === _contentElementNative) - return attributeName === null; - if (mutationType === 'attributes' && (attributeName === LEXICON.c || attributeName === LEXICON.s) && !_isTextarea) { - //ignore className changes by the plugin - if (attributeName === LEXICON.c && FRAMEWORK(mutationTarget).hasClass(_classNameHostElement)) - return hostClassNamesChanged(mutation.oldValue, mutationTarget.getAttribute(LEXICON.c)); - - //only do it of browser support it natively - if (typeof mutationTarget[strClosest] != TYPES.f) - return true; - if (mutationTarget[strClosest](_strDot + _classNameResizeObserverElement) !== null || - mutationTarget[strClosest](_strDot + _classNameScrollbar) !== null || - mutationTarget[strClosest](_strDot + _classNameScrollbarCorner) !== null) - return false; - } - return true; - } - - /** - * Returns true if the content size was changed since the last time this method was called. - * @returns {boolean} True if the content size was changed, false otherwise. - */ - function updateAutoContentSizeChanged() { - if (_sleeping) - return false; - - var contentMeasureElement = getContentMeasureElement(); - var textareaValueLength = _isTextarea && _widthAutoCache && !_textareaAutoWrappingCache ? _targetElement.val().length : 0; - var setCSS = !_mutationObserversConnected && _widthAutoCache && !_isTextarea; - var css = {}; - var float; - var bodyMinSizeC; - var changed; - var contentElementScrollSize; - - if (setCSS) { - float = _contentElement.css(_strFloat); - css[_strFloat] = _isRTL ? _strRight : _strLeft; - css[_strWidth] = _strAuto; - _contentElement.css(css); - } - contentElementScrollSize = { - w: contentMeasureElement[LEXICON.sW] + textareaValueLength, - h: contentMeasureElement[LEXICON.sH] + textareaValueLength - }; - if (setCSS) { - css[_strFloat] = float; - css[_strWidth] = _strHundredPercent; - _contentElement.css(css); - } - - bodyMinSizeC = bodyMinSizeChanged(); - changed = checkCache(contentElementScrollSize, _contentElementScrollSizeChangeDetectedCache); - - _contentElementScrollSizeChangeDetectedCache = contentElementScrollSize; - - return changed || bodyMinSizeC; - } - - /** - * Returns true when a attribute which the MutationObserver would observe has changed. - * @returns {boolean} True if one of the attributes which a MutationObserver would observe has changed, false or undefined otherwise. - */ - function meaningfulAttrsChanged() { - if (_sleeping || _mutationObserversConnected) - return; - - var elem; - var curr; - var cache; - var changedAttrs = []; - var checks = [ - { - _elem: _hostElement, - _attrs: _mutationObserverAttrsHost.concat(':visible') - }, - { - _elem: _isTextarea ? _targetElement : undefined, - _attrs: _mutationObserverAttrsTextarea - } - ]; - - each(checks, function (index, check) { - elem = check._elem; - if (elem) { - each(check._attrs, function (index, attr) { - curr = attr.charAt(0) === ':' ? elem.is(attr) : elem.attr(attr); - cache = _updateAutoCache[attr]; - - if(checkCache(curr, cache)) { - changedAttrs.push(attr); - } - - _updateAutoCache[attr] = curr; - }); - } - }); - - updateViewportAttrsFromTarget(changedAttrs); - - return changedAttrs[LEXICON.l] > 0; - } - - /** - * Checks is a CSS Property of a child element is affecting the scroll size of the content. - * @param propertyName The CSS property name. - * @returns {boolean} True if the property is affecting the content scroll size, false otherwise. - */ - function isSizeAffectingCSSProperty(propertyName) { - if (!_initialized) - return true; - var flexGrow = 'flex-grow'; - var flexShrink = 'flex-shrink'; - var flexBasis = 'flex-basis'; - var affectingPropsX = [ - _strWidth, - _strMinMinus + _strWidth, - _strMaxMinus + _strWidth, - _strMarginMinus + _strLeft, - _strMarginMinus + _strRight, - _strLeft, - _strRight, - 'font-weight', - 'word-spacing', - flexGrow, - flexShrink, - flexBasis - ]; - var affectingPropsXContentBox = [ - _strPaddingMinus + _strLeft, - _strPaddingMinus + _strRight, - _strBorderMinus + _strLeft + _strWidth, - _strBorderMinus + _strRight + _strWidth - ]; - var affectingPropsY = [ - _strHeight, - _strMinMinus + _strHeight, - _strMaxMinus + _strHeight, - _strMarginMinus + _strTop, - _strMarginMinus + _strBottom, - _strTop, - _strBottom, - 'line-height', - flexGrow, - flexShrink, - flexBasis - ]; - var affectingPropsYContentBox = [ - _strPaddingMinus + _strTop, - _strPaddingMinus + _strBottom, - _strBorderMinus + _strTop + _strWidth, - _strBorderMinus + _strBottom + _strWidth - ]; - var _strS = 's'; - var _strVS = 'v-s'; - var checkX = _overflowBehaviorCache.x === _strS || _overflowBehaviorCache.x === _strVS; - var checkY = _overflowBehaviorCache.y === _strS || _overflowBehaviorCache.y === _strVS; - var sizeIsAffected = false; - var checkPropertyName = function (arr, name) { - for (var i = 0; i < arr[LEXICON.l]; i++) { - if (arr[i] === name) - return true; - } - return false; - }; - - if (checkY) { - sizeIsAffected = checkPropertyName(affectingPropsY, propertyName); - if (!sizeIsAffected && !_isBorderBox) - sizeIsAffected = checkPropertyName(affectingPropsYContentBox, propertyName); - } - if (checkX && !sizeIsAffected) { - sizeIsAffected = checkPropertyName(affectingPropsX, propertyName); - if (!sizeIsAffected && !_isBorderBox) - sizeIsAffected = checkPropertyName(affectingPropsXContentBox, propertyName); - } - return sizeIsAffected; - } - - - //==== Update ====// - - /** - * Sets the attribute values of the viewport element to the values from the target element. - * The value of a attribute is only set if the attribute is whitelisted. - * @attrs attrs The array of attributes which shall be set or undefined if all whitelisted shall be set. - */ - function updateViewportAttrsFromTarget(attrs) { - attrs = attrs || _viewportAttrsFromTarget; - each(attrs, function (index, attr) { - if (COMPATIBILITY.inA(attr, _viewportAttrsFromTarget) > -1) { - var targetAttr = _targetElement.attr(attr); - if(type(targetAttr) == TYPES.s) { - _viewportElement.attr(attr, targetAttr); - } - else { - _viewportElement.removeAttr(attr); - } - } - }); - } - - /** - * Updates the variables and size of the textarea element, and manages the scroll on new line or new character. - */ - function textareaUpdate() { - if (!_sleeping) { - var wrapAttrOff = !_textareaAutoWrappingCache; - var minWidth = _viewportSize.w; - var minHeight = _viewportSize.h; - var css = {}; - var doMeasure = _widthAutoCache || wrapAttrOff; - var origWidth; - var width; - var origHeight; - var height; - - //reset min size - css[_strMinMinus + _strWidth] = _strEmpty; - css[_strMinMinus + _strHeight] = _strEmpty; - - //set width auto - css[_strWidth] = _strAuto; - _targetElement.css(css); - - //measure width - origWidth = _targetElementNative[LEXICON.oW]; - width = doMeasure ? MATH.max(origWidth, _targetElementNative[LEXICON.sW] - 1) : 1; - /*width += (_widthAutoCache ? _marginX + (!_isBorderBox ? wrapAttrOff ? 0 : _paddingX + _borderX : 0) : 0);*/ - - //set measured width - css[_strWidth] = _widthAutoCache ? _strAuto /*width*/ : _strHundredPercent; - css[_strMinMinus + _strWidth] = _strHundredPercent; - - //set height auto - css[_strHeight] = _strAuto; - _targetElement.css(css); - - //measure height - origHeight = _targetElementNative[LEXICON.oH]; - height = MATH.max(origHeight, _targetElementNative[LEXICON.sH] - 1); - - //append correct size values - css[_strWidth] = width; - css[_strHeight] = height; - _textareaCoverElement.css(css); - - //apply min width / min height to prevent textarea collapsing - css[_strMinMinus + _strWidth] = minWidth /*+ (!_isBorderBox && _widthAutoCache ? _paddingX + _borderX : 0)*/; - css[_strMinMinus + _strHeight] = minHeight /*+ (!_isBorderBox && _heightAutoCache ? _paddingY + _borderY : 0)*/; - _targetElement.css(css); - - return { - _originalWidth: origWidth, - _originalHeight: origHeight, - _dynamicWidth: width, - _dynamicHeight: height - }; - } - } - - /** - * Updates the plugin and DOM to the current options. - * This method should only be called if a update is 100% required. - * @param updateHints A objects which contains hints for this update: - * { - * _hostSizeChanged : boolean, - * _contentSizeChanged : boolean, - * _force : boolean, == preventSwallowing - * _changedOptions : { }, == preventSwallowing && preventSleep - * } - */ - function update(updateHints) { - clearTimeout(_swallowedUpdateTimeout); - updateHints = updateHints || {}; - _swallowedUpdateHints._hostSizeChanged |= updateHints._hostSizeChanged; - _swallowedUpdateHints._contentSizeChanged |= updateHints._contentSizeChanged; - _swallowedUpdateHints._force |= updateHints._force; - - var now = COMPATIBILITY.now(); - var hostSizeChanged = !!_swallowedUpdateHints._hostSizeChanged; - var contentSizeChanged = !!_swallowedUpdateHints._contentSizeChanged; - var force = !!_swallowedUpdateHints._force; - var changedOptions = updateHints._changedOptions; - var swallow = _swallowUpdateLag > 0 && _initialized && !_destroyed && !force && !changedOptions && (now - _lastUpdateTime) < _swallowUpdateLag && (!_heightAutoCache && !_widthAutoCache); - var displayIsHidden; - - if (swallow) - _swallowedUpdateTimeout = setTimeout(update, _swallowUpdateLag); - - //abort update due to: - //destroyed - //swallowing - //sleeping - //host is hidden or has false display - if (_destroyed || swallow || (_sleeping && !changedOptions) || (_initialized && !force && (displayIsHidden = _hostElement.is(':hidden'))) || _hostElement.css('display') === 'inline') - return; - - _lastUpdateTime = now; - _swallowedUpdateHints = {}; - - //if scrollbar styling is possible and native scrollbars aren't overlaid the scrollbar styling will be applied which hides the native scrollbars completely. - if (_nativeScrollbarStyling && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { - //native scrollbars are hidden, so change the values to zero - _nativeScrollbarSize.x = 0; - _nativeScrollbarSize.y = 0; - } - else { - //refresh native scrollbar size (in case of zoom) - _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); - } - - // Scrollbar padding is needed for firefox, because firefox hides scrollbar automatically if the size of the div is too small. - // The calculation: [scrollbar size +3 *3] - // (+3 because of possible decoration e.g. borders, margins etc., but only if native scrollbar is NOT a overlaid scrollbar) - // (*3 because (1)increase / (2)decrease -button and (3)resize handle) - _nativeScrollbarMinSize = { - x: (_nativeScrollbarSize.x + (_nativeScrollbarIsOverlaid.x ? 0 : 3)) * 3, - y: (_nativeScrollbarSize.y + (_nativeScrollbarIsOverlaid.y ? 0 : 3)) * 3 - }; - - //changedOptions = changedOptions || { }; - //freezeResizeObserver(_sizeObserverElement, true); - //freezeResizeObserver(_sizeAutoObserverElement, true); - - var checkCacheAutoForce = function () { - return checkCache.apply(this, [].slice.call(arguments).concat([force])); - }; - - //save current scroll offset - var currScroll = { - x: _viewportElement[_strScrollLeft](), - y: _viewportElement[_strScrollTop]() - }; - - var currentPreparedOptionsScrollbars = _currentPreparedOptions.scrollbars; - var currentPreparedOptionsTextarea = _currentPreparedOptions.textarea; - - //scrollbars visibility: - var scrollbarsVisibility = currentPreparedOptionsScrollbars.visibility; - var scrollbarsVisibilityChanged = checkCacheAutoForce(scrollbarsVisibility, _scrollbarsVisibilityCache); - - //scrollbars autoHide: - var scrollbarsAutoHide = currentPreparedOptionsScrollbars.autoHide; - var scrollbarsAutoHideChanged = checkCacheAutoForce(scrollbarsAutoHide, _scrollbarsAutoHideCache); - - //scrollbars click scrolling - var scrollbarsClickScrolling = currentPreparedOptionsScrollbars.clickScrolling; - var scrollbarsClickScrollingChanged = checkCacheAutoForce(scrollbarsClickScrolling, _scrollbarsClickScrollingCache); - - //scrollbars drag scrolling - var scrollbarsDragScrolling = currentPreparedOptionsScrollbars.dragScrolling; - var scrollbarsDragScrollingChanged = checkCacheAutoForce(scrollbarsDragScrolling, _scrollbarsDragScrollingCache); - - //className - var className = _currentPreparedOptions.className; - var classNameChanged = checkCacheAutoForce(className, _classNameCache); - - //resize - var resize = _currentPreparedOptions.resize; - var resizeChanged = checkCacheAutoForce(resize, _resizeCache) && !_isBody; //body can't be resized since the window itself acts as resize possibility. - - //paddingAbsolute - var paddingAbsolute = _currentPreparedOptions.paddingAbsolute; - var paddingAbsoluteChanged = checkCacheAutoForce(paddingAbsolute, _paddingAbsoluteCache); - - //clipAlways - var clipAlways = _currentPreparedOptions.clipAlways; - var clipAlwaysChanged = checkCacheAutoForce(clipAlways, _clipAlwaysCache); - - //sizeAutoCapable - var sizeAutoCapable = _currentPreparedOptions.sizeAutoCapable && !_isBody; //body can never be size auto, because it shall be always as big as the viewport. - var sizeAutoCapableChanged = checkCacheAutoForce(sizeAutoCapable, _sizeAutoCapableCache); - - //showNativeScrollbars - var ignoreOverlayScrollbarHiding = _currentPreparedOptions.nativeScrollbarsOverlaid.showNativeScrollbars; - var ignoreOverlayScrollbarHidingChanged = checkCacheAutoForce(ignoreOverlayScrollbarHiding, _ignoreOverlayScrollbarHidingCache); - - //autoUpdate - var autoUpdate = _currentPreparedOptions.autoUpdate; - var autoUpdateChanged = checkCacheAutoForce(autoUpdate, _autoUpdateCache); - - //overflowBehavior - var overflowBehavior = _currentPreparedOptions.overflowBehavior; - var overflowBehaviorChanged = checkCacheAutoForce(overflowBehavior, _overflowBehaviorCache, force); - - //dynWidth: - var textareaDynWidth = currentPreparedOptionsTextarea.dynWidth; - var textareaDynWidthChanged = checkCacheAutoForce(_textareaDynWidthCache, textareaDynWidth); - - //dynHeight: - var textareaDynHeight = currentPreparedOptionsTextarea.dynHeight; - var textareaDynHeightChanged = checkCacheAutoForce(_textareaDynHeightCache, textareaDynHeight); - - //scrollbars visibility - _scrollbarsAutoHideNever = scrollbarsAutoHide === 'n'; - _scrollbarsAutoHideScroll = scrollbarsAutoHide === 's'; - _scrollbarsAutoHideMove = scrollbarsAutoHide === 'm'; - _scrollbarsAutoHideLeave = scrollbarsAutoHide === 'l'; - - //scrollbars autoHideDelay - _scrollbarsAutoHideDelay = currentPreparedOptionsScrollbars.autoHideDelay; - - //old className - _oldClassName = _classNameCache; - - //resize - _resizeNone = resize === 'n'; - _resizeBoth = resize === 'b'; - _resizeHorizontal = resize === 'h'; - _resizeVertical = resize === 'v'; - - //normalizeRTL - _normalizeRTLCache = _currentPreparedOptions.normalizeRTL; - - //ignore overlay scrollbar hiding - ignoreOverlayScrollbarHiding = ignoreOverlayScrollbarHiding && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y); - - //refresh options cache - _scrollbarsVisibilityCache = scrollbarsVisibility; - _scrollbarsAutoHideCache = scrollbarsAutoHide; - _scrollbarsClickScrollingCache = scrollbarsClickScrolling; - _scrollbarsDragScrollingCache = scrollbarsDragScrolling; - _classNameCache = className; - _resizeCache = resize; - _paddingAbsoluteCache = paddingAbsolute; - _clipAlwaysCache = clipAlways; - _sizeAutoCapableCache = sizeAutoCapable; - _ignoreOverlayScrollbarHidingCache = ignoreOverlayScrollbarHiding; - _autoUpdateCache = autoUpdate; - _overflowBehaviorCache = extendDeep({}, overflowBehavior); - _textareaDynWidthCache = textareaDynWidth; - _textareaDynHeightCache = textareaDynHeight; - _hasOverflowCache = _hasOverflowCache || { x: false, y: false }; - - //set correct class name to the host element - if (classNameChanged) { - removeClass(_hostElement, _oldClassName + _strSpace + _classNameThemeNone); - addClass(_hostElement, className !== undefined && className !== null && className.length > 0 ? className : _classNameThemeNone); - } - - //set correct auto Update - if (autoUpdateChanged) { - if (autoUpdate === true) { - disconnectMutationObservers(); - autoUpdateLoop.add(_base); - } - else if (autoUpdate === null) { - if (_autoUpdateRecommended) { - disconnectMutationObservers(); - autoUpdateLoop.add(_base); - } - else { - autoUpdateLoop.remove(_base); - connectMutationObservers(); - } - } - else { - autoUpdateLoop.remove(_base); - connectMutationObservers(); - } - } - - //activate or deactivate size auto capability - if (sizeAutoCapableChanged) { - if (sizeAutoCapable) { - if (!_contentGlueElement) { - _contentGlueElement = FRAMEWORK(generateDiv(_classNameContentGlueElement)); - _paddingElement.before(_contentGlueElement); - } - else { - _contentGlueElement.show(); - } - if (_sizeAutoObserverAdded) { - _sizeAutoObserverElement.show(); - } - else { - _sizeAutoObserverElement = FRAMEWORK(generateDiv(_classNameSizeAutoObserverElement)); - _sizeAutoObserverElementNative = _sizeAutoObserverElement[0]; - - _contentGlueElement.before(_sizeAutoObserverElement); - var oldSize = { w: -1, h: -1 }; - setupResizeObserver(_sizeAutoObserverElement, function () { - var newSize = { - w: _sizeAutoObserverElementNative[LEXICON.oW], - h: _sizeAutoObserverElementNative[LEXICON.oH] - }; - if (checkCache(newSize, oldSize)) { - if (_initialized && (_heightAutoCache && newSize.h > 0) || (_widthAutoCache && newSize.w > 0)) { - update(); - } - else if (_initialized && (!_heightAutoCache && newSize.h === 0) || (!_widthAutoCache && newSize.w === 0)) { - update(); - } - } - oldSize = newSize; - }); - _sizeAutoObserverAdded = true; - //fix heightAuto detector bug if height is fixed but contentHeight is 0. - //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. - if (_cssCalc !== null) - _sizeAutoObserverElement.css(_strHeight, _cssCalc + '(100% + 1px)'); - } - } - else { - if (_sizeAutoObserverAdded) - _sizeAutoObserverElement.hide(); - if (_contentGlueElement) - _contentGlueElement.hide(); - } - } - - //if force, update all resizeObservers too - if (force) { - _sizeObserverElement.find('*').trigger(_strScroll); - if (_sizeAutoObserverAdded) - _sizeAutoObserverElement.find('*').trigger(_strScroll); - } - - //display hidden: - displayIsHidden = displayIsHidden === undefined ? _hostElement.is(':hidden') : displayIsHidden; - var displayIsHiddenChanged = checkCacheAutoForce(displayIsHidden, _displayIsHiddenCache); - - //textarea AutoWrapping: - var textareaAutoWrapping = _isTextarea ? _targetElement.attr('wrap') !== 'off' : false; - var textareaAutoWrappingChanged = checkCacheAutoForce(textareaAutoWrapping, _textareaAutoWrappingCache); - - //detect direction: - var cssDirection = _hostElement.css('direction'); - var cssDirectionChanged = checkCacheAutoForce(cssDirection, _cssDirectionCache); - - //detect box-sizing: - var boxSizing = _hostElement.css('box-sizing'); - var boxSizingChanged = checkCacheAutoForce(boxSizing, _cssBoxSizingCache); - - //detect padding: - var padding = { - c: force, - t: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strTop)), - r: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strRight)), - b: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strBottom)), - l: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strLeft)) - }; - - //width + height auto detecting var: - var sizeAutoObserverElementBCRect; - //exception occurs in IE8 sometimes (unknown exception) - try { - sizeAutoObserverElementBCRect = _sizeAutoObserverAdded ? _sizeAutoObserverElementNative[LEXICON.bCR]() : null; - } catch (ex) { - return; - } - - _isRTL = cssDirection === 'rtl'; - _isBorderBox = (boxSizing === 'border-box'); - var isRTLLeft = _isRTL ? _strLeft : _strRight; - var isRTLRight = _isRTL ? _strRight : _strLeft; - - //detect width auto: - var widthAutoResizeDetection = false; - var widthAutoObserverDetection = (_sizeAutoObserverAdded && (_hostElement.css(_strFloat) !== 'none' /*|| _isTextarea */)) ? (MATH.round(sizeAutoObserverElementBCRect.right - sizeAutoObserverElementBCRect.left) === 0) && (!paddingAbsolute ? (_hostElementNative[LEXICON.cW] - _paddingX) > 0 : true) : false; - if (sizeAutoCapable && !widthAutoObserverDetection) { - var tmpCurrHostWidth = _hostElementNative[LEXICON.oW]; - var tmpCurrContentGlueWidth = _contentGlueElement.css(_strWidth); - _contentGlueElement.css(_strWidth, _strAuto); - - var tmpNewHostWidth = _hostElementNative[LEXICON.oW]; - _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); - widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; - if (!widthAutoResizeDetection) { - _contentGlueElement.css(_strWidth, tmpCurrHostWidth + 1); - tmpNewHostWidth = _hostElementNative[LEXICON.oW]; - _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); - widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; - } - } - var widthAuto = (widthAutoObserverDetection || widthAutoResizeDetection) && sizeAutoCapable && !displayIsHidden; - var widthAutoChanged = checkCacheAutoForce(widthAuto, _widthAutoCache); - var wasWidthAuto = !widthAuto && _widthAutoCache; - - //detect height auto: - var heightAuto = _sizeAutoObserverAdded && sizeAutoCapable && !displayIsHidden ? (MATH.round(sizeAutoObserverElementBCRect.bottom - sizeAutoObserverElementBCRect.top) === 0) /* && (!paddingAbsolute && (_msieVersion > 9 || !_msieVersion) ? true : true) */ : false; - var heightAutoChanged = checkCacheAutoForce(heightAuto, _heightAutoCache); - var wasHeightAuto = !heightAuto && _heightAutoCache; - - //detect border: - //we need the border only if border box and auto size - var strMinusWidth = '-' + _strWidth; - var updateBorderX = (widthAuto && _isBorderBox) || !_isBorderBox; - var updateBorderY = (heightAuto && _isBorderBox) || !_isBorderBox; - var border = { - c: force, - t: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strTop + strMinusWidth), true) : 0, - r: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strRight + strMinusWidth), true) : 0, - b: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strBottom + strMinusWidth), true) : 0, - l: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strLeft + strMinusWidth), true) : 0 - }; - - //detect margin: - var margin = { - c: force, - t: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strTop)), - r: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strRight)), - b: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strBottom)), - l: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strLeft)) - }; - - //detect css max width & height: - var cssMaxValue = { - h: String(_hostElement.css(_strMaxMinus + _strHeight)), - w: String(_hostElement.css(_strMaxMinus + _strWidth)) - }; - - //vars to apply correct css - var contentElementCSS = {}; - var contentGlueElementCSS = {}; - - //funcs - var getHostSize = function () { - //has to be clientSize because offsetSize respect borders - return { - w: _hostElementNative[LEXICON.cW], - h: _hostElementNative[LEXICON.cH] - }; - }; - var getViewportSize = function () { - //viewport size is padding container because it never has padding, margin and a border - //determine zoom rounding error -> sometimes scrollWidth/Height is smaller than clientWidth/Height - //if this happens add the difference to the viewportSize to compensate the rounding error - return { - w: _paddingElementNative[LEXICON.oW] + MATH.max(0, _contentElementNative[LEXICON.cW] - _contentElementNative[LEXICON.sW]), - h: _paddingElementNative[LEXICON.oH] + MATH.max(0, _contentElementNative[LEXICON.cH] - _contentElementNative[LEXICON.sH]) - }; - }; - - //set info for padding - var paddingAbsoluteX = _paddingX = padding.l + padding.r; - var paddingAbsoluteY = _paddingY = padding.t + padding.b; - paddingAbsoluteX *= paddingAbsolute ? 1 : 0; - paddingAbsoluteY *= paddingAbsolute ? 1 : 0; - padding.c = checkCacheAutoForce(padding, _cssPaddingCache); - - //set info for border - _borderX = border.l + border.r; - _borderY = border.t + border.b; - border.c = checkCacheAutoForce(border, _cssBorderCache); - - //set info for margin - _marginX = margin.l + margin.r; - _marginY = margin.t + margin.b; - margin.c = checkCacheAutoForce(margin, _cssMarginCache); - - //set info for css max value - cssMaxValue.ih = parseToZeroOrNumber(cssMaxValue.h); //ih = integer height - cssMaxValue.iw = parseToZeroOrNumber(cssMaxValue.w); //iw = integer width - cssMaxValue.ch = cssMaxValue.h.indexOf('px') > -1; //ch = correct height - cssMaxValue.cw = cssMaxValue.w.indexOf('px') > -1; //cw = correct width - cssMaxValue.c = checkCacheAutoForce(cssMaxValue, _cssMaxValueCache); - - //refresh cache - _displayIsHiddenCache = displayIsHidden; - _textareaAutoWrappingCache = textareaAutoWrapping; - _cssDirectionCache = cssDirection; - _cssBoxSizingCache = boxSizing; - _widthAutoCache = widthAuto; - _heightAutoCache = heightAuto; - _cssPaddingCache = padding; - _cssBorderCache = border; - _cssMarginCache = margin; - _cssMaxValueCache = cssMaxValue; - - //IEFix direction changed - if (cssDirectionChanged && _sizeAutoObserverAdded) - _sizeAutoObserverElement.css(_strFloat, isRTLRight); - - //apply padding: - if (padding.c || cssDirectionChanged || paddingAbsoluteChanged || widthAutoChanged || heightAutoChanged || boxSizingChanged || sizeAutoCapableChanged) { - var paddingElementCSS = {}; - var textareaCSS = {}; - setTopRightBottomLeft(contentGlueElementCSS, _strMarginMinus, [-padding.t, -padding.r, -padding.b, -padding.l]); - if (paddingAbsolute) { - setTopRightBottomLeft(paddingElementCSS, _strEmpty, [padding.t, padding.r, padding.b, padding.l]); - if (_isTextarea) - setTopRightBottomLeft(textareaCSS, _strPaddingMinus); - else - setTopRightBottomLeft(contentElementCSS, _strPaddingMinus); - } - else { - setTopRightBottomLeft(paddingElementCSS, _strEmpty); - if (_isTextarea) - setTopRightBottomLeft(textareaCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); - else - setTopRightBottomLeft(contentElementCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); - } - _paddingElement.css(paddingElementCSS); - _targetElement.css(textareaCSS); - } - - //viewport size is padding container because it never has padding, margin and a border. - _viewportSize = getViewportSize(); - - //update Textarea - var textareaSize = _isTextarea ? textareaUpdate() : false; - var textareaSizeChanged = _isTextarea && checkCacheAutoForce(textareaSize, _textareaSizeCache); - var textareaDynOrigSize = _isTextarea && textareaSize ? { - w: textareaDynWidth ? textareaSize._dynamicWidth : textareaSize._originalWidth, - h: textareaDynHeight ? textareaSize._dynamicHeight : textareaSize._originalHeight - } : {}; - _textareaSizeCache = textareaSize; - - //fix height auto / width auto in cooperation with current padding & boxSizing behavior: - if (heightAuto && (heightAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c)) { - /* - if (cssMaxValue.ch) - contentElementCSS[_strMaxMinus + _strHeight] = - (cssMaxValue.ch ? (cssMaxValue.ih - paddingAbsoluteY + (_isBorderBox ? -_borderY : _paddingY)) - : _strEmpty); - */ - contentElementCSS[_strHeight] = _strAuto; - } - else if (heightAutoChanged || paddingAbsoluteChanged) { - contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; - contentElementCSS[_strHeight] = _strHundredPercent; - } - if (widthAuto && (widthAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c || cssDirectionChanged)) { - /* - if (cssMaxValue.cw) - contentElementCSS[_strMaxMinus + _strWidth] = - (cssMaxValue.cw ? (cssMaxValue.iw - paddingAbsoluteX + (_isBorderBox ? -_borderX : _paddingX)) + - (_nativeScrollbarIsOverlaid.y ? _overlayScrollbarDummySize.y : 0) - : _strEmpty); - */ - contentElementCSS[_strWidth] = _strAuto; - contentGlueElementCSS[_strMaxMinus + _strWidth] = _strHundredPercent; //IE Fix - } - else if (widthAutoChanged || paddingAbsoluteChanged) { - contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; - contentElementCSS[_strWidth] = _strHundredPercent; - contentElementCSS[_strFloat] = _strEmpty; - contentGlueElementCSS[_strMaxMinus + _strWidth] = _strEmpty; //IE Fix - } - if (widthAuto) { - if (!cssMaxValue.cw) - contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; - //textareaDynOrigSize.w || _strAuto :: doesnt works because applied margin will shift width - contentGlueElementCSS[_strWidth] = _strAuto; - - contentElementCSS[_strWidth] = _strAuto; - contentElementCSS[_strFloat] = isRTLRight; - } - else { - contentGlueElementCSS[_strWidth] = _strEmpty; - } - if (heightAuto) { - if (!cssMaxValue.ch) - contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; - //textareaDynOrigSize.h || _contentElementNative[LEXICON.cH] :: use for anti scroll jumping - contentGlueElementCSS[_strHeight] = textareaDynOrigSize.h || _contentElementNative[LEXICON.cH]; - } - else { - contentGlueElementCSS[_strHeight] = _strEmpty; - } - if (sizeAutoCapable) - _contentGlueElement.css(contentGlueElementCSS); - _contentElement.css(contentElementCSS); - - //CHECKPOINT HERE ~ - contentElementCSS = {}; - contentGlueElementCSS = {}; - - //if [content(host) client / scroll size, or target element direction, or content(host) max-sizes] changed, or force is true - if (hostSizeChanged || contentSizeChanged || textareaSizeChanged || cssDirectionChanged || boxSizingChanged || paddingAbsoluteChanged || widthAutoChanged || widthAuto || heightAutoChanged || heightAuto || cssMaxValue.c || ignoreOverlayScrollbarHidingChanged || overflowBehaviorChanged || clipAlwaysChanged || resizeChanged || scrollbarsVisibilityChanged || scrollbarsAutoHideChanged || scrollbarsDragScrollingChanged || scrollbarsClickScrollingChanged || textareaDynWidthChanged || textareaDynHeightChanged || textareaAutoWrappingChanged) { - var strOverflow = 'overflow'; - var strOverflowX = strOverflow + '-x'; - var strOverflowY = strOverflow + '-y'; - var strHidden = 'hidden'; - var strVisible = 'visible'; - - //Reset the viewport (very important for natively overlaid scrollbars and zoom change - //don't change the overflow prop as it is very expensive and affects performance !A LOT! - if(!_nativeScrollbarStyling) { - var viewportElementResetCSS = {}; - var resetXTmp = _hasOverflowCache.y && _hideOverflowCache.ys && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.y ? _viewportElement.css(isRTLLeft) : -_nativeScrollbarSize.y) : 0; - var resetBottomTmp = _hasOverflowCache.x && _hideOverflowCache.xs && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.x ? _viewportElement.css(_strBottom) : -_nativeScrollbarSize.x) : 0; - setTopRightBottomLeft(viewportElementResetCSS, _strEmpty); - _viewportElement.css(viewportElementResetCSS); - } - - //measure several sizes: - var contentMeasureElement = getContentMeasureElement(); - //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 - var contentSize = { - //use clientSize because natively overlaidScrollbars add borders - w: textareaDynOrigSize.w || contentMeasureElement[LEXICON.cW], - h: textareaDynOrigSize.h || contentMeasureElement[LEXICON.cH] - }; - var scrollSize = { - w: contentMeasureElement[LEXICON.sW], - h: contentMeasureElement[LEXICON.sH] - }; - - //apply the correct viewport style and measure viewport size - if(!_nativeScrollbarStyling) { - viewportElementResetCSS[_strBottom] = wasHeightAuto ? _strEmpty : resetBottomTmp; - viewportElementResetCSS[isRTLLeft] = wasWidthAuto ? _strEmpty : resetXTmp; - _viewportElement.css(viewportElementResetCSS); - } - _viewportSize = getViewportSize(); - - //measure and correct several sizes - var hostSize = getHostSize(); - var contentGlueSize = { - //client/scrollSize + AbsolutePadding -> because padding is only applied to the paddingElement if its absolute, so you have to add it manually - //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 - w: MATH.max((widthAuto ? contentSize.w : scrollSize.w) + paddingAbsoluteX, hostSize.w), - h: MATH.max((heightAuto ? contentSize.h : scrollSize.h) + paddingAbsoluteY, hostSize.h) - }; - contentGlueSize.c = checkCacheAutoForce(contentGlueSize, _contentGlueSizeCache); - _contentGlueSizeCache = contentGlueSize; - - //apply correct contentGlue size - if (sizeAutoCapable) { - //size contentGlue correctly to make sure the element has correct size if the sizing switches to auto - if (contentGlueSize.c || (heightAuto || widthAuto)) { - contentGlueElementCSS[_strWidth] = contentGlueSize.w; - contentGlueElementCSS[_strHeight] = contentGlueSize.h; - - //textarea-sizes are already calculated correctly at this point - if (!_isTextarea) { - contentSize = { - //use clientSize because natively overlaidScrollbars add borders - w: contentMeasureElement[LEXICON.cW], - h: contentMeasureElement[LEXICON.cH] - }; - } - } - var textareaCoverCSS = {}; - var setContentGlueElementCSSfunction = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var wh = scrollbarVars._w_h; - var strWH = scrollbarVars._width_height; - var autoSize = horizontal ? widthAuto : heightAuto; - var borderSize = horizontal ? _borderX : _borderY; - var paddingSize = horizontal ? _paddingX : _paddingY; - var marginSize = horizontal ? _marginX : _marginY; - var maxSize = contentGlueElementCSS[strWH] + (_isBorderBox ? borderSize : -paddingSize); - - //make contentGlue size -1 if element is not auto sized, to make sure that a resize event happens when the element shrinks - if (!autoSize || (!autoSize && border.c)) - contentGlueElementCSS[strWH] = hostSize[wh] - (_isBorderBox ? 0 : paddingSize + borderSize) - 1 - marginSize; - - //if size is auto and host is same size as max size, make content glue size +1 to make sure size changes will be detected - if (autoSize && cssMaxValue['c' + wh] && cssMaxValue['i' + wh] === maxSize) - contentGlueElementCSS[strWH] = maxSize + (_isBorderBox ? 0 : paddingSize) + 1; - - //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) - if (autoSize && (contentSize[wh] < _viewportSize[wh]) && (horizontal && _isTextarea ? !textareaAutoWrapping : true)) { - if (_isTextarea) - textareaCoverCSS[strWH] = parseToZeroOrNumber(_textareaCoverElement.css(strWH)) - 1; - contentGlueElementCSS[strWH] -= 1; - } - - //make sure content glue size is at least 1 - if (contentSize[wh] > 0) - contentGlueElementCSS[strWH] = MATH.max(1, contentGlueElementCSS[strWH]); - }; - setContentGlueElementCSSfunction(true); - setContentGlueElementCSSfunction(false); - - if (_isTextarea) - _textareaCoverElement.css(textareaCoverCSS); - _contentGlueElement.css(contentGlueElementCSS); - } - if (widthAuto) - contentElementCSS[_strWidth] = _strHundredPercent; - if (widthAuto && !_isBorderBox && !_mutationObserversConnected) - contentElementCSS[_strFloat] = 'none'; - - //apply and reset content style - _contentElement.css(contentElementCSS); - contentElementCSS = {}; - - //measure again, but this time all correct sizes: - var contentScrollSize = { - w: contentMeasureElement[LEXICON.sW], - h: contentMeasureElement[LEXICON.sH], - }; - contentScrollSize.c = contentSizeChanged = checkCacheAutoForce(contentScrollSize, _contentScrollSizeCache); - _contentScrollSizeCache = contentScrollSize; - - //refresh viewport size after correct measuring - _viewportSize = getViewportSize(); - - hostSize = getHostSize(); - hostSizeChanged = checkCacheAutoForce(hostSize, _hostSizeCache); - _hostSizeCache = hostSize; - - var hideOverflowForceTextarea = _isTextarea && (_viewportSize.w === 0 || _viewportSize.h === 0); - var previousOverflowAmount = _overflowAmountCache; - var overflowBehaviorIsVS = {}; - var overflowBehaviorIsVH = {}; - var overflowBehaviorIsS = {}; - var overflowAmount = {}; - var hasOverflow = {}; - var hideOverflow = {}; - var canScroll = {}; - var viewportRect = _paddingElementNative[LEXICON.bCR](); - var setOverflowVariables = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var scrollbarVarsInverted = getScrollbarVars(!horizontal); - var xyI = scrollbarVarsInverted._x_y; - var xy = scrollbarVars._x_y; - var wh = scrollbarVars._w_h; - var widthHeight = scrollbarVars._width_height; - var scrollMax = _strScroll + scrollbarVars._Left_Top + 'Max'; - var fractionalOverflowAmount = viewportRect[widthHeight] ? MATH.abs(viewportRect[widthHeight] - _viewportSize[wh]) : 0; - var checkFractionalOverflowAmount = previousOverflowAmount && previousOverflowAmount[xy] > 0 && _viewportElementNative[scrollMax] === 0; - overflowBehaviorIsVS[xy] = overflowBehavior[xy] === 'v-s'; - overflowBehaviorIsVH[xy] = overflowBehavior[xy] === 'v-h'; - overflowBehaviorIsS[xy] = overflowBehavior[xy] === 's'; - overflowAmount[xy] = MATH.max(0, MATH.round((contentScrollSize[wh] - _viewportSize[wh]) * 100) / 100); - overflowAmount[xy] *= (hideOverflowForceTextarea || (checkFractionalOverflowAmount && fractionalOverflowAmount > 0 && fractionalOverflowAmount < 1)) ? 0 : 1; - hasOverflow[xy] = overflowAmount[xy] > 0; - - //hideOverflow: - //x || y : true === overflow is hidden by "overflow: scroll" OR "overflow: hidden" - //xs || ys : true === overflow is hidden by "overflow: scroll" - hideOverflow[xy] = overflowBehaviorIsVS[xy] || overflowBehaviorIsVH[xy] ? (hasOverflow[xyI] && !overflowBehaviorIsVS[xyI] && !overflowBehaviorIsVH[xyI]) : hasOverflow[xy]; - hideOverflow[xy + 's'] = hideOverflow[xy] ? (overflowBehaviorIsS[xy] || overflowBehaviorIsVS[xy]) : false; - - canScroll[xy] = hasOverflow[xy] && hideOverflow[xy + 's']; - }; - setOverflowVariables(true); - setOverflowVariables(false); - - overflowAmount.c = checkCacheAutoForce(overflowAmount, _overflowAmountCache); - _overflowAmountCache = overflowAmount; - hasOverflow.c = checkCacheAutoForce(hasOverflow, _hasOverflowCache); - _hasOverflowCache = hasOverflow; - hideOverflow.c = checkCacheAutoForce(hideOverflow, _hideOverflowCache); - _hideOverflowCache = hideOverflow; - - //if native scrollbar is overlay at x OR y axis, prepare DOM - if (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y) { - var borderDesign = 'px solid transparent'; - var contentArrangeElementCSS = {}; - var arrangeContent = {}; - var arrangeChanged = force; - var setContentElementCSS; - - if (hasOverflow.x || hasOverflow.y) { - arrangeContent.w = _nativeScrollbarIsOverlaid.y && hasOverflow.y ? contentScrollSize.w + _overlayScrollbarDummySize.y : _strEmpty; - arrangeContent.h = _nativeScrollbarIsOverlaid.x && hasOverflow.x ? contentScrollSize.h + _overlayScrollbarDummySize.x : _strEmpty; - arrangeChanged = checkCacheAutoForce(arrangeContent, _arrangeContentSizeCache); - _arrangeContentSizeCache = arrangeContent; - } - - if (hasOverflow.c || hideOverflow.c || contentScrollSize.c || cssDirectionChanged || widthAutoChanged || heightAutoChanged || widthAuto || heightAuto || ignoreOverlayScrollbarHidingChanged) { - contentElementCSS[_strMarginMinus + isRTLRight] = contentElementCSS[_strBorderMinus + isRTLRight] = _strEmpty; - setContentElementCSS = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var scrollbarVarsInverted = getScrollbarVars(!horizontal); - var xy = scrollbarVars._x_y; - var strDirection = horizontal ? _strBottom : isRTLLeft; - var invertedAutoSize = horizontal ? heightAuto : widthAuto; - - if (_nativeScrollbarIsOverlaid[xy] && hasOverflow[xy] && hideOverflow[xy + 's']) { - contentElementCSS[_strMarginMinus + strDirection] = invertedAutoSize ? (ignoreOverlayScrollbarHiding ? _strEmpty : _overlayScrollbarDummySize[xy]) : _strEmpty; - contentElementCSS[_strBorderMinus + strDirection] = ((horizontal ? !invertedAutoSize : true) && !ignoreOverlayScrollbarHiding) ? (_overlayScrollbarDummySize[xy] + borderDesign) : _strEmpty; - } - else { - arrangeContent[scrollbarVarsInverted._w_h] = - contentElementCSS[_strMarginMinus + strDirection] = - contentElementCSS[_strBorderMinus + strDirection] = _strEmpty; - arrangeChanged = true; - } - }; - - if (_nativeScrollbarStyling) { - if (ignoreOverlayScrollbarHiding) - removeClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); - else - addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); - } - else { - setContentElementCSS(true); - setContentElementCSS(false); - } - } - if (ignoreOverlayScrollbarHiding) { - arrangeContent.w = arrangeContent.h = _strEmpty; - arrangeChanged = true; - } - if (arrangeChanged && !_nativeScrollbarStyling) { - contentArrangeElementCSS[_strWidth] = hideOverflow.y ? arrangeContent.w : _strEmpty; - contentArrangeElementCSS[_strHeight] = hideOverflow.x ? arrangeContent.h : _strEmpty; - - if (!_contentArrangeElement) { - _contentArrangeElement = FRAMEWORK(generateDiv(_classNameContentArrangeElement)); - _viewportElement.prepend(_contentArrangeElement); - } - _contentArrangeElement.css(contentArrangeElementCSS); - } - _contentElement.css(contentElementCSS); - } - - var viewportElementCSS = {}; - var paddingElementCSS = {}; - var setViewportCSS; - if (hostSizeChanged || hasOverflow.c || hideOverflow.c || contentScrollSize.c || overflowBehaviorChanged || boxSizingChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged || clipAlwaysChanged || heightAutoChanged) { - viewportElementCSS[isRTLRight] = _strEmpty; - setViewportCSS = function (horizontal) { - var scrollbarVars = getScrollbarVars(horizontal); - var scrollbarVarsInverted = getScrollbarVars(!horizontal); - var xy = scrollbarVars._x_y; - var XY = scrollbarVars._X_Y; - var strDirection = horizontal ? _strBottom : isRTLLeft; - - var reset = function () { - viewportElementCSS[strDirection] = _strEmpty; - _contentBorderSize[scrollbarVarsInverted._w_h] = 0; - }; - if (hasOverflow[xy] && hideOverflow[xy + 's']) { - viewportElementCSS[strOverflow + XY] = _strScroll; - if (ignoreOverlayScrollbarHiding || _nativeScrollbarStyling) { - reset(); - } - else { - viewportElementCSS[strDirection] = -(_nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[xy] : _nativeScrollbarSize[xy]); - _contentBorderSize[scrollbarVarsInverted._w_h] = _nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[scrollbarVarsInverted._x_y] : 0; - } - } else { - viewportElementCSS[strOverflow + XY] = _strEmpty; - reset(); - } - }; - setViewportCSS(true); - setViewportCSS(false); - - // if the scroll container is too small and if there is any overflow with no overlay scrollbar (and scrollbar styling isn't possible), - // make viewport element greater in size (Firefox hide Scrollbars fix) - // because firefox starts hiding scrollbars on too small elements - // with this behavior the overflow calculation may be incorrect or the scrollbars would appear suddenly - // https://bugzilla.mozilla.org/show_bug.cgi?id=292284 - if (!_nativeScrollbarStyling - && (_viewportSize.h < _nativeScrollbarMinSize.x || _viewportSize.w < _nativeScrollbarMinSize.y) - && ((hasOverflow.x && hideOverflow.x && !_nativeScrollbarIsOverlaid.x) || (hasOverflow.y && hideOverflow.y && !_nativeScrollbarIsOverlaid.y))) { - viewportElementCSS[_strPaddingMinus + _strTop] = _nativeScrollbarMinSize.x; - viewportElementCSS[_strMarginMinus + _strTop] = -_nativeScrollbarMinSize.x; - - viewportElementCSS[_strPaddingMinus + isRTLRight] = _nativeScrollbarMinSize.y; - viewportElementCSS[_strMarginMinus + isRTLRight] = -_nativeScrollbarMinSize.y; - } - else { - viewportElementCSS[_strPaddingMinus + _strTop] = - viewportElementCSS[_strMarginMinus + _strTop] = - viewportElementCSS[_strPaddingMinus + isRTLRight] = - viewportElementCSS[_strMarginMinus + isRTLRight] = _strEmpty; - } - viewportElementCSS[_strPaddingMinus + isRTLLeft] = - viewportElementCSS[_strMarginMinus + isRTLLeft] = _strEmpty; - - //if there is any overflow (x OR y axis) and this overflow shall be hidden, make overflow hidden, else overflow visible - if ((hasOverflow.x && hideOverflow.x) || (hasOverflow.y && hideOverflow.y) || hideOverflowForceTextarea) { - //only hide if is Textarea - if (_isTextarea && hideOverflowForceTextarea) { - paddingElementCSS[strOverflowX] = - paddingElementCSS[strOverflowY] = strHidden; - } - } - else { - if (!clipAlways || (overflowBehaviorIsVH.x || overflowBehaviorIsVS.x || overflowBehaviorIsVH.y || overflowBehaviorIsVS.y)) { - //only un-hide if Textarea - if (_isTextarea) { - paddingElementCSS[strOverflowX] = - paddingElementCSS[strOverflowY] = _strEmpty; - } - viewportElementCSS[strOverflowX] = - viewportElementCSS[strOverflowY] = strVisible; - } - } - - _paddingElement.css(paddingElementCSS); - _viewportElement.css(viewportElementCSS); - viewportElementCSS = {}; - - //force soft redraw in webkit because without the scrollbars will may appear because DOM wont be redrawn under special conditions - if ((hasOverflow.c || boxSizingChanged || widthAutoChanged || heightAutoChanged) && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { - var elementStyle = _contentElementNative[LEXICON.s]; - var dump; - elementStyle.webkitTransform = 'scale(1)'; - elementStyle.display = 'run-in'; - dump = _contentElementNative[LEXICON.oH]; - elementStyle.display = _strEmpty; //|| dump; //use dump to prevent it from deletion if minify - elementStyle.webkitTransform = _strEmpty; - } - /* - //force hard redraw in webkit if native overlaid scrollbars shall appear - if (ignoreOverlayScrollbarHidingChanged && ignoreOverlayScrollbarHiding) { - _hostElement.hide(); - var dump = _hostElementNative[LEXICON.oH]; - _hostElement.show(); - } - */ - } - - //change to direction RTL and width auto Bugfix in Webkit - //without this fix, the DOM still thinks the scrollbar is LTR and thus the content is shifted to the left - contentElementCSS = {}; - if (cssDirectionChanged || widthAutoChanged || heightAutoChanged) { - if (_isRTL && widthAuto) { - var floatTmp = _contentElement.css(_strFloat); - var posLeftWithoutFloat = MATH.round(_contentElement.css(_strFloat, _strEmpty).css(_strLeft, _strEmpty).position().left); - _contentElement.css(_strFloat, floatTmp); - var posLeftWithFloat = MATH.round(_contentElement.position().left); - - if (posLeftWithoutFloat !== posLeftWithFloat) - contentElementCSS[_strLeft] = posLeftWithoutFloat; - } - else { - contentElementCSS[_strLeft] = _strEmpty; - } - } - _contentElement.css(contentElementCSS); - - //handle scroll position - if (_isTextarea && contentSizeChanged) { - var textareaInfo = getTextareaInfo(); - if (textareaInfo) { - var textareaRowsChanged = _textareaInfoCache === undefined ? true : textareaInfo._rows !== _textareaInfoCache._rows; - var cursorRow = textareaInfo._cursorRow; - var cursorCol = textareaInfo._cursorColumn; - var widestRow = textareaInfo._widestRow; - var lastRow = textareaInfo._rows; - var lastCol = textareaInfo._columns; - var cursorPos = textareaInfo._cursorPosition; - var cursorMax = textareaInfo._cursorMax; - var cursorIsLastPosition = (cursorPos >= cursorMax && _textareaHasFocus); - var textareaScrollAmount = { - x: (!textareaAutoWrapping && (cursorCol === lastCol && cursorRow === widestRow)) ? _overflowAmountCache.x : -1, - y: (textareaAutoWrapping ? cursorIsLastPosition || textareaRowsChanged && (previousOverflowAmount ? (currScroll.y === previousOverflowAmount.y) : false) : (cursorIsLastPosition || textareaRowsChanged) && cursorRow === lastRow) ? _overflowAmountCache.y : -1 - }; - currScroll.x = textareaScrollAmount.x > -1 ? (_isRTL && _normalizeRTLCache && _rtlScrollBehavior.i ? 0 : textareaScrollAmount.x) : currScroll.x; //if inverted, scroll to 0 -> normalized this means to max scroll offset. - currScroll.y = textareaScrollAmount.y > -1 ? textareaScrollAmount.y : currScroll.y; - } - _textareaInfoCache = textareaInfo; - } - if (_isRTL && _rtlScrollBehavior.i && _nativeScrollbarIsOverlaid.y && hasOverflow.x && _normalizeRTLCache) - currScroll.x += _contentBorderSize.w || 0; - if (widthAuto) - _hostElement[_strScrollLeft](0); - if (heightAuto) - _hostElement[_strScrollTop](0); - _viewportElement[_strScrollLeft](currScroll.x)[_strScrollTop](currScroll.y); - - //scrollbars management: - var scrollbarsVisibilityVisible = scrollbarsVisibility === 'v'; - var scrollbarsVisibilityHidden = scrollbarsVisibility === 'h'; - var scrollbarsVisibilityAuto = scrollbarsVisibility === 'a'; - - var showScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, true, canScroll.x); - var showScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, true, canScroll.y); - var hideScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, false, canScroll.x); - var hideScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, false, canScroll.y); - - //manage class name which indicates scrollable overflow - if (hideOverflow.x || hideOverflow.y) - addClass(_hostElement, _classNameHostOverflow); - else - removeClass(_hostElement, _classNameHostOverflow); - if (hideOverflow.x) - addClass(_hostElement, _classNameHostOverflowX); - else - removeClass(_hostElement, _classNameHostOverflowX); - if (hideOverflow.y) - addClass(_hostElement, _classNameHostOverflowY); - else - removeClass(_hostElement, _classNameHostOverflowY); - - //add or remove rtl class name for styling purposes - if (cssDirectionChanged) { - if (_isRTL) - addClass(_hostElement, _classNameHostRTL); - else - removeClass(_hostElement, _classNameHostRTL); - } - - //manage the resize feature (CSS3 resize "polyfill" for this plugin) - if (_isBody) - addClass(_hostElement, _classNameHostResizeDisabled); - if (resizeChanged) { - removeClass(_scrollbarCornerElement, [ - _classNameScrollbarCornerResize, - _classNameScrollbarCornerResizeB, - _classNameScrollbarCornerResizeH, - _classNameScrollbarCornerResizeV].join(_strSpace)); - if (_resizeNone) { - addClass(_hostElement, _classNameHostResizeDisabled); - } - else { - removeClass(_hostElement, _classNameHostResizeDisabled); - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResize); - if (_resizeBoth) - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeB); - else if (_resizeHorizontal) - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeH); - else if (_resizeVertical) - addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeV); - } - } - - //manage the scrollbars general visibility + the scrollbar interactivity (unusable class name) - if (scrollbarsVisibilityChanged || overflowBehaviorChanged || hideOverflow.c || hasOverflow.c || ignoreOverlayScrollbarHidingChanged) { - if (ignoreOverlayScrollbarHiding) { - if (ignoreOverlayScrollbarHidingChanged) { - removeClass(_hostElement, _classNameHostScrolling); - if (ignoreOverlayScrollbarHiding) { - hideScrollbarH(); - hideScrollbarV(); - } - } - } - else if (scrollbarsVisibilityAuto) { - if (canScroll.x) - showScrollbarH(); - else - hideScrollbarH(); - - if (canScroll.y) - showScrollbarV(); - else - hideScrollbarV(); - } - else if (scrollbarsVisibilityVisible) { - showScrollbarH(); - showScrollbarV(); - } - else if (scrollbarsVisibilityHidden) { - hideScrollbarH(); - hideScrollbarV(); - } - } - - //manage the scrollbars auto hide feature (auto hide them after specific actions) - if (scrollbarsAutoHideChanged || ignoreOverlayScrollbarHidingChanged) { - if (_scrollbarsAutoHideLeave || _scrollbarsAutoHideMove) { - setupHostMouseTouchEvents(true); - setupHostMouseTouchEvents(); - } - else { - setupHostMouseTouchEvents(true); - } - - if (_scrollbarsAutoHideNever) - refreshScrollbarsAutoHide(true); - else - refreshScrollbarsAutoHide(false, true); - } - - //manage scrollbars handle length & offset - don't remove! - if (hostSizeChanged || overflowAmount.c || heightAutoChanged || widthAutoChanged || resizeChanged || boxSizingChanged || paddingAbsoluteChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged) { - refreshScrollbarHandleLength(true); - refreshScrollbarHandleOffset(true); - refreshScrollbarHandleLength(false); - refreshScrollbarHandleOffset(false); - } - - //manage interactivity - if (scrollbarsClickScrollingChanged) - refreshScrollbarsInteractive(true, scrollbarsClickScrolling); - if (scrollbarsDragScrollingChanged) - refreshScrollbarsInteractive(false, scrollbarsDragScrolling); - - //callbacks: - if (cssDirectionChanged) { - dispatchCallback('onDirectionChanged', { - isRTL: _isRTL, - dir: cssDirection - }); - } - if (hostSizeChanged) { - dispatchCallback('onHostSizeChanged', { - width: _hostSizeCache.w, - height: _hostSizeCache.h - }); - } - if (contentSizeChanged) { - dispatchCallback('onContentSizeChanged', { - width: _contentScrollSizeCache.w, - height: _contentScrollSizeCache.h - }); - } - if (hasOverflow.c || hideOverflow.c) { - dispatchCallback('onOverflowChanged', { - x: hasOverflow.x, - y: hasOverflow.y, - xScrollable: hideOverflow.xs, - yScrollable: hideOverflow.ys, - clipped: hideOverflow.x || hideOverflow.y - }); - } - if (overflowAmount.c) { - dispatchCallback('onOverflowAmountChanged', { - x: overflowAmount.x, - y: overflowAmount.y - }); - } - } - - //fix body min size - if (_isBody && _bodyMinSizeCache && (_hasOverflowCache.c || _bodyMinSizeCache.c)) { - //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. - if (!_bodyMinSizeCache.f) - bodyMinSizeChanged(); - if (_nativeScrollbarIsOverlaid.y && _hasOverflowCache.x) - _contentElement.css(_strMinMinus + _strWidth, _bodyMinSizeCache.w + _overlayScrollbarDummySize.y); - if (_nativeScrollbarIsOverlaid.x && _hasOverflowCache.y) - _contentElement.css(_strMinMinus + _strHeight, _bodyMinSizeCache.h + _overlayScrollbarDummySize.x); - _bodyMinSizeCache.c = false; - } - - //freezeResizeObserver(_sizeObserverElement, false); - //freezeResizeObserver(_sizeAutoObserverElement, false); - - dispatchCallback('onUpdated', { forced: force }); - } - - - //==== Options ====// - - /** - * Sets new options but doesn't call the update method. - * @param newOptions The object which contains the new options. - * @returns {*} A object which contains the changed options. - */ - function setOptions(newOptions) { - var validatedOpts = _pluginsOptions._validate(newOptions, _pluginsOptions._template, true, _currentOptions) - - _currentOptions = extendDeep({}, _currentOptions, validatedOpts._default); - _currentPreparedOptions = extendDeep({}, _currentPreparedOptions, validatedOpts._prepared); - - return validatedOpts._prepared; - } - - - //==== Structure ====// - - /** - * Builds or destroys the wrapper and helper DOM elements. - * @param destroy Indicates whether the DOM shall be build or destroyed. - */ - function setupStructureDOM(destroy) { - var strParent = 'parent'; - var classNameResizeObserverHost = 'os-resize-observer-host'; - var classNameTextareaElementFull = _classNameTextareaElement + _strSpace + _classNameTextInherit; - var textareaClass = _isTextarea ? _strSpace + _classNameTextInherit : _strEmpty; - var adoptAttrs = _currentPreparedOptions.textarea.inheritedAttrs; - var adoptAttrsMap = {}; - var applyAdoptedAttrs = function () { - var applyAdoptedAttrsElm = destroy ? _targetElement : _hostElement; - each(adoptAttrsMap, function (key, value) { - if (type(value) == TYPES.s) { - if (key == LEXICON.c) - applyAdoptedAttrsElm.addClass(value); - else - applyAdoptedAttrsElm.attr(key, value); - } - }); - }; - var hostElementClassNames = [ - _classNameHostElement, - _classNameHostTextareaElement, - _classNameHostResizeDisabled, - _classNameHostRTL, - _classNameHostScrollbarHorizontalHidden, - _classNameHostScrollbarVerticalHidden, - _classNameHostTransition, - _classNameHostScrolling, - _classNameHostOverflow, - _classNameHostOverflowX, - _classNameHostOverflowY, - _classNameThemeNone, - _classNameTextareaElement, - _classNameTextInherit, - _classNameCache].join(_strSpace); - var hostElementCSS = {}; - - //get host element as first element, because that's the most upper element and required for the other elements - _hostElement = _hostElement || (_isTextarea ? (_domExists ? _targetElement[strParent]()[strParent]()[strParent]()[strParent]() : FRAMEWORK(generateDiv(_classNameHostTextareaElement))) : _targetElement); - _contentElement = _contentElement || selectOrGenerateDivByClass(_classNameContentElement + textareaClass); - _viewportElement = _viewportElement || selectOrGenerateDivByClass(_classNameViewportElement + textareaClass); - _paddingElement = _paddingElement || selectOrGenerateDivByClass(_classNamePaddingElement + textareaClass); - _sizeObserverElement = _sizeObserverElement || selectOrGenerateDivByClass(classNameResizeObserverHost); - _textareaCoverElement = _textareaCoverElement || (_isTextarea ? selectOrGenerateDivByClass(_classNameTextareaCoverElement) : undefined); - - //on destroy, remove all generated class names from the host element before collecting the adopted attributes - //to prevent adopting generated class names - if (destroy) - removeClass(_hostElement, hostElementClassNames); - - //collect all adopted attributes - adoptAttrs = type(adoptAttrs) == TYPES.s ? adoptAttrs.split(_strSpace) : adoptAttrs; - if (type(adoptAttrs) == TYPES.a && _isTextarea) { - each(adoptAttrs, function (i, v) { - if (type(v) == TYPES.s) { - adoptAttrsMap[v] = destroy ? _hostElement.attr(v) : _targetElement.attr(v); - } - }); - } - - if (!destroy) { - if (_isTextarea) { - if (!_currentPreparedOptions.sizeAutoCapable) { - hostElementCSS[_strWidth] = _targetElement.css(_strWidth); - hostElementCSS[_strHeight] = _targetElement.css(_strHeight); - } - - if (!_domExists) - _targetElement.addClass(_classNameTextInherit).wrap(_hostElement); - - //jQuery clones elements in wrap functions, so we have to select them again - _hostElement = _targetElement[strParent]().css(hostElementCSS); - } - - if (!_domExists) { - //add the correct class to the target element - addClass(_targetElement, _isTextarea ? classNameTextareaElementFull : _classNameHostElement); - - //wrap the content into the generated elements to create the required DOM - _hostElement.wrapInner(_contentElement) - .wrapInner(_viewportElement) - .wrapInner(_paddingElement) - .prepend(_sizeObserverElement); - - //jQuery clones elements in wrap functions, so we have to select them again - _contentElement = findFirst(_hostElement, _strDot + _classNameContentElement); - _viewportElement = findFirst(_hostElement, _strDot + _classNameViewportElement); - _paddingElement = findFirst(_hostElement, _strDot + _classNamePaddingElement); - - if (_isTextarea) { - _contentElement.prepend(_textareaCoverElement); - applyAdoptedAttrs(); - } - } - - if (_nativeScrollbarStyling) - addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); - if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y) - addClass(_viewportElement, _classNameViewportNativeScrollbarsOverlaid); - if (_isBody) - addClass(_htmlElement, _classNameHTMLElement); - - _sizeObserverElementNative = _sizeObserverElement[0]; - _hostElementNative = _hostElement[0]; - _paddingElementNative = _paddingElement[0]; - _viewportElementNative = _viewportElement[0]; - _contentElementNative = _contentElement[0]; - - updateViewportAttrsFromTarget(); - } - else { - if (_domExists && _initialized) { - //clear size observer - _sizeObserverElement.children().remove(); - - //remove the style property and classes from already generated elements - each([_paddingElement, _viewportElement, _contentElement, _textareaCoverElement], function (i, elm) { - if (elm) { - removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); - } - }); - - //add classes to the host element which was removed previously to match the expected DOM - addClass(_hostElement, _isTextarea ? _classNameHostTextareaElement : _classNameHostElement); - } - else { - //remove size observer - remove(_sizeObserverElement); - - //unwrap the content to restore DOM - _contentElement.contents() - .unwrap() - .unwrap() - .unwrap(); - - if (_isTextarea) { - _targetElement.unwrap(); - remove(_hostElement); - remove(_textareaCoverElement); - applyAdoptedAttrs(); - } - } - - if (_isTextarea) - _targetElement.removeAttr(LEXICON.s); - - if (_isBody) - removeClass(_htmlElement, _classNameHTMLElement); - } - } - - /** - * Adds or removes all wrapper elements interactivity events. - * @param destroy Indicates whether the Events shall be added or removed. - */ - function setupStructureEvents() { - var textareaKeyDownRestrictedKeyCodes = [ - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 123, //F1 to F12 - 33, 34, //page up, page down - 37, 38, 39, 40, //left, up, right, down arrows - 16, 17, 18, 19, 20, 144 //Shift, Ctrl, Alt, Pause, CapsLock, NumLock - ]; - var textareaKeyDownKeyCodesList = []; - var textareaUpdateIntervalID; - var scrollStopTimeoutId; - var scrollStopDelay = 175; - var strFocus = 'focus'; - - function updateTextarea(doClearInterval) { - textareaUpdate(); - _base.update(_strAuto); - if (doClearInterval && _autoUpdateRecommended) - clearInterval(textareaUpdateIntervalID); - } - function textareaOnScroll(event) { - _targetElement[_strScrollLeft](_rtlScrollBehavior.i && _normalizeRTLCache ? 9999999 : 0); - _targetElement[_strScrollTop](0); - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - return false; - } - function textareaOnDrop(event) { - setTimeout(function () { - if (!_destroyed) - updateTextarea(); - }, 50); - } - function textareaOnFocus() { - _textareaHasFocus = true; - addClass(_hostElement, strFocus); - } - function textareaOnFocusout() { - _textareaHasFocus = false; - textareaKeyDownKeyCodesList = []; - removeClass(_hostElement, strFocus); - updateTextarea(true); - } - function textareaOnKeyDown(event) { - var keyCode = event.keyCode; - - if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { - if (!textareaKeyDownKeyCodesList[LEXICON.l]) { - updateTextarea(); - textareaUpdateIntervalID = setInterval(updateTextarea, 1000 / 60); - } - if (inArray(keyCode, textareaKeyDownKeyCodesList) < 0) - textareaKeyDownKeyCodesList.push(keyCode); - } - } - function textareaOnKeyUp(event) { - var keyCode = event.keyCode; - var index = inArray(keyCode, textareaKeyDownKeyCodesList); - - if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { - if (index > -1) - textareaKeyDownKeyCodesList.splice(index, 1); - if (!textareaKeyDownKeyCodesList[LEXICON.l]) - updateTextarea(true); - } - } - function contentOnTransitionEnd(event) { - if (_autoUpdateCache === true) - return; - event = event.originalEvent || event; - if (isSizeAffectingCSSProperty(event.propertyName)) - _base.update(_strAuto); - } - function viewportOnScroll(event) { - if (!_sleeping) { - if (scrollStopTimeoutId !== undefined) - clearTimeout(scrollStopTimeoutId); - else { - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(true); - - if (!nativeOverlayScrollbarsAreActive()) - addClass(_hostElement, _classNameHostScrolling); - - dispatchCallback('onScrollStart', event); - } - - //if a scrollbars handle gets dragged, the mousemove event is responsible for refreshing the handle offset - //because if CSS scroll-snap is used, the handle offset gets only refreshed on every snap point - //this looks laggy & clunky, it looks much better if the offset refreshes with the mousemove - if (!_scrollbarsHandlesDefineScrollPos) { - refreshScrollbarHandleOffset(true); - refreshScrollbarHandleOffset(false); - } - dispatchCallback('onScroll', event); - - scrollStopTimeoutId = setTimeout(function () { - if (!_destroyed) { - //OnScrollStop: - clearTimeout(scrollStopTimeoutId); - scrollStopTimeoutId = undefined; - - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(false); - - if (!nativeOverlayScrollbarsAreActive()) - removeClass(_hostElement, _classNameHostScrolling); - - dispatchCallback('onScrollStop', event); - } - }, scrollStopDelay); - } - } - - - if (_isTextarea) { - if (_msieVersion > 9 || !_autoUpdateRecommended) { - addDestroyEventListener(_targetElement, 'input', updateTextarea); - } - else { - addDestroyEventListener(_targetElement, - [_strKeyDownEvent, _strKeyUpEvent], - [textareaOnKeyDown, textareaOnKeyUp]); - } - - addDestroyEventListener(_targetElement, - [_strScroll, 'drop', strFocus, strFocus + 'out'], - [textareaOnScroll, textareaOnDrop, textareaOnFocus, textareaOnFocusout]); - } - else { - addDestroyEventListener(_contentElement, _strTransitionEndEvent, contentOnTransitionEnd); - } - addDestroyEventListener(_viewportElement, _strScroll, viewportOnScroll, true); - } - - - //==== Scrollbars ====// - - /** - * Builds or destroys all scrollbar DOM elements (scrollbar, track, handle) - * @param destroy Indicates whether the DOM shall be build or destroyed. - */ - function setupScrollbarsDOM(destroy) { - var selectOrGenerateScrollbarDOM = function (isHorizontal) { - var scrollbarClassName = isHorizontal ? _classNameScrollbarHorizontal : _classNameScrollbarVertical; - var scrollbar = selectOrGenerateDivByClass(_classNameScrollbar + _strSpace + scrollbarClassName, true); - var track = selectOrGenerateDivByClass(_classNameScrollbarTrack, scrollbar); - var handle = selectOrGenerateDivByClass(_classNameScrollbarHandle, scrollbar); - - if (!_domExists && !destroy) { - scrollbar.append(track); - track.append(handle); - } - - return { - _scrollbar: scrollbar, - _track: track, - _handle: handle - }; - }; - function resetScrollbarDOM(isHorizontal) { - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbar = scrollbarVars._scrollbar; - var track = scrollbarVars._track; - var handle = scrollbarVars._handle; - - if (_domExists && _initialized) { - each([scrollbar, track, handle], function (i, elm) { - removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); - }); - } - else { - remove(scrollbar || selectOrGenerateScrollbarDOM(isHorizontal)._scrollbar); - } - } - var horizontalElements; - var verticalElements; - - if (!destroy) { - horizontalElements = selectOrGenerateScrollbarDOM(true); - verticalElements = selectOrGenerateScrollbarDOM(); - - _scrollbarHorizontalElement = horizontalElements._scrollbar; - _scrollbarHorizontalTrackElement = horizontalElements._track; - _scrollbarHorizontalHandleElement = horizontalElements._handle; - _scrollbarVerticalElement = verticalElements._scrollbar; - _scrollbarVerticalTrackElement = verticalElements._track; - _scrollbarVerticalHandleElement = verticalElements._handle; - - if (!_domExists) { - _paddingElement.after(_scrollbarVerticalElement); - _paddingElement.after(_scrollbarHorizontalElement); - } - } - else { - resetScrollbarDOM(true); - resetScrollbarDOM(); - } - } - - /** - * Initializes all scrollbar interactivity events. (track and handle dragging, clicking, scrolling) - * @param isHorizontal True if the target scrollbar is the horizontal scrollbar, false if the target scrollbar is the vertical scrollbar. - */ - function setupScrollbarEvents(isHorizontal) { - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbarVarsInfo = scrollbarVars._info; - var insideIFrame = _windowElementNative.top !== _windowElementNative; - var xy = scrollbarVars._x_y; - var XY = scrollbarVars._X_Y; - var scroll = _strScroll + scrollbarVars._Left_Top; - var strActive = 'active'; - var strSnapHandle = 'snapHandle'; - var scrollDurationFactor = 1; - var increaseDecreaseScrollAmountKeyCodes = [16, 17]; //shift, ctrl - var trackTimeout; - var mouseDownScroll; - var mouseDownOffset; - var mouseDownInvertedScale; - - function getPointerPosition(event) { - return _msieVersion && insideIFrame ? event['screen' + XY] : COMPATIBILITY.page(event)[xy]; //use screen coordinates in EDGE & IE because the page values are incorrect in frames. - } - function getPreparedScrollbarsOption(name) { - return _currentPreparedOptions.scrollbars[name]; - } - function increaseTrackScrollAmount() { - scrollDurationFactor = 0.5; - } - function decreaseTrackScrollAmount() { - scrollDurationFactor = 1; - } - function documentKeyDown(event) { - if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) - increaseTrackScrollAmount(); - } - function documentKeyUp(event) { - if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) - decreaseTrackScrollAmount(); - } - function onMouseTouchDownContinue(event) { - var originalEvent = event.originalEvent || event; - var isTouchEvent = originalEvent.touches !== undefined; - return _sleeping || _destroyed || nativeOverlayScrollbarsAreActive() || !_scrollbarsDragScrollingCache || (isTouchEvent && !getPreparedScrollbarsOption('touchSupport')) ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; - } - function documentDragMove(event) { - if (onMouseTouchDownContinue(event)) { - var trackLength = scrollbarVarsInfo._trackLength; - var handleLength = scrollbarVarsInfo._handleLength; - var scrollRange = scrollbarVarsInfo._maxScroll; - var scrollRaw = (getPointerPosition(event) - mouseDownOffset) * mouseDownInvertedScale; - var scrollDeltaPercent = scrollRaw / (trackLength - handleLength); - var scrollDelta = (scrollRange * scrollDeltaPercent); - scrollDelta = isFinite(scrollDelta) ? scrollDelta : 0; - if (_isRTL && isHorizontal && !_rtlScrollBehavior.i) - scrollDelta *= -1; - - _viewportElement[scroll](MATH.round(mouseDownScroll + scrollDelta)); - - if (_scrollbarsHandlesDefineScrollPos) - refreshScrollbarHandleOffset(isHorizontal, mouseDownScroll + scrollDelta); - - if (!_supportPassiveEvents) - COMPATIBILITY.prvD(event); - } - else - documentMouseTouchUp(event); - } - function documentMouseTouchUp(event) { - event = event || event.originalEvent; - - setupResponsiveEventListener(_documentElement, - [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], - [documentDragMove, documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart], - true); - - if (_scrollbarsHandlesDefineScrollPos) - refreshScrollbarHandleOffset(isHorizontal, true); - - _scrollbarsHandlesDefineScrollPos = false; - removeClass(_bodyElement, _classNameDragging); - removeClass(scrollbarVars._handle, strActive); - removeClass(scrollbarVars._track, strActive); - removeClass(scrollbarVars._scrollbar, strActive); - - mouseDownScroll = undefined; - mouseDownOffset = undefined; - mouseDownInvertedScale = 1; - - decreaseTrackScrollAmount(); - - if (trackTimeout !== undefined) { - _base.scrollStop(); - clearTimeout(trackTimeout); - trackTimeout = undefined; - } - - if (event) { - var rect = _hostElementNative[LEXICON.bCR](); - var mouseInsideHost = event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom; - - //if mouse is outside host element - if (!mouseInsideHost) - hostOnMouseLeave(); - - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(false); - } - } - function onHandleMouseTouchDown(event) { - if (onMouseTouchDownContinue(event)) - onHandleMouseTouchDownAction(event); - } - function onHandleMouseTouchDownAction(event) { - mouseDownScroll = _viewportElement[scroll](); - mouseDownScroll = isNaN(mouseDownScroll) ? 0 : mouseDownScroll; - if (_isRTL && isHorizontal && !_rtlScrollBehavior.n || !_isRTL) - mouseDownScroll = mouseDownScroll < 0 ? 0 : mouseDownScroll; - - mouseDownInvertedScale = getHostElementInvertedScale()[xy]; - mouseDownOffset = getPointerPosition(event); - - _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); - addClass(_bodyElement, _classNameDragging); - addClass(scrollbarVars._handle, strActive); - addClass(scrollbarVars._scrollbar, strActive); - - setupResponsiveEventListener(_documentElement, - [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strSelectStartEvent], - [documentDragMove, documentMouseTouchUp, documentOnSelectStart]); - - if (_msieVersion || !_documentMixed) - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - function onTrackMouseTouchDown(event) { - if (onMouseTouchDownContinue(event)) { - var scrollDistance = MATH.round(_viewportSize[scrollbarVars._w_h]); - var trackOffset = scrollbarVars._track.offset()[scrollbarVars._left_top]; - var ctrlKey = event.ctrlKey; - var instantScroll = event.shiftKey; - var instantScrollTransition = instantScroll && ctrlKey; - var isFirstIteration = true; - var easing = 'linear'; - var decreaseScroll; - var finishedCondition; - var scrollActionFinsished = function (transition) { - if (_scrollbarsHandlesDefineScrollPos) - refreshScrollbarHandleOffset(isHorizontal, transition); - }; - var scrollActionInstantFinished = function () { - scrollActionFinsished(); - onHandleMouseTouchDownAction(event); - }; - var scrollAction = function () { - if (!_destroyed) { - var mouseOffset = (mouseDownOffset - trackOffset) * mouseDownInvertedScale; - var handleOffset = scrollbarVarsInfo._handleOffset; - var trackLength = scrollbarVarsInfo._trackLength; - var handleLength = scrollbarVarsInfo._handleLength; - var scrollRange = scrollbarVarsInfo._maxScroll; - var currScroll = scrollbarVarsInfo._currentScroll; - var scrollDuration = 270 * scrollDurationFactor; - var timeoutDelay = isFirstIteration ? MATH.max(400, scrollDuration) : scrollDuration; - var instantScrollPosition = scrollRange * ((mouseOffset - (handleLength / 2)) / (trackLength - handleLength)); // 100% * positionPercent - var rtlIsNormal = _isRTL && isHorizontal && ((!_rtlScrollBehavior.i && !_rtlScrollBehavior.n) || _normalizeRTLCache); - var decreaseScrollCondition = rtlIsNormal ? handleOffset < mouseOffset : handleOffset > mouseOffset; - var scrollObj = {}; - var animationObj = { - easing: easing, - step: function (now) { - if (_scrollbarsHandlesDefineScrollPos) { - _viewportElement[scroll](now); //https://github.com/jquery/jquery/issues/4340 - refreshScrollbarHandleOffset(isHorizontal, now); - } - } - }; - instantScrollPosition = isFinite(instantScrollPosition) ? instantScrollPosition : 0; - instantScrollPosition = _isRTL && isHorizontal && !_rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; - - //_base.scrollStop(); - - if (instantScroll) { - _viewportElement[scroll](instantScrollPosition); //scroll instantly to new position - if (instantScrollTransition) { - //get the scroll position after instant scroll (in case CSS Snap Points are used) to get the correct snapped scroll position - //and the animation stops at the correct point - instantScrollPosition = _viewportElement[scroll](); - //scroll back to the position before instant scrolling so animation can be performed - _viewportElement[scroll](currScroll); - - instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; - instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.n ? -instantScrollPosition : instantScrollPosition; - - scrollObj[xy] = instantScrollPosition; - _base.scroll(scrollObj, extendDeep(animationObj, { - duration: 130, - complete: scrollActionInstantFinished - })); - } - else - scrollActionInstantFinished(); - } - else { - decreaseScroll = isFirstIteration ? decreaseScrollCondition : decreaseScroll; - finishedCondition = rtlIsNormal - ? (decreaseScroll ? handleOffset + handleLength >= mouseOffset : handleOffset <= mouseOffset) - : (decreaseScroll ? handleOffset <= mouseOffset : handleOffset + handleLength >= mouseOffset); - - if (finishedCondition) { - clearTimeout(trackTimeout); - _base.scrollStop(); - trackTimeout = undefined; - scrollActionFinsished(true); - } - else { - trackTimeout = setTimeout(scrollAction, timeoutDelay); - - scrollObj[xy] = (decreaseScroll ? '-=' : '+=') + scrollDistance; - _base.scroll(scrollObj, extendDeep(animationObj, { - duration: scrollDuration - })); - } - isFirstIteration = false; - } - } - }; - if (ctrlKey) - increaseTrackScrollAmount(); - - mouseDownInvertedScale = getHostElementInvertedScale()[xy]; - mouseDownOffset = COMPATIBILITY.page(event)[xy]; - - _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); - addClass(_bodyElement, _classNameDragging); - addClass(scrollbarVars._track, strActive); - addClass(scrollbarVars._scrollbar, strActive); - - setupResponsiveEventListener(_documentElement, - [_strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], - [documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart]); - - scrollAction(); - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - } - function onTrackMouseTouchEnter(event) { - //make sure both scrollbars will stay visible if one scrollbar is hovered if autoHide is "scroll" or "move". - _scrollbarsHandleHovered = true; - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(true); - } - function onTrackMouseTouchLeave(event) { - _scrollbarsHandleHovered = false; - if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) - refreshScrollbarsAutoHide(false); - } - function onScrollbarMouseTouchDown(event) { - COMPATIBILITY.stpP(event); - } - - addDestroyEventListener(scrollbarVars._handle, - _strMouseTouchDownEvent, - onHandleMouseTouchDown); - addDestroyEventListener(scrollbarVars._track, - [_strMouseTouchDownEvent, _strMouseTouchEnter, _strMouseTouchLeave], - [onTrackMouseTouchDown, onTrackMouseTouchEnter, onTrackMouseTouchLeave]); - addDestroyEventListener(scrollbarVars._scrollbar, - _strMouseTouchDownEvent, - onScrollbarMouseTouchDown); - - if (_supportTransition) { - addDestroyEventListener(scrollbarVars._scrollbar, _strTransitionEndEvent, function (event) { - if (event.target !== scrollbarVars._scrollbar[0]) - return; - refreshScrollbarHandleLength(isHorizontal); - refreshScrollbarHandleOffset(isHorizontal); - }); - } - } - - /** - * Shows or hides the given scrollbar and applied a class name which indicates if the scrollbar is scrollable or not. - * @param isHorizontal True if the horizontal scrollbar is the target, false if the vertical scrollbar is the target. - * @param shallBeVisible True if the scrollbar shall be shown, false if hidden. - * @param canScroll True if the scrollbar is scrollable, false otherwise. - */ - function refreshScrollbarAppearance(isHorizontal, shallBeVisible, canScroll) { - var scrollbarClassName = isHorizontal ? _classNameHostScrollbarHorizontalHidden : _classNameHostScrollbarVerticalHidden; - var scrollbarElement = isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement; - - if (shallBeVisible) - removeClass(_hostElement, scrollbarClassName); - else - addClass(_hostElement, scrollbarClassName); - - if (canScroll) - removeClass(scrollbarElement, _classNameScrollbarUnusable); - else - addClass(scrollbarElement, _classNameScrollbarUnusable); - } - - /** - * Autoshows / autohides both scrollbars with. - * @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. - * @param delayfree True if the scrollbars shall be hidden without a delay, false or undefined otherwise. - */ - function refreshScrollbarsAutoHide(shallBeVisible, delayfree) { - clearTimeout(_scrollbarsAutoHideTimeoutId); - if (shallBeVisible) { - //if(_hasOverflowCache.x && _hideOverflowCache.xs) - removeClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); - //if(_hasOverflowCache.y && _hideOverflowCache.ys) - removeClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); - } - else { - var anyActive; - var strActive = 'active'; - var hide = function () { - if (!_scrollbarsHandleHovered && !_destroyed) { - anyActive = _scrollbarHorizontalHandleElement.hasClass(strActive) || _scrollbarVerticalHandleElement.hasClass(strActive); - if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) - addClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); - if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) - addClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); - } - }; - if (_scrollbarsAutoHideDelay > 0 && delayfree !== true) - _scrollbarsAutoHideTimeoutId = setTimeout(hide, _scrollbarsAutoHideDelay); - else - hide(); - } - } - - /** - * Refreshes the handle length of the given scrollbar. - * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. - */ - function refreshScrollbarHandleLength(isHorizontal) { - var handleCSS = {}; - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbarVarsInfo = scrollbarVars._info; - var digit = 1000000; - //get and apply intended handle length - var handleRatio = MATH.min(1, (_hostSizeCache[scrollbarVars._w_h] - (_paddingAbsoluteCache ? (isHorizontal ? _paddingX : _paddingY) : 0)) / _contentScrollSizeCache[scrollbarVars._w_h]); - handleCSS[scrollbarVars._width_height] = (MATH.floor(handleRatio * 100 * digit) / digit) + '%'; //the last * digit / digit is for flooring to the 4th digit - - if (!nativeOverlayScrollbarsAreActive()) - scrollbarVars._handle.css(handleCSS); - - //measure the handle length to respect min & max length - scrollbarVarsInfo._handleLength = scrollbarVars._handle[0]['offset' + scrollbarVars._Width_Height]; - scrollbarVarsInfo._handleLengthRatio = handleRatio; - } - - /** - * Refreshes the handle offset of the given scrollbar. - * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. - * @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) - */ - function refreshScrollbarHandleOffset(isHorizontal, scrollOrTransition) { - var transition = type(scrollOrTransition) == TYPES.b; - var transitionDuration = 250; - var isRTLisHorizontal = _isRTL && isHorizontal; - var scrollbarVars = getScrollbarVars(isHorizontal); - var scrollbarVarsInfo = scrollbarVars._info; - var strTranslateBrace = 'translate('; - var strTransform = VENDORS._cssProperty('transform'); - var strTransition = VENDORS._cssProperty('transition'); - var nativeScroll = isHorizontal ? _viewportElement[_strScrollLeft]() : _viewportElement[_strScrollTop](); - var currentScroll = scrollOrTransition === undefined || transition ? nativeScroll : scrollOrTransition; - - //measure the handle length to respect min & max length - var handleLength = scrollbarVarsInfo._handleLength; - var trackLength = scrollbarVars._track[0]['offset' + scrollbarVars._Width_Height]; - var handleTrackDiff = trackLength - handleLength; - var handleCSS = {}; - var transformOffset; - var translateValue; - - //DONT use the variable '_contentScrollSizeCache[scrollbarVars._w_h]' instead of '_viewportElement[0]['scroll' + scrollbarVars._Width_Height]' - // because its a bit behind during the small delay when content size updates - //(delay = mutationObserverContentLag, if its 0 then this var could be used) - var maxScroll = (_viewportElementNative[_strScroll + scrollbarVars._Width_Height] - _viewportElementNative['client' + scrollbarVars._Width_Height]) * (_rtlScrollBehavior.n && isRTLisHorizontal ? -1 : 1); //* -1 if rtl scroll max is negative - var getScrollRatio = function (base) { - return isNaN(base / maxScroll) ? 0 : MATH.max(0, MATH.min(1, base / maxScroll)); - }; - var getHandleOffset = function (scrollRatio) { - var offset = handleTrackDiff * scrollRatio; - offset = isNaN(offset) ? 0 : offset; - offset = (isRTLisHorizontal && !_rtlScrollBehavior.i) ? (trackLength - handleLength - offset) : offset; - offset = MATH.max(0, offset); - return offset; - }; - var scrollRatio = getScrollRatio(nativeScroll); - var unsnappedScrollRatio = getScrollRatio(currentScroll); - var handleOffset = getHandleOffset(unsnappedScrollRatio); - var snappedHandleOffset = getHandleOffset(scrollRatio); - - scrollbarVarsInfo._maxScroll = maxScroll; - scrollbarVarsInfo._currentScroll = nativeScroll; - scrollbarVarsInfo._currentScrollRatio = scrollRatio; - - if (_supportTransform) { - transformOffset = isRTLisHorizontal ? -(trackLength - handleLength - handleOffset) : handleOffset; //in px - //transformOffset = (transformOffset / trackLength * 100) * (trackLength / handleLength); //in % - translateValue = isHorizontal ? strTranslateBrace + transformOffset + 'px, 0)' : strTranslateBrace + '0, ' + transformOffset + 'px)'; - - handleCSS[strTransform] = translateValue; - - //apply or clear up transition - if (_supportTransition) - handleCSS[strTransition] = transition && MATH.abs(handleOffset - scrollbarVarsInfo._handleOffset) > 1 ? getCSSTransitionString(scrollbarVars._handle) + ', ' + (strTransform + _strSpace + transitionDuration + 'ms') : _strEmpty; - } - else - handleCSS[scrollbarVars._left_top] = handleOffset; - - - //only apply css if offset has changed and overflow exists. - if (!nativeOverlayScrollbarsAreActive()) { - scrollbarVars._handle.css(handleCSS); - - //clear up transition - if (_supportTransform && _supportTransition && transition) { - scrollbarVars._handle.one(_strTransitionEndEvent, function () { - if (!_destroyed) - scrollbarVars._handle.css(strTransition, _strEmpty); - }); - } - } - - scrollbarVarsInfo._handleOffset = handleOffset; - scrollbarVarsInfo._snappedHandleOffset = snappedHandleOffset; - scrollbarVarsInfo._trackLength = trackLength; - } - - /** - * Refreshes the interactivity of the given scrollbar element. - * @param isTrack True if the track element is the target, false if the handle element is the target. - * @param value True for interactivity false for no interactivity. - */ - function refreshScrollbarsInteractive(isTrack, value) { - var action = value ? 'removeClass' : 'addClass'; - var element1 = isTrack ? _scrollbarHorizontalTrackElement : _scrollbarHorizontalHandleElement; - var element2 = isTrack ? _scrollbarVerticalTrackElement : _scrollbarVerticalHandleElement; - var className = isTrack ? _classNameScrollbarTrackOff : _classNameScrollbarHandleOff; - - element1[action](className); - element2[action](className); - } - - /** - * Returns a object which is used for fast access for specific variables. - * @param isHorizontal True if the horizontal scrollbar vars shall be accessed, false if the vertical scrollbar vars shall be accessed. - * @returns {{wh: string, WH: string, lt: string, _wh: string, _lt: string, t: *, h: *, c: {}, s: *}} - */ - function getScrollbarVars(isHorizontal) { - return { - _width_height: isHorizontal ? _strWidth : _strHeight, - _Width_Height: isHorizontal ? 'Width' : 'Height', - _left_top: isHorizontal ? _strLeft : _strTop, - _Left_Top: isHorizontal ? 'Left' : 'Top', - _x_y: isHorizontal ? _strX : _strY, - _X_Y: isHorizontal ? 'X' : 'Y', - _w_h: isHorizontal ? 'w' : 'h', - _l_t: isHorizontal ? 'l' : 't', - _track: isHorizontal ? _scrollbarHorizontalTrackElement : _scrollbarVerticalTrackElement, - _handle: isHorizontal ? _scrollbarHorizontalHandleElement : _scrollbarVerticalHandleElement, - _scrollbar: isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement, - _info: isHorizontal ? _scrollHorizontalInfo : _scrollVerticalInfo - }; - } - - - //==== Scrollbar Corner ====// - - /** - * Builds or destroys the scrollbar corner DOM element. - * @param destroy Indicates whether the DOM shall be build or destroyed. - */ - function setupScrollbarCornerDOM(destroy) { - _scrollbarCornerElement = _scrollbarCornerElement || selectOrGenerateDivByClass(_classNameScrollbarCorner, true); - - if (!destroy) { - if (!_domExists) { - _hostElement.append(_scrollbarCornerElement); - } - } - else { - if (_domExists && _initialized) { - removeClass(_scrollbarCornerElement.removeAttr(LEXICON.s), _classNamesDynamicDestroy); - } - else { - remove(_scrollbarCornerElement); - } - } - } - - /** - * Initializes all scrollbar corner interactivity events. - */ - function setupScrollbarCornerEvents() { - var insideIFrame = _windowElementNative.top !== _windowElementNative; - var mouseDownPosition = {}; - var mouseDownSize = {}; - var mouseDownInvertedScale = {}; - var reconnectMutationObserver; - - function documentDragMove(event) { - if (onMouseTouchDownContinue(event)) { - var pageOffset = getCoordinates(event); - var hostElementCSS = {}; - if (_resizeHorizontal || _resizeBoth) - hostElementCSS[_strWidth] = (mouseDownSize.w + (pageOffset.x - mouseDownPosition.x) * mouseDownInvertedScale.x); - if (_resizeVertical || _resizeBoth) - hostElementCSS[_strHeight] = (mouseDownSize.h + (pageOffset.y - mouseDownPosition.y) * mouseDownInvertedScale.y); - _hostElement.css(hostElementCSS); - COMPATIBILITY.stpP(event); - } - else { - documentMouseTouchUp(event); - } - } - function documentMouseTouchUp(event) { - var eventIsTrusted = event !== undefined; - - setupResponsiveEventListener(_documentElement, - [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], - [documentOnSelectStart, documentDragMove, documentMouseTouchUp], - true); - - removeClass(_bodyElement, _classNameDragging); - if (_scrollbarCornerElement.releaseCapture) - _scrollbarCornerElement.releaseCapture(); - - if (eventIsTrusted) { - if (reconnectMutationObserver) - connectMutationObservers(); - _base.update(_strAuto); - } - reconnectMutationObserver = false; - } - function onMouseTouchDownContinue(event) { - var originalEvent = event.originalEvent || event; - var isTouchEvent = originalEvent.touches !== undefined; - return _sleeping || _destroyed ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; - } - function getCoordinates(event) { - return _msieVersion && insideIFrame ? { x: event.screenX, y: event.screenY } : COMPATIBILITY.page(event); - } - - addDestroyEventListener(_scrollbarCornerElement, _strMouseTouchDownEvent, function (event) { - if (onMouseTouchDownContinue(event) && !_resizeNone) { - if (_mutationObserversConnected) { - reconnectMutationObserver = true; - disconnectMutationObservers(); - } - - mouseDownPosition = getCoordinates(event); - - mouseDownSize.w = _hostElementNative[LEXICON.oW] - (!_isBorderBox ? _paddingX : 0); - mouseDownSize.h = _hostElementNative[LEXICON.oH] - (!_isBorderBox ? _paddingY : 0); - mouseDownInvertedScale = getHostElementInvertedScale(); - - setupResponsiveEventListener(_documentElement, - [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], - [documentOnSelectStart, documentDragMove, documentMouseTouchUp]); - - addClass(_bodyElement, _classNameDragging); - if (_scrollbarCornerElement.setCapture) - _scrollbarCornerElement.setCapture(); - - COMPATIBILITY.prvD(event); - COMPATIBILITY.stpP(event); - } - }); - } - - - //==== Utils ====// - - /** - * Calls the callback with the given name. The Context of this callback is always _base (this). - * @param name The name of the target which shall be called. - * @param args The args with which the callback shall be called. - */ - function dispatchCallback(name, args) { - if (_initialized) { - var callback = _currentPreparedOptions.callbacks[name]; - var extensionOnName = name; - var ext; - - if (extensionOnName.substr(0, 2) === 'on') - extensionOnName = extensionOnName.substr(2, 1).toLowerCase() + extensionOnName.substr(3); - - if (type(callback) == TYPES.f) - callback.call(_base, args); - - each(_extensions, function () { - ext = this; - if (type(ext.on) == TYPES.f) - ext.on(extensionOnName, args); - }); - } - else if (!_destroyed) - _callbacksInitQeueue.push({ n: name, a: args }); - } - - /** - * Sets the "top, right, bottom, left" properties, with a given prefix, of the given css object. - * @param targetCSSObject The css object to which the values shall be applied. - * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix) - * @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]. - * If this argument is undefined the value '' (empty string) will be applied to all properties. - */ - function setTopRightBottomLeft(targetCSSObject, prefix, values) { - if (values === undefined) - values = [_strEmpty, _strEmpty, _strEmpty, _strEmpty]; - - targetCSSObject[prefix + _strTop] = values[0]; - targetCSSObject[prefix + _strRight] = values[1]; - targetCSSObject[prefix + _strBottom] = values[2]; - targetCSSObject[prefix + _strLeft] = values[3]; - } - - /** - * Returns the computed CSS transition string from the given element. - * @param element The element from which the transition string shall be returned. - * @returns {string} The CSS transition string from the given element. - */ - function getCSSTransitionString(element) { - var transitionStr = VENDORS._cssProperty('transition'); - var assembledValue = element.css(transitionStr); - if (assembledValue) - return assembledValue; - var regExpString = '\\s*(' + '([^,(]+(\\(.+?\\))?)+' + ')[\\s,]*'; - var regExpMain = new RegExp(regExpString); - var regExpValidate = new RegExp('^(' + regExpString + ')+$'); - var properties = 'property duration timing-function delay'.split(' '); - var result = []; - var strResult; - var valueArray; - var i = 0; - var j; - var splitCssStyleByComma = function (str) { - strResult = []; - if (!str.match(regExpValidate)) - return str; - while (str.match(regExpMain)) { - strResult.push(RegExp.$1); - str = str.replace(regExpMain, _strEmpty); - } - - return strResult; - }; - for (; i < properties[LEXICON.l]; i++) { - valueArray = splitCssStyleByComma(element.css(transitionStr + '-' + properties[i])); - for (j = 0; j < valueArray[LEXICON.l]; j++) - result[j] = (result[j] ? result[j] + _strSpace : _strEmpty) + valueArray[j]; - } - return result.join(', '); - } - - /** - * Calculates the host-elements inverted scale. (invertedScale = 1 / scale) - * @returns {{x: number, y: number}} The scale of the host-element. - */ - function getHostElementInvertedScale() { - var rect = _paddingElementNative[LEXICON.bCR](); - return { - x: _supportTransform ? 1 / (MATH.round(rect.width) / _paddingElementNative[LEXICON.oW]) || 1 : 1, - y: _supportTransform ? 1 / (MATH.round(rect.height) / _paddingElementNative[LEXICON.oH]) || 1 : 1 - }; - } - - /** - * Checks whether the given object is a HTMLElement. - * @param o The object which shall be checked. - * @returns {boolean} True the given object is a HTMLElement, false otherwise. - */ - function isHTMLElement(o) { - var strOwnerDocument = 'ownerDocument'; - var strHTMLElement = 'HTMLElement'; - var wnd = o && o[strOwnerDocument] ? (o[strOwnerDocument].parentWindow || window) : window; - return ( - typeof wnd[strHTMLElement] == TYPES.o ? o instanceof wnd[strHTMLElement] : //DOM2 - o && typeof o == TYPES.o && o !== null && o.nodeType === 1 && typeof o.nodeName == TYPES.s - ); - } - - /** - * Compares 2 arrays and returns the differences between them as a array. - * @param a1 The first array which shall be compared. - * @param a2 The second array which shall be compared. - * @returns {Array} The differences between the two arrays. - */ - function getArrayDifferences(a1, a2) { - var a = []; - var diff = []; - var i; - var k; - for (i = 0; i < a1.length; i++) - a[a1[i]] = true; - for (i = 0; i < a2.length; i++) { - if (a[a2[i]]) - delete a[a2[i]]; - else - a[a2[i]] = true; - } - for (k in a) - diff.push(k); - return diff; - } - - /** - * Returns Zero or the number to which the value can be parsed. - * @param value The value which shall be parsed. - * @param toFloat Indicates whether the number shall be parsed to a float. - */ - function parseToZeroOrNumber(value, toFloat) { - var num = toFloat ? parseFloat(value) : parseInt(value, 10); - return isNaN(num) ? 0 : num; - } - - /** - * Gets several information of the textarea and returns them as a object or undefined if the browser doesn't support it. - * @returns {{cursorRow: Number, cursorCol, rows: Number, cols: number, wRow: number, pos: number, max : number}} or undefined if not supported. - */ - function getTextareaInfo() { - //read needed values - var textareaCursorPosition = _targetElementNative.selectionStart; - if (textareaCursorPosition === undefined) - return; - - var textareaValue = _targetElement.val(); - var textareaLength = textareaValue[LEXICON.l]; - var textareaRowSplit = textareaValue.split('\n'); - var textareaLastRow = textareaRowSplit[LEXICON.l]; - var textareaCurrentCursorRowSplit = textareaValue.substr(0, textareaCursorPosition).split('\n'); - var widestRow = 0; - var textareaLastCol = 0; - var cursorRow = textareaCurrentCursorRowSplit[LEXICON.l]; - var cursorCol = textareaCurrentCursorRowSplit[textareaCurrentCursorRowSplit[LEXICON.l] - 1][LEXICON.l]; - var rowCols; - var i; - - //get widest Row and the last column of the textarea - for (i = 0; i < textareaRowSplit[LEXICON.l]; i++) { - rowCols = textareaRowSplit[i][LEXICON.l]; - if (rowCols > textareaLastCol) { - widestRow = i + 1; - textareaLastCol = rowCols; - } - } - - return { - _cursorRow: cursorRow, //cursorRow - _cursorColumn: cursorCol, //cursorCol - _rows: textareaLastRow, //rows - _columns: textareaLastCol, //cols - _widestRow: widestRow, //wRow - _cursorPosition: textareaCursorPosition, //pos - _cursorMax: textareaLength //max - }; - } - - /** - * Determines whether native overlay scrollbars are active. - * @returns {boolean} True if native overlay scrollbars are active, false otherwise. - */ - function nativeOverlayScrollbarsAreActive() { - return (_ignoreOverlayScrollbarHidingCache && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)); - } - - /** - * Gets the element which is used to measure the content size. - * @returns {*} TextareaCover if target element is textarea else the ContentElement. - */ - function getContentMeasureElement() { - return _isTextarea ? _textareaCoverElement[0] : _contentElementNative; - } - - /** - * Generates a string which represents a HTML div with the given classes or attributes. - * @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".) - * @param content The content of the div as string. - * @returns {string} The concated string which represents a HTML div and its content. - */ - function generateDiv(classesOrAttrs, content) { - return '
' + - (content || _strEmpty) + - '
'; - } - - /** - * Selects or generates a div with the given class attribute. - * @param className The class names (divided by spaces) of the div which shall be selected or generated. - * @param selectParentOrOnlyChildren The parent element from which of the element shall be selected. (if undefined or boolean its hostElement) - * If its a boolean it decides whether only the children of the host element shall be selected. - * @returns {*} The generated or selected element. - */ - function selectOrGenerateDivByClass(className, selectParentOrOnlyChildren) { - var onlyChildren = type(selectParentOrOnlyChildren) == TYPES.b; - var selectParent = onlyChildren ? _hostElement : (selectParentOrOnlyChildren || _hostElement); - - return (_domExists && !selectParent[LEXICON.l]) - ? null - : _domExists - ? selectParent[onlyChildren ? 'children' : 'find'](_strDot + className.replace(/\s/g, _strDot)).eq(0) - : FRAMEWORK(generateDiv(className)) - } - - /** - * Gets the value of the given property from the given object. - * @param obj The object from which the property value shall be got. - * @param path The property of which the value shall be got. - * @returns {*} Returns the value of the searched property or undefined of the property wasn't found. - */ - function getObjectPropVal(obj, path) { - var splits = path.split(_strDot); - var i = 0; - var val; - for (; i < splits.length; i++) { - if (!obj[LEXICON.hOP](splits[i])) - return; - val = obj[splits[i]]; - if (i < splits.length && type(val) == TYPES.o) - obj = val; - } - return val; - } - - /** - * Sets the value of the given property from the given object. - * @param obj The object from which the property value shall be set. - * @param path The property of which the value shall be set. - * @param val The value of the property which shall be set. - */ - function setObjectPropVal(obj, path, val) { - var splits = path.split(_strDot); - var splitsLength = splits.length; - var i = 0; - var extendObj = {}; - var extendObjRoot = extendObj; - for (; i < splitsLength; i++) - extendObj = extendObj[splits[i]] = i + 1 < splitsLength ? {} : val; - FRAMEWORK.extend(obj, extendObjRoot, true); - } - - - //==== Utils Cache ====// - - /** - * Compares two values or objects and returns true if they aren't equal. - * @param current The first value or object which shall be compared. - * @param cache The second value or object which shall be compared. - * @param force If true the returned value is always true. - * @returns {boolean} True if both values or objects aren't equal or force is true, false otherwise. - */ - function checkCache(current, cache, force) { - if (force) - return force; - if (type(current) == TYPES.o && type(cache) == TYPES.o) { - for (var prop in current) { - if (prop !== 'c') { - if (current[LEXICON.hOP](prop) && cache[LEXICON.hOP](prop)) { - if (checkCache(current[prop], cache[prop])) - return true; - } - else { - return true; - } - } - } - } - else { - return current !== cache; - } - return false; - } - - - //==== Shortcuts ====// - - /** - * jQuery extend method shortcut with a appended "true" as first argument. - */ - function extendDeep() { - return FRAMEWORK.extend.apply(this, [true].concat([].slice.call(arguments))); - } - - /** - * jQuery addClass method shortcut. - */ - function addClass(el, classes) { - return _frameworkProto.addClass.call(el, classes); - } - - /** - * jQuery removeClass method shortcut. - */ - function removeClass(el, classes) { - return _frameworkProto.removeClass.call(el, classes); - } - - /** - * jQuery remove method shortcut. - */ - function remove(el) { - return _frameworkProto.remove.call(el); - } - - /** - * Finds the first child element with the given selector of the given element. - * @param el The root element from which the selector shall be valid. - * @param selector The selector of the searched element. - * @returns {*} The first element which is a child of the given element and matches the givens selector. - */ - function findFirst(el, selector) { - return _frameworkProto.find.call(el, selector).eq(0); - } - - - //==== API ====// - - /** - * 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. - * This behavior can be reset by calling the update method. - */ - _base.sleep = function () { - _sleeping = true; - }; - - /** - * Updates the plugin and DOM to the current options. - * This method should only be called if a update is 100% required. - * @param force True if every property shall be updated and the cache shall be ignored. - * !INTERNAL USAGE! : force can be a string "auto", "sync" or "zoom" too - * 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. - * 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. - * if "zoom" then a update takes place where it's assumed that content and host size changed - * @returns {boolean|undefined} - * If force is "sync" then a boolean is returned which indicates whether a update was needed due to pending changes. - * If force is "auto" then a boolean is returned whether a update was needed due to attribute or size changes. - * undefined otherwise. - */ - _base.update = function (force) { - if (_destroyed) - return; - - var attrsChanged; - var contentSizeC; - var isString = type(force) == TYPES.s; - var imgElementSelector = 'img'; - var imgElementLoadEvent = 'load'; - var doUpdateAuto; - var mutHost; - var mutContent; - - if (isString) { - if (force === _strAuto) { - attrsChanged = meaningfulAttrsChanged(); - contentSizeC = updateAutoContentSizeChanged(); - doUpdateAuto = attrsChanged || contentSizeC; - if (doUpdateAuto) { - update({ - _contentSizeChanged: contentSizeC, - _changedOptions: _initialized ? undefined : _currentPreparedOptions - }); - } - } - else if (force === _strSync) { - if (_mutationObserversConnected) { - mutHost = _mutationObserverHostCallback(_mutationObserverHost.takeRecords()); - mutContent = _mutationObserverContentCallback(_mutationObserverContent.takeRecords()); - } - else { - mutHost = _base.update(_strAuto); - } - } - else if (force === 'zoom') { - update({ - _hostSizeChanged: true, - _contentSizeChanged: true - }); - } - } - else { - force = _sleeping || force; - _sleeping = false; - if (!_base.update(_strSync) || force) - update({ _force: force }); - } - if (!_isTextarea) { - _contentElement.find(imgElementSelector).each(function (i, el) { - var index = COMPATIBILITY.inA(el, _imgs); - if (index === -1) - FRAMEWORK(el).off(imgElementLoadEvent, imgOnLoad).on(imgElementLoadEvent, imgOnLoad); - }); - } - return doUpdateAuto || mutHost || mutContent; - }; - - /** - Gets or sets the current options. The update method will be called automatically if new options were set. - * @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. - * @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. - * @returns {*} - */ - _base.options = function (newOptions, value) { - var option = {}; - var changedOps; - - //return current options if newOptions are undefined or empty - if (FRAMEWORK.isEmptyObject(newOptions) || !FRAMEWORK.isPlainObject(newOptions)) { - if (type(newOptions) == TYPES.s) { - if (arguments.length > 1) { - setObjectPropVal(option, newOptions, value); - changedOps = setOptions(option); - } - else - return getObjectPropVal(_currentOptions, newOptions); - } - else - return _currentOptions; - } - else { - changedOps = setOptions(newOptions); - } - - if (!FRAMEWORK.isEmptyObject(changedOps)) { - update({ _changedOptions: changedOps }); - } - }; - - /** - * Restore the DOM, disconnects all observers, remove all resize observers and put the instance to sleep. - */ - _base.destroy = function () { - if (_destroyed) - return; - - //remove this instance from auto update loop - autoUpdateLoop.remove(_base); - - //disconnect all mutation observers - disconnectMutationObservers(); - - //remove all resize observers - setupResizeObserver(_sizeObserverElement); - setupResizeObserver(_sizeAutoObserverElement); - - //remove all extensions - for (var extName in _extensions) - _base.removeExt(extName); - - //remove all 'destroy' events - while (_destroyEvents[LEXICON.l] > 0) - _destroyEvents.pop()(); - - //remove all events from host element - setupHostMouseTouchEvents(true); - - //remove all helper / detection elements - if (_contentGlueElement) - remove(_contentGlueElement); - if (_contentArrangeElement) - remove(_contentArrangeElement); - if (_sizeAutoObserverAdded) - remove(_sizeAutoObserverElement); - - //remove all generated DOM - setupScrollbarsDOM(true); - setupScrollbarCornerDOM(true); - setupStructureDOM(true); - - //remove all generated image load events - for (var i = 0; i < _imgs[LEXICON.l]; i++) - FRAMEWORK(_imgs[i]).off('load', imgOnLoad); - _imgs = undefined; - - _destroyed = true; - _sleeping = true; - - //remove this instance from the instances list - INSTANCES(pluginTargetElement, 0); - dispatchCallback('onDestroyed'); - - //remove all properties and methods - //for (var property in _base) - // delete _base[property]; - //_base = undefined; - }; - - /** - * Scrolls to a given position or element. - * @param coordinates - * 1. Can be "coordinates" which looks like: - * { x : ?, y : ? } OR Object with x and y properties - * { left : ?, top : ? } OR Object with left and top properties - * { l : ?, t : ? } OR Object with l and t properties - * [ ?, ? ] OR Array where the first two element are the coordinates (first is x, second is y) - * ? A single value which stays for both axis - * A value can be a number, a string or a calculation. - * - * Operators: - * [NONE] The current scroll will be overwritten by the value. - * '+=' The value will be added to the current scroll offset - * '-=' The value will be subtracted from the current scroll offset - * '*=' The current scroll wil be multiplicated by the value. - * '/=' The current scroll wil be divided by the value. - * - * Units: - * [NONE] The value is the final scroll amount. final = (value * 1) - * 'px' Same as none - * '%' The value is dependent on the current scroll value. final = ((currentScrollValue / 100) * value) - * 'vw' The value is multiplicated by the viewport width. final = (value * viewportWidth) - * 'vh' The value is multiplicated by the viewport height. final = (value * viewportHeight) - * - * example final values: - * 200, '200px', '50%', '1vw', '1vh', '+=200', '/=1vw', '*=2px', '-=5vh', '+=33%', '+= 50% - 2px', '-= 1vw - 50%' - * - * 2. Can be a HTML or jQuery element: - * The final scroll offset is the offset (without margin) of the given HTML / jQuery element. - * - * 3. Can be a object with a HTML or jQuery element with additional settings: - * { - * el : [HTMLElement, jQuery element], MUST be specified, else this object isn't valid. - * scroll : [string, array, object], Default value is 'always'. - * block : [string, array, object], Default value is 'begin'. - * margin : [number, boolean, array, object] Default value is false. - * } - * - * Possible scroll settings are: - * 'always' Scrolls always. - * 'ifneeded' Scrolls only if the element isnt fully in view. - * 'never' Scrolls never. - * - * Possible block settings are: - * 'begin' Both axis shall be docked to the "begin" edge. - The element will be docked to the top and left edge of the viewport. - * '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.) - * 'center' Both axis shall be docked to "center". - The element will be centered in the viewport. - * 'nearest' The element will be docked to the nearest edge(s). - * - * Possible margin settings are: -- The actual margin of the element wont be affect, this option affects only the final scroll offset. - * [BOOLEAN] If true the css margin of the element will be used, if false no margin will be used. - * [NUMBER] The margin will be used for all edges. - * - * @param duration The duration of the scroll animation, OR a jQuery animation configuration object. - * @param easing The animation easing. - * @param complete The animation complete callback. - * @returns {{ - * position: {x: number, y: number}, - * ratio: {x: number, y: number}, - * max: {x: number, y: number}, - * handleOffset: {x: number, y: number}, - * handleLength: {x: number, y: number}, - * handleLengthRatio: {x: number, y: number}, t - * rackLength: {x: number, y: number}, - * isRTL: boolean, - * isRTLNormalized: boolean - * }} - */ - _base.scroll = function (coordinates, duration, easing, complete) { - if (arguments.length === 0 || coordinates === undefined) { - var infoX = _scrollHorizontalInfo; - var infoY = _scrollVerticalInfo; - var normalizeInvert = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.i; - var normalizeNegate = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.n; - var scrollX = infoX._currentScroll; - var scrollXRatio = infoX._currentScrollRatio; - var maxScrollX = infoX._maxScroll; - scrollXRatio = normalizeInvert ? 1 - scrollXRatio : scrollXRatio; - scrollX = normalizeInvert ? maxScrollX - scrollX : scrollX; - scrollX *= normalizeNegate ? -1 : 1; - maxScrollX *= normalizeNegate ? -1 : 1; - - return { - position: { - x: scrollX, - y: infoY._currentScroll - }, - ratio: { - x: scrollXRatio, - y: infoY._currentScrollRatio - }, - max: { - x: maxScrollX, - y: infoY._maxScroll - }, - handleOffset: { - x: infoX._handleOffset, - y: infoY._handleOffset - }, - handleLength: { - x: infoX._handleLength, - y: infoY._handleLength - }, - handleLengthRatio: { - x: infoX._handleLengthRatio, - y: infoY._handleLengthRatio - }, - trackLength: { - x: infoX._trackLength, - y: infoY._trackLength - }, - snappedHandleOffset: { - x: infoX._snappedHandleOffset, - y: infoY._snappedHandleOffset - }, - isRTL: _isRTL, - isRTLNormalized: _normalizeRTLCache - }; - } - - _base.update(_strSync); - - var normalizeRTL = _normalizeRTLCache; - var coordinatesXAxisProps = [_strX, _strLeft, 'l']; - var coordinatesYAxisProps = [_strY, _strTop, 't']; - var coordinatesOperators = ['+=', '-=', '*=', '/=']; - var durationIsObject = type(duration) == TYPES.o; - var completeCallback = durationIsObject ? duration.complete : complete; - var i; - var finalScroll = {}; - var specialEasing = {}; - var doScrollLeft; - var doScrollTop; - var animationOptions; - var strEnd = 'end'; - var strBegin = 'begin'; - var strCenter = 'center'; - var strNearest = 'nearest'; - var strAlways = 'always'; - var strNever = 'never'; - var strIfNeeded = 'ifneeded'; - var strLength = LEXICON.l; - var settingsAxis; - var settingsScroll; - var settingsBlock; - var settingsMargin; - var finalElement; - var elementObjSettingsAxisValues = [_strX, _strY, 'xy', 'yx']; - var elementObjSettingsBlockValues = [strBegin, strEnd, strCenter, strNearest]; - var elementObjSettingsScrollValues = [strAlways, strNever, strIfNeeded]; - var coordinatesIsElementObj = coordinates[LEXICON.hOP]('el'); - var possibleElement = coordinatesIsElementObj ? coordinates.el : coordinates; - var possibleElementIsJQuery = possibleElement instanceof FRAMEWORK || JQUERY ? possibleElement instanceof JQUERY : false; - var possibleElementIsHTMLElement = possibleElementIsJQuery ? false : isHTMLElement(possibleElement); - var updateScrollbarInfos = function () { - if (doScrollLeft) - refreshScrollbarHandleOffset(true); - if (doScrollTop) - refreshScrollbarHandleOffset(false); - }; - var proxyCompleteCallback = type(completeCallback) != TYPES.f ? undefined : function () { - updateScrollbarInfos(); - completeCallback(); - }; - function checkSettingsStringValue(currValue, allowedValues) { - for (i = 0; i < allowedValues[strLength]; i++) { - if (currValue === allowedValues[i]) - return true; - } - return false; - } - function getRawScroll(isX, coordinates) { - var coordinateProps = isX ? coordinatesXAxisProps : coordinatesYAxisProps; - coordinates = type(coordinates) == TYPES.s || type(coordinates) == TYPES.n ? [coordinates, coordinates] : coordinates; - - if (type(coordinates) == TYPES.a) - return isX ? coordinates[0] : coordinates[1]; - else if (type(coordinates) == TYPES.o) { - //decides RTL normalization "hack" with .n - //normalizeRTL = type(coordinates.n) == TYPES.b ? coordinates.n : normalizeRTL; - for (i = 0; i < coordinateProps[strLength]; i++) - if (coordinateProps[i] in coordinates) - return coordinates[coordinateProps[i]]; - } - } - function getFinalScroll(isX, rawScroll) { - var isString = type(rawScroll) == TYPES.s; - var operator; - var amount; - var scrollInfo = isX ? _scrollHorizontalInfo : _scrollVerticalInfo; - var currScroll = scrollInfo._currentScroll; - var maxScroll = scrollInfo._maxScroll; - var mult = ' * '; - var finalValue; - var isRTLisX = _isRTL && isX; - var normalizeShortcuts = isRTLisX && _rtlScrollBehavior.n && !normalizeRTL; - var strReplace = 'replace'; - var evalFunc = eval; - var possibleOperator; - if (isString) { - //check operator - if (rawScroll[strLength] > 2) { - possibleOperator = rawScroll.substr(0, 2); - if (inArray(possibleOperator, coordinatesOperators) > -1) - operator = possibleOperator; - } - - //calculate units and shortcuts - rawScroll = operator ? rawScroll.substr(2) : rawScroll; - rawScroll = rawScroll - [strReplace](/min/g, 0) //'min' = 0% - [strReplace](//g, (normalizeShortcuts ? '-' : _strEmpty) + _strHundredPercent) //'>' = 100% - [strReplace](/px/g, _strEmpty) - [strReplace](/%/g, mult + (maxScroll * (isRTLisX && _rtlScrollBehavior.n ? -1 : 1) / 100.0)) - [strReplace](/vw/g, mult + _viewportSize.w) - [strReplace](/vh/g, mult + _viewportSize.h); - amount = parseToZeroOrNumber(isNaN(rawScroll) ? parseToZeroOrNumber(evalFunc(rawScroll), true).toFixed() : rawScroll); - } - else { - amount = rawScroll; - } - - if (amount !== undefined && !isNaN(amount) && type(amount) == TYPES.n) { - var normalizeIsRTLisX = normalizeRTL && isRTLisX; - var operatorCurrScroll = currScroll * (normalizeIsRTLisX && _rtlScrollBehavior.n ? -1 : 1); - var invert = normalizeIsRTLisX && _rtlScrollBehavior.i; - var negate = normalizeIsRTLisX && _rtlScrollBehavior.n; - operatorCurrScroll = invert ? (maxScroll - operatorCurrScroll) : operatorCurrScroll; - switch (operator) { - case '+=': - finalValue = operatorCurrScroll + amount; - break; - case '-=': - finalValue = operatorCurrScroll - amount; - break; - case '*=': - finalValue = operatorCurrScroll * amount; - break; - case '/=': - finalValue = operatorCurrScroll / amount; - break; - default: - finalValue = amount; - break; - } - finalValue = invert ? maxScroll - finalValue : finalValue; - finalValue *= negate ? -1 : 1; - finalValue = isRTLisX && _rtlScrollBehavior.n ? MATH.min(0, MATH.max(maxScroll, finalValue)) : MATH.max(0, MATH.min(maxScroll, finalValue)); - } - return finalValue === currScroll ? undefined : finalValue; - } - function getPerAxisValue(value, valueInternalType, defaultValue, allowedValues) { - var resultDefault = [defaultValue, defaultValue]; - var valueType = type(value); - var valueArrLength; - var valueArrItem; - - //value can be [ string, or array of two strings ] - if (valueType == valueInternalType) { - value = [value, value]; - } - else if (valueType == TYPES.a) { - valueArrLength = value[strLength]; - if (valueArrLength > 2 || valueArrLength < 1) - value = resultDefault; - else { - if (valueArrLength === 1) - value[1] = defaultValue; - for (i = 0; i < valueArrLength; i++) { - valueArrItem = value[i]; - if (type(valueArrItem) != valueInternalType || !checkSettingsStringValue(valueArrItem, allowedValues)) { - value = resultDefault; - break; - } - } - } - } - else if (valueType == TYPES.o) - value = [value[_strX] || defaultValue, value[_strY] || defaultValue]; - else - value = resultDefault; - return { x: value[0], y: value[1] }; - } - function generateMargin(marginTopRightBottomLeftArray) { - var result = []; - var currValue; - var currValueType; - var valueDirections = [_strTop, _strRight, _strBottom, _strLeft]; - for (i = 0; i < marginTopRightBottomLeftArray[strLength]; i++) { - if (i === valueDirections[strLength]) - break; - currValue = marginTopRightBottomLeftArray[i]; - currValueType = type(currValue); - if (currValueType == TYPES.b) - result.push(currValue ? parseToZeroOrNumber(finalElement.css(_strMarginMinus + valueDirections[i])) : 0); - else - result.push(currValueType == TYPES.n ? currValue : 0); - } - return result; - } - - if (possibleElementIsJQuery || possibleElementIsHTMLElement) { - //get settings - var margin = coordinatesIsElementObj ? coordinates.margin : 0; - var axis = coordinatesIsElementObj ? coordinates.axis : 0; - var scroll = coordinatesIsElementObj ? coordinates.scroll : 0; - var block = coordinatesIsElementObj ? coordinates.block : 0; - var marginDefault = [0, 0, 0, 0]; - var marginType = type(margin); - var marginLength; - finalElement = possibleElementIsJQuery ? possibleElement : FRAMEWORK(possibleElement); - - if (finalElement[strLength] > 0) { - //margin can be [ boolean, number, array of 2, array of 4, object ] - if (marginType == TYPES.n || marginType == TYPES.b) - margin = generateMargin([margin, margin, margin, margin]); - else if (marginType == TYPES.a) { - marginLength = margin[strLength]; - if (marginLength === 2) - margin = generateMargin([margin[0], margin[1], margin[0], margin[1]]); - else if (marginLength >= 4) - margin = generateMargin(margin); - else - margin = marginDefault; - } - else if (marginType == TYPES.o) - margin = generateMargin([margin[_strTop], margin[_strRight], margin[_strBottom], margin[_strLeft]]); - else - margin = marginDefault; - - //block = type(block) === TYPES.b ? block ? [ strNearest, strBegin ] : [ strNearest, strEnd ] : block; - settingsAxis = checkSettingsStringValue(axis, elementObjSettingsAxisValues) ? axis : 'xy'; - settingsScroll = getPerAxisValue(scroll, TYPES.s, strAlways, elementObjSettingsScrollValues); - settingsBlock = getPerAxisValue(block, TYPES.s, strBegin, elementObjSettingsBlockValues); - settingsMargin = margin; - - var viewportScroll = { - l: _scrollHorizontalInfo._currentScroll, - t: _scrollVerticalInfo._currentScroll - }; - // use padding element instead of viewport element because padding element has never padding, margin or position applied. - var viewportOffset = _paddingElement.offset(); - - //get coordinates - var elementOffset = finalElement.offset(); - var doNotScroll = { - x: settingsScroll.x == strNever || settingsAxis == _strY, - y: settingsScroll.y == strNever || settingsAxis == _strX - }; - elementOffset[_strTop] -= settingsMargin[0]; - elementOffset[_strLeft] -= settingsMargin[3]; - var elementScrollCoordinates = { - x: MATH.round(elementOffset[_strLeft] - viewportOffset[_strLeft] + viewportScroll.l), - y: MATH.round(elementOffset[_strTop] - viewportOffset[_strTop] + viewportScroll.t) - }; - if (_isRTL) { - if (!_rtlScrollBehavior.n && !_rtlScrollBehavior.i) - elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + viewportScroll.l); - if (_rtlScrollBehavior.n && normalizeRTL) - elementScrollCoordinates.x *= -1; - if (_rtlScrollBehavior.i && normalizeRTL) - elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + (_scrollHorizontalInfo._maxScroll - viewportScroll.l)); - } - - //measuring is required - if (settingsBlock.x != strBegin || settingsBlock.y != strBegin || settingsScroll.x == strIfNeeded || settingsScroll.y == strIfNeeded || _isRTL) { - var measuringElm = finalElement[0]; - var rawElementSize = _supportTransform ? measuringElm[LEXICON.bCR]() : { - width: measuringElm[LEXICON.oW], - height: measuringElm[LEXICON.oH] - }; - var elementSize = { - w: rawElementSize[_strWidth] + settingsMargin[3] + settingsMargin[1], - h: rawElementSize[_strHeight] + settingsMargin[0] + settingsMargin[2] - }; - var finalizeBlock = function (isX) { - var vars = getScrollbarVars(isX); - var wh = vars._w_h; - var lt = vars._left_top; - var xy = vars._x_y; - var blockIsEnd = settingsBlock[xy] == (isX ? _isRTL ? strBegin : strEnd : strEnd); - var blockIsCenter = settingsBlock[xy] == strCenter; - var blockIsNearest = settingsBlock[xy] == strNearest; - var scrollNever = settingsScroll[xy] == strNever; - var scrollIfNeeded = settingsScroll[xy] == strIfNeeded; - var vpSize = _viewportSize[wh]; - var vpOffset = viewportOffset[lt]; - var elSize = elementSize[wh]; - var elOffset = elementOffset[lt]; - var divide = blockIsCenter ? 2 : 1; - var elementCenterOffset = elOffset + (elSize / 2); - var viewportCenterOffset = vpOffset + (vpSize / 2); - var isInView = - elSize <= vpSize - && elOffset >= vpOffset - && elOffset + elSize <= vpOffset + vpSize; - - if (scrollNever) - doNotScroll[xy] = true; - else if (!doNotScroll[xy]) { - if (blockIsNearest || scrollIfNeeded) { - doNotScroll[xy] = scrollIfNeeded ? isInView : false; - blockIsEnd = elSize < vpSize ? elementCenterOffset > viewportCenterOffset : elementCenterOffset < viewportCenterOffset; - } - elementScrollCoordinates[xy] -= blockIsEnd || blockIsCenter ? ((vpSize / divide) - (elSize / divide)) * (isX && _isRTL && normalizeRTL ? -1 : 1) : 0; - } - }; - finalizeBlock(true); - finalizeBlock(false); - } - - if (doNotScroll.y) - delete elementScrollCoordinates.y; - if (doNotScroll.x) - delete elementScrollCoordinates.x; - - coordinates = elementScrollCoordinates; - } - } - - finalScroll[_strScrollLeft] = getFinalScroll(true, getRawScroll(true, coordinates)); - finalScroll[_strScrollTop] = getFinalScroll(false, getRawScroll(false, coordinates)); - doScrollLeft = finalScroll[_strScrollLeft] !== undefined; - doScrollTop = finalScroll[_strScrollTop] !== undefined; - - if ((doScrollLeft || doScrollTop) && (duration > 0 || durationIsObject)) { - if (durationIsObject) { - duration.complete = proxyCompleteCallback; - _viewportElement.animate(finalScroll, duration); - } - else { - animationOptions = { - duration: duration, - complete: proxyCompleteCallback - }; - if (type(easing) == TYPES.a || FRAMEWORK.isPlainObject(easing)) { - specialEasing[_strScrollLeft] = easing[0] || easing.x; - specialEasing[_strScrollTop] = easing[1] || easing.y; - animationOptions.specialEasing = specialEasing; - } - else { - animationOptions.easing = easing; - } - _viewportElement.animate(finalScroll, animationOptions); - } - } - else { - if (doScrollLeft) - _viewportElement[_strScrollLeft](finalScroll[_strScrollLeft]); - if (doScrollTop) - _viewportElement[_strScrollTop](finalScroll[_strScrollTop]); - updateScrollbarInfos(); - } - }; - - /** - * Stops all scroll animations. - * @returns {*} The current OverlayScrollbars instance (for chaining). - */ - _base.scrollStop = function (param1, param2, param3) { - _viewportElement.stop(param1, param2, param3); - return _base; - }; - - /** - * Returns all relevant elements. - * @param elementName The name of the element which shall be returned. - * @returns {{target: *, host: *, padding: *, viewport: *, content: *, scrollbarHorizontal: {scrollbar: *, track: *, handle: *}, scrollbarVertical: {scrollbar: *, track: *, handle: *}, scrollbarCorner: *} | *} - */ - _base.getElements = function (elementName) { - var obj = { - target: _targetElementNative, - host: _hostElementNative, - padding: _paddingElementNative, - viewport: _viewportElementNative, - content: _contentElementNative, - scrollbarHorizontal: { - scrollbar: _scrollbarHorizontalElement[0], - track: _scrollbarHorizontalTrackElement[0], - handle: _scrollbarHorizontalHandleElement[0] - }, - scrollbarVertical: { - scrollbar: _scrollbarVerticalElement[0], - track: _scrollbarVerticalTrackElement[0], - handle: _scrollbarVerticalHandleElement[0] - }, - scrollbarCorner: _scrollbarCornerElement[0] - }; - return type(elementName) == TYPES.s ? getObjectPropVal(obj, elementName) : obj; - }; - - /** - * Returns a object which describes the current state of this instance. - * @param stateProperty A specific property from the state object which shall be returned. - * @returns {{widthAuto, heightAuto, overflowAmount, hideOverflow, hasOverflow, contentScrollSize, viewportSize, hostSize, autoUpdate} | *} - */ - _base.getState = function (stateProperty) { - function prepare(obj) { - if (!FRAMEWORK.isPlainObject(obj)) - return obj; - var extended = extendDeep({}, obj); - var changePropertyName = function (from, to) { - if (extended[LEXICON.hOP](from)) { - extended[to] = extended[from]; - delete extended[from]; - } - }; - changePropertyName('w', _strWidth); //change w to width - changePropertyName('h', _strHeight); //change h to height - delete extended.c; //delete c (the 'changed' prop) - return extended; - }; - var obj = { - destroyed: !!prepare(_destroyed), - sleeping: !!prepare(_sleeping), - autoUpdate: prepare(!_mutationObserversConnected), - widthAuto: prepare(_widthAutoCache), - heightAuto: prepare(_heightAutoCache), - padding: prepare(_cssPaddingCache), - overflowAmount: prepare(_overflowAmountCache), - hideOverflow: prepare(_hideOverflowCache), - hasOverflow: prepare(_hasOverflowCache), - contentScrollSize: prepare(_contentScrollSizeCache), - viewportSize: prepare(_viewportSize), - hostSize: prepare(_hostSizeCache), - documentMixed: prepare(_documentMixed) - }; - return type(stateProperty) == TYPES.s ? getObjectPropVal(obj, stateProperty) : obj; - }; - - /** - * Gets all or specific extension instance. - * @param extName The name of the extension from which the instance shall be got. - * @returns {{}} The instance of the extension with the given name or undefined if the instance couldn't be found. - */ - _base.ext = function (extName) { - var result; - var privateMethods = _extensionsPrivateMethods.split(' '); - var i = 0; - if (type(extName) == TYPES.s) { - if (_extensions[LEXICON.hOP](extName)) { - result = extendDeep({}, _extensions[extName]); - for (; i < privateMethods.length; i++) - delete result[privateMethods[i]]; - } - } - else { - result = {}; - for (i in _extensions) - result[i] = extendDeep({}, _base.ext(i)); - } - return result; - }; - - /** - * Adds a extension to this instance. - * @param extName The name of the extension which shall be added. - * @param extensionOptions The extension options which shall be used. - * @returns {{}} The instance of the added extension or undefined if the extension couldn't be added properly. - */ - _base.addExt = function (extName, extensionOptions) { - var registeredExtensionObj = _plugin.extension(extName); - var instance; - var instanceAdded; - var instanceContract; - var contractResult; - var contractFulfilled = true; - if (registeredExtensionObj) { - if (!_extensions[LEXICON.hOP](extName)) { - instance = registeredExtensionObj.extensionFactory.call(_base, - extendDeep({}, registeredExtensionObj.defaultOptions), - FRAMEWORK, - COMPATIBILITY); - - if (instance) { - instanceContract = instance.contract; - if (type(instanceContract) == TYPES.f) { - contractResult = instanceContract(window); - contractFulfilled = type(contractResult) == TYPES.b ? contractResult : contractFulfilled; - } - if (contractFulfilled) { - _extensions[extName] = instance; - instanceAdded = instance.added; - if (type(instanceAdded) == TYPES.f) - instanceAdded(extensionOptions); - - return _base.ext(extName); - } - } - } - else - return _base.ext(extName); - } - else - console.warn("A extension with the name \"" + extName + "\" isn't registered."); - }; - - /** - * Removes a extension from this instance. - * @param extName The name of the extension which shall be removed. - * @returns {boolean} True if the extension was removed, false otherwise e.g. if the extension wasn't added before. - */ - _base.removeExt = function (extName) { - var instance = _extensions[extName]; - var instanceRemoved; - if (instance) { - delete _extensions[extName]; - - instanceRemoved = instance.removed; - if (type(instanceRemoved) == TYPES.f) - instanceRemoved(); - - return true; - } - return false; - }; - - /** - * Constructs the plugin. - * @param targetElement The element to which the plugin shall be applied. - * @param options The initial options of the plugin. - * @param extensions The extension(s) which shall be added right after the initialization. - * @returns {boolean} True if the plugin was successfully initialized, false otherwise. - */ - function construct(targetElement, options, extensions) { - _defaultOptions = globals.defaultOptions; - _nativeScrollbarStyling = globals.nativeScrollbarStyling; - _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); - _nativeScrollbarIsOverlaid = extendDeep({}, globals.nativeScrollbarIsOverlaid); - _overlayScrollbarDummySize = extendDeep({}, globals.overlayScrollbarDummySize); - _rtlScrollBehavior = extendDeep({}, globals.rtlScrollBehavior); - - //parse & set options but don't update - setOptions(extendDeep({}, _defaultOptions, options)); - - _cssCalc = globals.cssCalc; - _msieVersion = globals.msie; - _autoUpdateRecommended = globals.autoUpdateRecommended; - _supportTransition = globals.supportTransition; - _supportTransform = globals.supportTransform; - _supportPassiveEvents = globals.supportPassiveEvents; - _supportResizeObserver = globals.supportResizeObserver; - _supportMutationObserver = globals.supportMutationObserver; - _restrictedMeasuring = globals.restrictedMeasuring; - _documentElement = FRAMEWORK(targetElement.ownerDocument); - _documentElementNative = _documentElement[0]; - _windowElement = FRAMEWORK(_documentElementNative.defaultView || _documentElementNative.parentWindow); - _windowElementNative = _windowElement[0]; - _htmlElement = findFirst(_documentElement, 'html'); - _bodyElement = findFirst(_htmlElement, 'body'); - _targetElement = FRAMEWORK(targetElement); - _targetElementNative = _targetElement[0]; - _isTextarea = _targetElement.is('textarea'); - _isBody = _targetElement.is('body'); - _documentMixed = _documentElementNative !== document; - - /* On a div Element The if checks only whether: - * - the targetElement has the class "os-host" - * - the targetElement has a a child with the class "os-padding" - * - * If that's the case, its assumed the DOM has already the following structure: - * (The ".os-host" element is the targetElement) - * - *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- * - * ===================================================================================== - * - * On a Textarea Element The if checks only whether: - * - the targetElement has the class "os-textarea" - * - the targetElement is inside a element with the class "os-content" - * - * If that's the case, its assumed the DOM has already the following structure: - * (The ".os-textarea" (textarea) element is the targetElement) - * - *
- *
- *
- *
- *
- *
- * - *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- */ - _domExists = _isTextarea - ? _targetElement.hasClass(_classNameTextareaElement) && _targetElement.parent().hasClass(_classNameContentElement) - : _targetElement.hasClass(_classNameHostElement) && _targetElement.children(_strDot + _classNamePaddingElement)[LEXICON.l]; - - var initBodyScroll; - var bodyMouseTouchDownListener; - - //check if the plugin hasn't to be initialized - if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y && !_currentPreparedOptions.nativeScrollbarsOverlaid.initialize) { - dispatchCallback('onInitializationWithdrawn'); - if (_domExists) { - setupStructureDOM(true); - setupScrollbarsDOM(true); - setupScrollbarCornerDOM(true); - } - - _destroyed = true; - _sleeping = true; - - return _base; - } - - if (_isBody) { - initBodyScroll = {}; - initBodyScroll.l = MATH.max(_targetElement[_strScrollLeft](), _htmlElement[_strScrollLeft](), _windowElement[_strScrollLeft]()); - initBodyScroll.t = MATH.max(_targetElement[_strScrollTop](), _htmlElement[_strScrollTop](), _windowElement[_strScrollTop]()); - - bodyMouseTouchDownListener = function () { - _viewportElement.removeAttr(LEXICON.ti); - setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, true, true); - } - } - - //build OverlayScrollbars DOM - setupStructureDOM(); - setupScrollbarsDOM(); - setupScrollbarCornerDOM(); - - //create OverlayScrollbars events - setupStructureEvents(); - setupScrollbarEvents(true); - setupScrollbarEvents(false); - setupScrollbarCornerEvents(); - - //create mutation observers - createMutationObservers(); - - //build resize observer for the host element - setupResizeObserver(_sizeObserverElement, hostOnResized); - - if (_isBody) { - //apply the body scroll to handle it right in the update method - _viewportElement[_strScrollLeft](initBodyScroll.l)[_strScrollTop](initBodyScroll.t); - - //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 - if (document.activeElement == targetElement && _viewportElementNative.focus) { - //set a tabindex to make the viewportElement focusable - _viewportElement.attr(LEXICON.ti, '-1'); - _viewportElementNative.focus(); - - /* the tabindex has to be removed due to; - * If you set the tabindex attribute on an
, then its child content cannot be scrolled with the arrow keys unless you set tabindex on the content, too - * https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex - */ - setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, false, true); - } - } - - //update for the first time & initialize cache - _base.update(_strAuto); - - //the plugin is initialized now! - _initialized = true; - dispatchCallback('onInitialized'); - - //call all callbacks which would fire before the initialized was complete - each(_callbacksInitQeueue, function (index, value) { dispatchCallback(value.n, value.a); }); - _callbacksInitQeueue = []; - - //add extensions - if (type(extensions) == TYPES.s) - extensions = [extensions]; - if (COMPATIBILITY.isA(extensions)) - each(extensions, function (index, value) { _base.addExt(value); }); - else if (FRAMEWORK.isPlainObject(extensions)) - each(extensions, function (key, value) { _base.addExt(key, value); }); - - //add the transition class for transitions AFTER the first update & AFTER the applied extensions (for preventing unwanted transitions) - setTimeout(function () { - if (_supportTransition && !_destroyed) - addClass(_hostElement, _classNameHostTransition); - }, 333); - - return _base; - } - - if (_plugin.valid(construct(pluginTargetElement, options, extensions))) { - INSTANCES(pluginTargetElement, _base); - } - - return _base; - } - - /** - * Initializes a new OverlayScrollbarsInstance object or changes options if already initialized or returns the current instance. - * @param pluginTargetElements The elements to which the Plugin shall be initialized. - * @param options The custom options with which the plugin shall be initialized. - * @param extensions The extension(s) which shall be added right after initialization. - * @returns {*} - */ - _plugin = window[PLUGINNAME] = function (pluginTargetElements, options, extensions) { - if (arguments[LEXICON.l] === 0) - return this; - - var arr = []; - var optsIsPlainObj = FRAMEWORK.isPlainObject(options); - var inst; - var result; - - //pluginTargetElements is null or undefined - if (!pluginTargetElements) - return optsIsPlainObj || !options ? result : arr; - - /* - pluginTargetElements will be converted to: - 1. A jQueryElement Array - 2. A HTMLElement Array - 3. A Array with a single HTML Element - so pluginTargetElements is always a array. - */ - pluginTargetElements = pluginTargetElements[LEXICON.l] != undefined ? pluginTargetElements : [pluginTargetElements[0] || pluginTargetElements]; - initOverlayScrollbarsStatics(); - - if (pluginTargetElements[LEXICON.l] > 0) { - if (optsIsPlainObj) { - FRAMEWORK.each(pluginTargetElements, function (i, v) { - inst = v; - if (inst !== undefined) - arr.push(OverlayScrollbarsInstance(inst, options, extensions, _pluginsGlobals, _pluginsAutoUpdateLoop)); - }); - } - else { - FRAMEWORK.each(pluginTargetElements, function (i, v) { - inst = INSTANCES(v); - if ((options === '!' && _plugin.valid(inst)) || (COMPATIBILITY.type(options) == TYPES.f && options(v, inst))) - arr.push(inst); - else if (options === undefined) - arr.push(inst); - }); - } - result = arr[LEXICON.l] === 1 ? arr[0] : arr; - } - return result; - }; - - /** - * Returns a object which contains global information about the plugin and each instance of it. - * The returned object is just a copy, that means that changes to the returned object won't have any effect to the original object. - */ - _plugin.globals = function () { - initOverlayScrollbarsStatics(); - var globals = FRAMEWORK.extend(true, {}, _pluginsGlobals); - delete globals['msie']; - return globals; - }; - - /** - * Gets or Sets the default options for each new plugin initialization. - * @param newDefaultOptions The object with which the default options shall be extended. - */ - _plugin.defaultOptions = function (newDefaultOptions) { - initOverlayScrollbarsStatics(); - var currDefaultOptions = _pluginsGlobals.defaultOptions; - if (newDefaultOptions === undefined) - return FRAMEWORK.extend(true, {}, currDefaultOptions); - - //set the new default options - _pluginsGlobals.defaultOptions = FRAMEWORK.extend(true, {}, currDefaultOptions, _pluginsOptions._validate(newDefaultOptions, _pluginsOptions._template, true, currDefaultOptions)._default); - }; - - /** - * Checks whether the passed instance is a non-destroyed OverlayScrollbars instance. - * @param osInstance The potential OverlayScrollbars instance which shall be checked. - * @returns {boolean} True if the passed value is a non-destroyed OverlayScrollbars instance, false otherwise. - */ - _plugin.valid = function (osInstance) { - return osInstance instanceof _plugin && !osInstance.getState().destroyed; - }; - - /** - * Registers, Unregisters or returns a extension. - * Register: Pass the name and the extension. (defaultOptions is optional) - * Unregister: Pass the name and anything except a function as extension parameter. - * Get extension: Pass the name of the extension which shall be got. - * Get all extensions: Pass no arguments. - * @param extensionName The name of the extension which shall be registered, unregistered or returned. - * @param extension A function which generates the instance of the extension or anything other to remove a already registered extension. - * @param defaultOptions The default options which shall be used for the registered extension. - */ - _plugin.extension = function (extensionName, extension, defaultOptions) { - var extNameTypeString = COMPATIBILITY.type(extensionName) == TYPES.s; - var argLen = arguments[LEXICON.l]; - var i = 0; - if (argLen < 1 || !extNameTypeString) { - //return a copy of all extension objects - return FRAMEWORK.extend(true, { length: _pluginsExtensions[LEXICON.l] }, _pluginsExtensions); - } - else if (extNameTypeString) { - if (COMPATIBILITY.type(extension) == TYPES.f) { - //register extension - _pluginsExtensions.push({ - name: extensionName, - extensionFactory: extension, - defaultOptions: defaultOptions - }); - } - else { - for (; i < _pluginsExtensions[LEXICON.l]; i++) { - if (_pluginsExtensions[i].name === extensionName) { - if (argLen > 1) - _pluginsExtensions.splice(i, 1); //remove extension - else - return FRAMEWORK.extend(true, {}, _pluginsExtensions[i]); //return extension with the given name - } - } - } - } - }; - - return _plugin; - })(); - - if (JQUERY && JQUERY.fn) { - /** - * The jQuery initialization interface. - * @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. - * @param extensions The extension(s) which shall be added right after initialization. - * @returns {*} After initialization it returns the jQuery element array, else it returns the instance(s) of the elements which are selected. - */ - JQUERY.fn.overlayScrollbars = function (options, extensions) { - var _elements = this; - if (JQUERY.isPlainObject(options)) { - JQUERY.each(_elements, function () { PLUGIN(this, options, extensions); }); - return _elements; - } - else - return PLUGIN(_elements, options); - }; - } - return PLUGIN; - } +/*! + * OverlayScrollbars + * https://github.com/KingSora/OverlayScrollbars + * + * Version: 1.11.0 + * + * Copyright KingSora | Rene Haas. + * https://github.com/KingSora + * + * Released under the MIT license. + * Date: 29.02.2020 + */ + +(function (global, factory) { + if (typeof define === 'function' && define.amd) + define(['jquery'], function(framework) { return factory(global, global.document, undefined, framework); }); + else if (typeof module === 'object' && typeof module.exports === 'object') + module.exports = factory(global, global.document, undefined, require('jquery')); + else + factory(global, global.document, undefined, global.jQuery); +}(typeof window !== 'undefined' ? window : this, + function(window, document, undefined, framework) { + 'use strict'; + var PLUGINNAME = 'OverlayScrollbars'; + var TYPES = { + o : 'object', + f : 'function', + a : 'array', + s : 'string', + b : 'boolean', + n : 'number', + u : 'undefined', + z : 'null' + //d : 'date', + //e : 'error', + //r : 'regexp', + //y : 'symbol' + }; + var LEXICON = { + c: 'class', + s: 'style', + i: 'id', + l: 'length', + p: 'prototype', + ti: 'tabindex', + oH: 'offsetHeight', + cH: 'clientHeight', + sH: 'scrollHeight', + oW: 'offsetWidth', + cW: 'clientWidth', + sW: 'scrollWidth', + hOP: 'hasOwnProperty', + bCR: 'getBoundingClientRect' + }; + var VENDORS = (function() { + //https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix + var jsCache = { }; + var cssCache = { }; + var cssPrefixes = ['-webkit-', '-moz-', '-o-', '-ms-']; + var jsPrefixes = ['WebKit', 'Moz', 'O', 'MS']; + function firstLetterToUpper(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + + return { + _cssPrefixes: cssPrefixes, + _jsPrefixes: jsPrefixes, + _cssProperty : function(name) { + var result = cssCache[name]; + + if(cssCache[LEXICON.hOP](name)) + return result; + + var uppercasedName = firstLetterToUpper(name); + var elmStyle = document.createElement('div')[LEXICON.s]; + var resultPossibilities; + var i = 0; + var v; + var currVendorWithoutDashes; + + for (; i < cssPrefixes.length; i++) { + currVendorWithoutDashes = cssPrefixes[i].replace(/-/g, ''); + resultPossibilities = [ + name, //transition + cssPrefixes[i] + name, //-webkit-transition + currVendorWithoutDashes + uppercasedName, //webkitTransition + firstLetterToUpper(currVendorWithoutDashes) + uppercasedName //WebkitTransition + ]; + for(v = 0; v < resultPossibilities[LEXICON.l]; v++) { + if(elmStyle[resultPossibilities[v]] !== undefined) { + result = resultPossibilities[v]; + break; + } + } + } + + cssCache[name] = result; + return result; + }, + _jsAPI : function(name, isInterface, fallback) { + var i = 0; + var result = jsCache[name]; + + if(!jsCache[LEXICON.hOP](name)) { + result = window[name]; + for(; i < jsPrefixes[LEXICON.l]; i++) + result = result || window[(isInterface ? jsPrefixes[i] : jsPrefixes[i].toLowerCase()) + firstLetterToUpper(name)]; + jsCache[name] = result; + } + return result || fallback; + } + + } + })(); + var COMPATIBILITY = (function() { + function windowSize(x) { + return x ? window.innerWidth || document.documentElement[LEXICON.cW] || document.body[LEXICON.cW] : window.innerHeight || document.documentElement[LEXICON.cH] || document.body[LEXICON.cH]; + } + function bind(func, thisObj) { + if (typeof func != TYPES.f) { + throw "Can't bind function!"; + // closest thing possible to the ECMAScript 5 + // internal IsCallable function + //throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + var proto = LEXICON.p; + var aArgs = Array[proto].slice.call(arguments, 2); + var fNOP = function() {}; + var fBound = function() { return func.apply(this instanceof fNOP ? this : thisObj, aArgs.concat(Array[proto].slice.call(arguments))); }; + + if (func[proto]) + fNOP[proto] = func[proto]; // Function.prototype doesn't have a prototype property + fBound[proto] = new fNOP(); + + return fBound; + } + + return { + /** + * Gets the current window width. + * @returns {Number|number} The current window width in pixel. + */ + wW: bind(windowSize, 0, true), + + /** + * Gets the current window height. + * @returns {Number|number} The current window height in pixel. + */ + wH: bind(windowSize, 0), + + /** + * Gets the MutationObserver Object or undefined if not supported. + * @returns {MutationObserver|*|undefined} The MutationsObserver Object or undefined. + */ + mO: bind(VENDORS._jsAPI, 0, 'MutationObserver', true), + + /** + * Gets the ResizeObserver Object or undefined if not supported. + * @returns {MutationObserver|*|undefined} The ResizeObserver Object or undefined. + */ + rO: bind(VENDORS._jsAPI, 0, 'ResizeObserver', true), + + /** + * Gets the RequestAnimationFrame method or it's corresponding polyfill. + * @returns {*|Function} The RequestAnimationFrame method or it's corresponding polyfill. + */ + rAF: bind(VENDORS._jsAPI, 0, 'requestAnimationFrame', false, function (func) { return window.setTimeout(func, 1000 / 60); }), + + /** + * Gets the CancelAnimationFrame method or it's corresponding polyfill. + * @returns {*|Function} The CancelAnimationFrame method or it's corresponding polyfill. + */ + cAF: bind(VENDORS._jsAPI, 0, 'cancelAnimationFrame', false, function (id) { return window.clearTimeout(id); }), + + /** + * Gets the current time. + * @returns {number} The current time. + */ + now: function() { + return Date.now && Date.now() || new Date().getTime(); + }, + + /** + * Stops the propagation of the given event. + * @param event The event of which the propagation shall be stoped. + */ + stpP: function(event) { + if(event.stopPropagation) + event.stopPropagation(); + else + event.cancelBubble = true; + }, + + /** + * Prevents the default action of the given event. + * @param event The event of which the default action shall be prevented. + */ + prvD: function(event) { + if(event.preventDefault && event.cancelable) + event.preventDefault(); + else + event.returnValue = false; + }, + + /** + * Gets the pageX and pageY values of the given mouse event. + * @param event The mouse event of which the pageX and pageX shall be got. + * @returns {{x: number, y: number}} x = pageX value, y = pageY value. + */ + page: function(event) { + event = event.originalEvent || event; + + var strPage = 'page'; + var strClient = 'client'; + var strX = 'X'; + var strY = 'Y'; + var target = event.target || event.srcElement || document; + var eventDoc = target.ownerDocument || document; + var doc = eventDoc.documentElement; + var body = eventDoc.body; + + //if touch event return return pageX/Y of it + if(event.touches !== undefined) { + var touch = event.touches[0]; + return { + x : touch[strPage + strX], + y : touch[strPage + strY] + } + } + + // Calculate pageX/Y if not native supported + if (!event[strPage + strX] && event[strClient + strX] && event[strClient + strX] != null) { + + return { + x : event[strClient + strX] + + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - + (doc && doc.clientLeft || body && body.clientLeft || 0), + y : event[strClient + strY] + + (doc && doc.scrollTop || body && body.scrollTop || 0) - + (doc && doc.clientTop || body && body.clientTop || 0) + } + } + return { + x : event[strPage + strX], + y : event[strPage + strY] + }; + }, + + /** + * Gets the clicked mouse button of the given mouse event. + * @param event The mouse event of which the clicked button shal be got. + * @returns {number} The number of the clicked mouse button. (0 : none | 1 : leftButton | 2 : middleButton | 3 : rightButton) + */ + mBtn: function(event) { + var button = event.button; + if (!event.which && button !== undefined) + return (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); + else + return event.which; + }, + + /** + * Checks whether a item is in the given array and returns its index. + * @param item The item of which the position in the array shall be determined. + * @param arr The array. + * @returns {number} The zero based index of the item or -1 if the item isn't in the array. + */ + inA : function(item, arr) { + for (var i = 0; i < arr[LEXICON.l]; i++) + //Sometiems in IE a "SCRIPT70" Permission denied error occurs if HTML elements in a iFrame are compared + try { + if (arr[i] === item) + return i; + } + catch(e) { } + return -1; + }, + + /** + * Returns true if the given value is a array. + * @param arr The potential array. + * @returns {boolean} True if the given value is a array, false otherwise. + */ + isA: function(arr) { + var def = Array.isArray; + return def ? def(arr) : this.type(arr) == TYPES.a; + }, + + /** + * Determine the internal JavaScript [[Class]] of the given object. + * @param obj The object of which the type shall be determined. + * @returns {string} The type of the given object. + */ + type: function(obj) { + if (obj === undefined) + return obj + ''; + if (obj === null) + return obj + ''; + return Object[LEXICON.p].toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase(); + }, + + + bind: bind + + /** + * Gets the vendor-prefixed CSS property by the given name. + * For example the given name is "transform" and you're using a old Firefox browser then the returned value would be "-moz-transform". + * If the browser doesn't need a vendor-prefix, then the returned string is the given name. + * If the browser doesn't support the given property name at all (not even with a vendor-prefix) the returned value is null. + * @param propName The unprefixed CSS property name. + * @returns {string|null} The vendor-prefixed CSS property or null if the browser doesn't support the given CSS property. + + cssProp: function(propName) { + return VENDORS._cssProperty(propName); + } + */ + } + })(); + + var MATH = Math; + var JQUERY = framework; + var EASING = framework.easing; + var FRAMEWORK = framework; + var INSTANCES = (function () { + var _targets = []; + var _instancePropertyString = '__overlayScrollbars__'; + + /** + * Register, unregister or get a certain (or all) instances. + * Register: Pass the target and the instance. + * Unregister: Pass the target and null. + * Get Instance: Pass the target from which the instance shall be got. + * Get Targets: Pass no arguments. + * @param target The target to which the instance shall be registered / from which the instance shall be unregistered / the instance shall be got + * @param instance The instance. + * @returns {*|void} Returns the instance from the given target. + */ + return function (target, instance) { + var argLen = arguments[LEXICON.l]; + if (argLen < 1) { + //return all targets + return _targets; + } + else { + if (instance) { + //register instance + target[_instancePropertyString] = instance; + _targets.push(target); + } + else { + var index = COMPATIBILITY.inA(target, _targets); + if (index > -1) { + if (argLen > 1) { + //unregister instance + delete target[_instancePropertyString]; + _targets.splice(index, 1); + } + else { + //get instance from target + return _targets[index][_instancePropertyString]; + } + } + } + } + } + })(); + var PLUGIN = (function () { + var _plugin; + var _pluginsGlobals; + var _pluginsAutoUpdateLoop; + var _pluginsExtensions = []; + var _pluginsOptions = (function () { + var type = COMPATIBILITY.type; + var possibleTemplateTypes = [ + TYPES.b, //boolean + TYPES.n, //number + TYPES.s, //string + TYPES.a, //array + TYPES.o, //object + TYPES.f, //function + TYPES.z //null + ]; + var restrictedStringsSplit = ' '; + var restrictedStringsPossibilitiesSplit = ':'; + var classNameAllowedValues = [TYPES.z, TYPES.s]; + var numberAllowedValues = TYPES.n; + var booleanNullAllowedValues = [TYPES.z, TYPES.b]; + var booleanTrueTemplate = [true, TYPES.b]; + var booleanFalseTemplate = [false, TYPES.b]; + var callbackTemplate = [null, [TYPES.z, TYPES.f]]; + var inheritedAttrsTemplate = [['style', 'class'], [TYPES.s, TYPES.a, TYPES.z]]; + var resizeAllowedValues = 'n:none b:both h:horizontal v:vertical'; + var overflowBehaviorAllowedValues = 'v-h:visible-hidden v-s:visible-scroll s:scroll h:hidden'; + var scrollbarsVisibilityAllowedValues = 'v:visible h:hidden a:auto'; + var scrollbarsAutoHideAllowedValues = 'n:never s:scroll l:leave m:move'; + var optionsDefaultsAndTemplate = { + className: ['os-theme-dark', classNameAllowedValues], //null || string + resize: ['none', resizeAllowedValues], //none || both || horizontal || vertical || n || b || h || v + sizeAutoCapable: booleanTrueTemplate, //true || false + clipAlways: booleanTrueTemplate, //true || false + normalizeRTL: booleanTrueTemplate, //true || false + paddingAbsolute: booleanFalseTemplate, //true || false + autoUpdate: [null, booleanNullAllowedValues], //true || false || null + autoUpdateInterval: [33, numberAllowedValues], //number + nativeScrollbarsOverlaid: { + showNativeScrollbars: booleanFalseTemplate, //true || false + initialize: booleanTrueTemplate //true || false + }, + overflowBehavior: { + x: ['scroll', overflowBehaviorAllowedValues], //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s + y: ['scroll', overflowBehaviorAllowedValues] //visible-hidden || visible-scroll || hidden || scroll || v-h || v-s || h || s + }, + scrollbars: { + visibility: ['auto', scrollbarsVisibilityAllowedValues], //visible || hidden || auto || v || h || a + autoHide: ['never', scrollbarsAutoHideAllowedValues], //never || scroll || leave || move || n || s || l || m + autoHideDelay: [800, numberAllowedValues], //number + dragScrolling: booleanTrueTemplate, //true || false + clickScrolling: booleanFalseTemplate, //true || false + touchSupport: booleanTrueTemplate, //true || false + snapHandle: booleanFalseTemplate //true || false + }, + textarea: { + dynWidth: booleanFalseTemplate, //true || false + dynHeight: booleanFalseTemplate, //true || false + inheritedAttrs: inheritedAttrsTemplate //string || array || null + }, + callbacks: { + onInitialized: callbackTemplate, //null || function + onInitializationWithdrawn: callbackTemplate, //null || function + onDestroyed: callbackTemplate, //null || function + onScrollStart: callbackTemplate, //null || function + onScroll: callbackTemplate, //null || function + onScrollStop: callbackTemplate, //null || function + onOverflowChanged: callbackTemplate, //null || function + onOverflowAmountChanged: callbackTemplate, //null || function + onDirectionChanged: callbackTemplate, //null || function + onContentSizeChanged: callbackTemplate, //null || function + onHostSizeChanged: callbackTemplate, //null || function + onUpdated: callbackTemplate //null || function + } + }; + var convert = function (template) { + var recursive = function (obj) { + var key; + var val; + var valType; + for (key in obj) { + if (!obj[LEXICON.hOP](key)) + continue; + val = obj[key]; + valType = type(val); + if (valType == TYPES.a) + obj[key] = val[template ? 1 : 0]; + else if (valType == TYPES.o) + obj[key] = recursive(val); + } + return obj; + }; + return recursive(FRAMEWORK.extend(true, {}, optionsDefaultsAndTemplate)); + }; + + return { + _defaults: convert(), + + _template: convert(true), + + /** + * Validates the passed object by the passed template. + * @param obj The object which shall be validated. + * @param template The template which defines the allowed values and types. + * @param writeErrors True if errors shall be logged to the console. + * @param diffObj If a object is passed then only valid differences to this object will be returned. + * @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. + */ + _validate: function (obj, template, writeErrors, diffObj) { + var validatedOptions = {}; + var validatedOptionsPrepared = {}; + var objectCopy = FRAMEWORK.extend(true, {}, obj); + var inArray = FRAMEWORK.inArray; + var isEmptyObj = FRAMEWORK.isEmptyObject; + var checkObjectProps = function (data, template, diffData, validatedOptions, validatedOptionsPrepared, prevPropName) { + for (var prop in template) { + if (template[LEXICON.hOP](prop) && data[LEXICON.hOP](prop)) { + var isValid = false; + var isDiff = false; + var templateValue = template[prop]; + var templateValueType = type(templateValue); + var templateIsComplex = templateValueType == TYPES.o; + var templateTypes = type(templateValue) != TYPES.a ? [templateValue] : templateValue; + var dataDiffValue = diffData[prop]; + var dataValue = data[prop]; + var dataValueType = type(dataValue); + var propPrefix = prevPropName ? prevPropName + '.' : ''; + var error = "The option \"" + propPrefix + prop + "\" wasn't set, because"; + var errorPossibleTypes = []; + var errorRestrictedStrings = []; + var restrictedStringValuesSplit; + var restrictedStringValuesPossibilitiesSplit; + var isRestrictedValue; + var mainPossibility; + var currType; + var i; + var v; + var j; + + dataDiffValue = dataDiffValue === undefined ? {} : dataDiffValue; + + //if the template has a object as value, it means that the options are complex (verschachtelt) + if (templateIsComplex && dataValueType == TYPES.o) { + validatedOptions[prop] = {}; + validatedOptionsPrepared[prop] = {}; + checkObjectProps(dataValue, templateValue, dataDiffValue, validatedOptions[prop], validatedOptionsPrepared[prop], propPrefix + prop); + FRAMEWORK.each([data, validatedOptions, validatedOptionsPrepared], function (index, value) { + if (isEmptyObj(value[prop])) { + delete value[prop]; + } + }); + } + else if (!templateIsComplex) { + for (i = 0; i < templateTypes[LEXICON.l]; i++) { + currType = templateTypes[i]; + templateValueType = type(currType); + //if currtype is string and starts with restrictedStringPrefix and end with restrictedStringSuffix + isRestrictedValue = templateValueType == TYPES.s && inArray(currType, possibleTemplateTypes) === -1; + if (isRestrictedValue) { + errorPossibleTypes.push(TYPES.s); + + //split it into a array which contains all possible values for example: ["y:yes", "n:no", "m:maybe"] + restrictedStringValuesSplit = currType.split(restrictedStringsSplit); + errorRestrictedStrings = errorRestrictedStrings.concat(restrictedStringValuesSplit); + for (v = 0; v < restrictedStringValuesSplit[LEXICON.l]; v++) { + //split the possible values into their possibiliteis for example: ["y", "yes"] -> the first is always the mainPossibility + restrictedStringValuesPossibilitiesSplit = restrictedStringValuesSplit[v].split(restrictedStringsPossibilitiesSplit); + mainPossibility = restrictedStringValuesPossibilitiesSplit[0]; + for (j = 0; j < restrictedStringValuesPossibilitiesSplit[LEXICON.l]; j++) { + //if any possibility matches with the dataValue, its valid + if (dataValue === restrictedStringValuesPossibilitiesSplit[j]) { + isValid = true; + break; + } + } + if (isValid) + break; + } + } + else { + errorPossibleTypes.push(currType); + + if (dataValueType === currType) { + isValid = true; + break; + } + } + } + + if (isValid) { + isDiff = dataValue !== dataDiffValue; + + if (isDiff) + validatedOptions[prop] = dataValue; + + if (isRestrictedValue ? inArray(dataDiffValue, restrictedStringValuesPossibilitiesSplit) < 0 : isDiff) + validatedOptionsPrepared[prop] = isRestrictedValue ? mainPossibility : dataValue; + } + else if (writeErrors) { + console.warn(error + " it doesn't accept the type [ " + dataValueType.toUpperCase() + " ] with the value of \"" + dataValue + "\".\r\n" + + "Accepted types are: [ " + errorPossibleTypes.join(', ').toUpperCase() + " ]." + + (errorRestrictedStrings[length] > 0 ? "\r\nValid strings are: [ " + errorRestrictedStrings.join(', ').split(restrictedStringsPossibilitiesSplit).join(', ') + " ]." : '')); + } + delete data[prop]; + } + } + } + }; + checkObjectProps(objectCopy, template, diffObj || {}, validatedOptions, validatedOptionsPrepared); + + //add values which aren't specified in the template to the finished validated object to prevent them from being discarded + /* + if(keepForeignProps) { + FRAMEWORK.extend(true, validatedOptions, objectCopy); + FRAMEWORK.extend(true, validatedOptionsPrepared, objectCopy); + } + */ + + if (!isEmptyObj(objectCopy) && writeErrors) + console.warn('The following options are discarded due to invalidity:\r\n' + window.JSON.stringify(objectCopy, null, 2)); + + return { + _default: validatedOptions, + _prepared: validatedOptionsPrepared + }; + } + } + }()); + + /** + * Initializes the object which contains global information about the plugin and each instance of it. + */ + function initOverlayScrollbarsStatics() { + if (!_pluginsGlobals) + _pluginsGlobals = new OverlayScrollbarsGlobals(_pluginsOptions._defaults); + if (!_pluginsAutoUpdateLoop) + _pluginsAutoUpdateLoop = new OverlayScrollbarsAutoUpdateLoop(_pluginsGlobals); + } + + /** + * 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. + * @param defaultOptions + * @constructor + */ + function OverlayScrollbarsGlobals(defaultOptions) { + var _base = this; + var strOverflow = 'overflow'; + var strHidden = 'hidden'; + var strScroll = 'scroll'; + var bodyElement = FRAMEWORK('body'); + var scrollbarDummyElement = FRAMEWORK('
'); + var scrollbarDummyElement0 = scrollbarDummyElement[0]; + var dummyContainerChild = FRAMEWORK(scrollbarDummyElement.children('div').eq(0)); + + bodyElement.append(scrollbarDummyElement); + scrollbarDummyElement.hide().show(); //fix IE8 bug (incorrect measuring) + + var nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement0); + var nativeScrollbarIsOverlaid = { + x: nativeScrollbarSize.x === 0, + y: nativeScrollbarSize.y === 0 + }; + var msie = (function () { + var ua = window.navigator.userAgent; + var strIndexOf = 'indexOf'; + var strSubString = 'substring'; + var msie = ua[strIndexOf]('MSIE '); + var trident = ua[strIndexOf]('Trident/'); + var edge = ua[strIndexOf]('Edge/'); + var rv = ua[strIndexOf]('rv:'); + var result; + var parseIntFunc = parseInt; + + // IE 10 or older => return version number + if (msie > 0) + result = parseIntFunc(ua[strSubString](msie + 5, ua[strIndexOf]('.', msie)), 10); + + // IE 11 => return version number + else if (trident > 0) + result = parseIntFunc(ua[strSubString](rv + 3, ua[strIndexOf]('.', rv)), 10); + + // Edge (IE 12+) => return version number + else if (edge > 0) + result = parseIntFunc(ua[strSubString](edge + 5, ua[strIndexOf]('.', edge)), 10); + + // other browser + return result; + })(); + + FRAMEWORK.extend(_base, { + defaultOptions: defaultOptions, + msie: msie, + autoUpdateLoop: false, + autoUpdateRecommended: !COMPATIBILITY.mO(), + nativeScrollbarSize: nativeScrollbarSize, + nativeScrollbarIsOverlaid: nativeScrollbarIsOverlaid, + nativeScrollbarStyling: (function () { + var result = false; + scrollbarDummyElement.addClass('os-viewport-native-scrollbars-invisible'); + try { + result = (scrollbarDummyElement.css('scrollbar-width') === 'none' && (msie > 9 || !msie)) || window.getComputedStyle(scrollbarDummyElement0, '::-webkit-scrollbar').getPropertyValue('display') === 'none'; + } catch (ex) { } + + //fix opera bug: scrollbar styles will only appear if overflow value is scroll or auto during the activation of the style. + //and set overflow to scroll + //scrollbarDummyElement.css(strOverflow, strHidden).hide().css(strOverflow, strScroll).show(); + //return (scrollbarDummyElement0[LEXICON.oH] - scrollbarDummyElement0[LEXICON.cH]) === 0 && (scrollbarDummyElement0[LEXICON.oW] - scrollbarDummyElement0[LEXICON.cW]) === 0; + + return result; + })(), + overlayScrollbarDummySize: { x: 30, y: 30 }, + cssCalc: (function () { + var dummyStyle = document.createElement('div')[LEXICON.s]; + var strCalc = 'calc'; + var i = -1; + var prop; + + for (; i < VENDORS._cssPrefixes[LEXICON.l]; i++) { + prop = i < 0 ? strCalc : VENDORS._cssPrefixes[i] + strCalc; + dummyStyle.cssText = 'width:' + prop + '(1px);'; + if (dummyStyle[LEXICON.l]) + return prop; + } + return null; + })(), + restrictedMeasuring: (function () { + //https://bugzilla.mozilla.org/show_bug.cgi?id=1439305 + //since 1.11.0 always false -> fixed via CSS (hopefully) + scrollbarDummyElement.css(strOverflow, strHidden); + var scrollSize = { + w: scrollbarDummyElement0[LEXICON.sW], + h: scrollbarDummyElement0[LEXICON.sH] + }; + scrollbarDummyElement.css(strOverflow, 'visible'); + var scrollSize2 = { + w: scrollbarDummyElement0[LEXICON.sW], + h: scrollbarDummyElement0[LEXICON.sH] + }; + return (scrollSize.w - scrollSize2.w) !== 0 || (scrollSize.h - scrollSize2.h) !== 0; + })(), + rtlScrollBehavior: (function () { + scrollbarDummyElement.css({ 'overflow-y': strHidden, 'overflow-x': strScroll, 'direction': 'rtl' }).scrollLeft(0); + var dummyContainerOffset = scrollbarDummyElement.offset(); + var dummyContainerChildOffset = dummyContainerChild.offset(); + //https://github.com/KingSora/OverlayScrollbars/issues/187 + scrollbarDummyElement.scrollLeft(-999); + var dummyContainerChildOffsetAfterScroll = dummyContainerChild.offset(); + return { + //origin direction = determines if the zero scroll position is on the left or right side + //'i' means 'invert' (i === true means that the axis must be inverted to be correct) + //true = on the left side + //false = on the right side + i: dummyContainerOffset.left === dummyContainerChildOffset.left, + //negative = determines if the maximum scroll is positive or negative + //'n' means 'negate' (n === true means that the axis must be negated to be correct) + //true = negative + //false = positive + n: dummyContainerChildOffset.left !== dummyContainerChildOffsetAfterScroll.left + }; + })(), + supportTransform: VENDORS._cssProperty('transform') !== undefined, + supportTransition: VENDORS._cssProperty('transition') !== undefined, + supportPassiveEvents: (function () { + var supportsPassive = false; + try { + window.addEventListener('test', null, Object.defineProperty({}, 'passive', { + get: function () { + supportsPassive = true; + } + })); + } catch (e) { } + return supportsPassive; + })(), + supportResizeObserver: !!COMPATIBILITY.rO(), + supportMutationObserver: !!COMPATIBILITY.mO() + }); + + scrollbarDummyElement.removeAttr(LEXICON.s).remove(); + + //Catch zoom event: + (function () { + if (nativeScrollbarIsOverlaid.x && nativeScrollbarIsOverlaid.y) + return; + + var abs = MATH.abs; + var windowWidth = COMPATIBILITY.wW(); + var windowHeight = COMPATIBILITY.wH(); + var windowDpr = getWindowDPR(); + var onResize = function () { + if (INSTANCES().length > 0) { + var newW = COMPATIBILITY.wW(); + var newH = COMPATIBILITY.wH(); + var deltaW = newW - windowWidth; + var deltaH = newH - windowHeight; + + if (deltaW === 0 && deltaH === 0) + return; + + var deltaWRatio = MATH.round(newW / (windowWidth / 100.0)); + var deltaHRatio = MATH.round(newH / (windowHeight / 100.0)); + var absDeltaW = abs(deltaW); + var absDeltaH = abs(deltaH); + var absDeltaWRatio = abs(deltaWRatio); + var absDeltaHRatio = abs(deltaHRatio); + var newDPR = getWindowDPR(); + + var deltaIsBigger = absDeltaW > 2 && absDeltaH > 2; + var difference = !differenceIsBiggerThanOne(absDeltaWRatio, absDeltaHRatio); + var dprChanged = newDPR !== windowDpr && windowDpr > 0; + var isZoom = deltaIsBigger && difference && dprChanged; + var oldScrollbarSize = _base.nativeScrollbarSize; + var newScrollbarSize; + + if (isZoom) { + bodyElement.append(scrollbarDummyElement); + newScrollbarSize = _base.nativeScrollbarSize = calcNativeScrollbarSize(scrollbarDummyElement[0]); + scrollbarDummyElement.remove(); + if (oldScrollbarSize.x !== newScrollbarSize.x || oldScrollbarSize.y !== newScrollbarSize.y) { + FRAMEWORK.each(INSTANCES(), function () { + if (INSTANCES(this)) + INSTANCES(this).update('zoom'); + }); + } + } + + windowWidth = newW; + windowHeight = newH; + windowDpr = newDPR; + } + }; + + function differenceIsBiggerThanOne(valOne, valTwo) { + var absValOne = abs(valOne); + var absValTwo = abs(valTwo); + return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo); + } + + function getWindowDPR() { + var dDPI = window.screen.deviceXDPI || 0; + var sDPI = window.screen.logicalXDPI || 1; + return window.devicePixelRatio || (dDPI / sDPI); + } + + FRAMEWORK(window).on('resize', onResize); + })(); + + function calcNativeScrollbarSize(measureElement) { + return { + x: measureElement[LEXICON.oH] - measureElement[LEXICON.cH], + y: measureElement[LEXICON.oW] - measureElement[LEXICON.cW] + }; + } + } + + /** + * 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. + * @constructor + */ + function OverlayScrollbarsAutoUpdateLoop(globals) { + var _base = this; + var _inArray = FRAMEWORK.inArray; + var _getNow = COMPATIBILITY.now; + var _strAutoUpdate = 'autoUpdate'; + var _strAutoUpdateInterval = _strAutoUpdate + 'Interval'; + var _strLength = LEXICON.l; + var _loopingInstances = []; + var _loopingInstancesIntervalCache = []; + var _loopIsActive = false; + var _loopIntervalDefault = 33; + var _loopInterval = _loopIntervalDefault; + var _loopTimeOld = _getNow(); + var _loopID; + + + /** + * The auto update loop which will run every 50 milliseconds or less if the update interval of a instance is lower than 50 milliseconds. + */ + var loop = function () { + if (_loopingInstances[_strLength] > 0 && _loopIsActive) { + _loopID = COMPATIBILITY.rAF()(function () { + loop(); + }); + var timeNew = _getNow(); + var timeDelta = timeNew - _loopTimeOld; + var lowestInterval; + var instance; + var instanceOptions; + var instanceAutoUpdateAllowed; + var instanceAutoUpdateInterval; + var now; + + if (timeDelta > _loopInterval) { + _loopTimeOld = timeNew - (timeDelta % _loopInterval); + lowestInterval = _loopIntervalDefault; + for (var i = 0; i < _loopingInstances[_strLength]; i++) { + instance = _loopingInstances[i]; + if (instance !== undefined) { + instanceOptions = instance.options(); + instanceAutoUpdateAllowed = instanceOptions[_strAutoUpdate]; + instanceAutoUpdateInterval = MATH.max(1, instanceOptions[_strAutoUpdateInterval]); + now = _getNow(); + + if ((instanceAutoUpdateAllowed === true || instanceAutoUpdateAllowed === null) && (now - _loopingInstancesIntervalCache[i]) > instanceAutoUpdateInterval) { + instance.update('auto'); + _loopingInstancesIntervalCache[i] = new Date(now += instanceAutoUpdateInterval); + } + + lowestInterval = MATH.max(1, MATH.min(lowestInterval, instanceAutoUpdateInterval)); + } + } + _loopInterval = lowestInterval; + } + } else { + _loopInterval = _loopIntervalDefault; + } + }; + + /** + * Add OverlayScrollbars instance to the auto update loop. Only successful if the instance isn't already added. + * @param instance The instance which shall be updated in a loop automatically. + */ + _base.add = function (instance) { + if (_inArray(instance, _loopingInstances) === -1) { + _loopingInstances.push(instance); + _loopingInstancesIntervalCache.push(_getNow()); + if (_loopingInstances[_strLength] > 0 && !_loopIsActive) { + _loopIsActive = true; + globals.autoUpdateLoop = _loopIsActive; + loop(); + } + } + }; + + /** + * Remove OverlayScrollbars instance from the auto update loop. Only successful if the instance was added before. + * @param instance The instance which shall be updated in a loop automatically. + */ + _base.remove = function (instance) { + var index = _inArray(instance, _loopingInstances); + if (index > -1) { + //remove from loopingInstances list + _loopingInstancesIntervalCache.splice(index, 1); + _loopingInstances.splice(index, 1); + + //correct update loop behavior + if (_loopingInstances[_strLength] === 0 && _loopIsActive) { + _loopIsActive = false; + globals.autoUpdateLoop = _loopIsActive; + if (_loopID !== undefined) { + COMPATIBILITY.cAF()(_loopID); + _loopID = -1; + } + } + } + }; + } + + /** + * A object which manages the scrollbars visibility of the target element. + * @param pluginTargetElement The element from which the scrollbars shall be hidden. + * @param options The custom options. + * @param extensions The custom extensions. + * @param globals + * @param autoUpdateLoop + * @returns {*} + * @constructor + */ + function OverlayScrollbarsInstance(pluginTargetElement, options, extensions, globals, autoUpdateLoop) { + //shortcuts + var type = COMPATIBILITY.type; + var inArray = FRAMEWORK.inArray; + var each = FRAMEWORK.each; + + //make correct instanceof + var _base = new _plugin(); + var _frameworkProto = FRAMEWORK[LEXICON.p]; + + //if passed element is no HTML element: skip and return + if (!isHTMLElement(pluginTargetElement)) + return; + + //if passed element is already initialized: set passed options if there are any and return its instance + if (INSTANCES(pluginTargetElement)) { + var inst = INSTANCES(pluginTargetElement); + inst.options(options); + return inst; + } + + //globals: + var _nativeScrollbarIsOverlaid; + var _overlayScrollbarDummySize; + var _rtlScrollBehavior; + var _autoUpdateRecommended; + var _msieVersion; + var _nativeScrollbarStyling; + var _cssCalc; + var _nativeScrollbarSize; + var _supportTransition; + var _supportTransform; + var _supportPassiveEvents; + var _supportResizeObserver; + var _supportMutationObserver; + var _restrictedMeasuring; + + //general readonly: + var _initialized; + var _destroyed; + var _isTextarea; + var _isBody; + var _documentMixed; + var _domExists; + + //general: + var _isBorderBox; + var _sizeAutoObserverAdded; + var _paddingX; + var _paddingY; + var _borderX; + var _borderY; + var _marginX; + var _marginY; + var _isRTL; + var _sleeping; + var _contentBorderSize = {}; + var _scrollHorizontalInfo = {}; + var _scrollVerticalInfo = {}; + var _viewportSize = {}; + var _nativeScrollbarMinSize = {}; + + //naming: + var _strMinusHidden = '-hidden'; + var _strMarginMinus = 'margin-'; + var _strPaddingMinus = 'padding-'; + var _strBorderMinus = 'border-'; + var _strTop = 'top'; + var _strRight = 'right'; + var _strBottom = 'bottom'; + var _strLeft = 'left'; + var _strMinMinus = 'min-'; + var _strMaxMinus = 'max-'; + var _strWidth = 'width'; + var _strHeight = 'height'; + var _strFloat = 'float'; + var _strEmpty = ''; + var _strAuto = 'auto'; + var _strSync = 'sync'; + var _strScroll = 'scroll'; + var _strHundredPercent = '100%'; + var _strX = 'x'; + var _strY = 'y'; + var _strDot = '.'; + var _strSpace = ' '; + var _strScrollbar = 'scrollbar'; + var _strMinusHorizontal = '-horizontal'; + var _strMinusVertical = '-vertical'; + var _strScrollLeft = _strScroll + 'Left'; + var _strScrollTop = _strScroll + 'Top'; + var _strMouseTouchDownEvent = 'mousedown touchstart'; + var _strMouseTouchUpEvent = 'mouseup touchend touchcancel'; + var _strMouseTouchMoveEvent = 'mousemove touchmove'; + var _strMouseTouchEnter = 'mouseenter'; + var _strMouseTouchLeave = 'mouseleave'; + var _strKeyDownEvent = 'keydown'; + var _strKeyUpEvent = 'keyup'; + var _strSelectStartEvent = 'selectstart'; + var _strTransitionEndEvent = 'transitionend webkitTransitionEnd oTransitionEnd'; + var _strResizeObserverProperty = '__overlayScrollbarsRO__'; + + //class names: + var _cassNamesPrefix = 'os-'; + var _classNameHTMLElement = _cassNamesPrefix + 'html'; + var _classNameHostElement = _cassNamesPrefix + 'host'; + var _classNameHostTextareaElement = _classNameHostElement + '-textarea'; + var _classNameHostScrollbarHorizontalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusHorizontal + _strMinusHidden; + var _classNameHostScrollbarVerticalHidden = _classNameHostElement + '-' + _strScrollbar + _strMinusVertical + _strMinusHidden; + var _classNameHostTransition = _classNameHostElement + '-transition'; + var _classNameHostRTL = _classNameHostElement + '-rtl'; + var _classNameHostResizeDisabled = _classNameHostElement + '-resize-disabled'; + var _classNameHostScrolling = _classNameHostElement + '-scrolling'; + var _classNameHostOverflow = _classNameHostElement + '-overflow'; + var _classNameHostOverflowX = _classNameHostOverflow + '-x'; + var _classNameHostOverflowY = _classNameHostOverflow + '-y'; + var _classNameTextareaElement = _cassNamesPrefix + 'textarea'; + var _classNameTextareaCoverElement = _classNameTextareaElement + '-cover'; + var _classNamePaddingElement = _cassNamesPrefix + 'padding'; + var _classNameViewportElement = _cassNamesPrefix + 'viewport'; + var _classNameViewportNativeScrollbarsInvisible = _classNameViewportElement + '-native-scrollbars-invisible'; + var _classNameViewportNativeScrollbarsOverlaid = _classNameViewportElement + '-native-scrollbars-overlaid'; + var _classNameContentElement = _cassNamesPrefix + 'content'; + var _classNameContentArrangeElement = _cassNamesPrefix + 'content-arrange'; + var _classNameContentGlueElement = _cassNamesPrefix + 'content-glue'; + var _classNameSizeAutoObserverElement = _cassNamesPrefix + 'size-auto-observer'; + var _classNameResizeObserverElement = _cassNamesPrefix + 'resize-observer'; + var _classNameResizeObserverItemElement = _cassNamesPrefix + 'resize-observer-item'; + var _classNameResizeObserverItemFinalElement = _classNameResizeObserverItemElement + '-final'; + var _classNameTextInherit = _cassNamesPrefix + 'text-inherit'; + var _classNameScrollbar = _cassNamesPrefix + _strScrollbar; + var _classNameScrollbarTrack = _classNameScrollbar + '-track'; + var _classNameScrollbarTrackOff = _classNameScrollbarTrack + '-off'; + var _classNameScrollbarHandle = _classNameScrollbar + '-handle'; + var _classNameScrollbarHandleOff = _classNameScrollbarHandle + '-off'; + var _classNameScrollbarUnusable = _classNameScrollbar + '-unusable'; + var _classNameScrollbarAutoHidden = _classNameScrollbar + '-' + _strAuto + _strMinusHidden; + var _classNameScrollbarCorner = _classNameScrollbar + '-corner'; + var _classNameScrollbarCornerResize = _classNameScrollbarCorner + '-resize'; + var _classNameScrollbarCornerResizeB = _classNameScrollbarCornerResize + '-both'; + var _classNameScrollbarCornerResizeH = _classNameScrollbarCornerResize + _strMinusHorizontal; + var _classNameScrollbarCornerResizeV = _classNameScrollbarCornerResize + _strMinusVertical; + var _classNameScrollbarHorizontal = _classNameScrollbar + _strMinusHorizontal; + var _classNameScrollbarVertical = _classNameScrollbar + _strMinusVertical; + var _classNameDragging = _cassNamesPrefix + 'dragging'; + var _classNameThemeNone = _cassNamesPrefix + 'theme-none'; + var _classNamesDynamicDestroy = [ + _classNameViewportNativeScrollbarsInvisible, + _classNameViewportNativeScrollbarsOverlaid, + _classNameScrollbarTrackOff, + _classNameScrollbarHandleOff, + _classNameScrollbarUnusable, + _classNameScrollbarAutoHidden, + _classNameScrollbarCornerResize, + _classNameScrollbarCornerResizeB, + _classNameScrollbarCornerResizeH, + _classNameScrollbarCornerResizeV, + _classNameDragging].join(_strSpace); + + //callbacks: + var _callbacksInitQeueue = []; + + //attrs viewport shall inherit from target + var _viewportAttrsFromTarget = [LEXICON.ti]; + + //options: + var _defaultOptions; + var _currentOptions; + var _currentPreparedOptions; + + //extensions: + var _extensions = {}; + var _extensionsPrivateMethods = 'added removed on contract'; + + //update + var _lastUpdateTime; + var _swallowedUpdateHints = {}; + var _swallowedUpdateTimeout; + var _swallowUpdateLag = 42; + var _imgs = []; + + //DOM elements: + var _windowElement; + var _documentElement; + var _htmlElement; + var _bodyElement; + var _targetElement; //the target element of this OverlayScrollbars object + var _hostElement; //the host element of this OverlayScrollbars object -> may be the same as targetElement + var _sizeAutoObserverElement; //observes size auto changes + var _sizeObserverElement; //observes size and padding changes + var _paddingElement; //manages the padding + var _viewportElement; //is the viewport of our scrollbar model + var _contentElement; //the element which holds the content + var _contentArrangeElement; //is needed for correct sizing of the content element (only if native scrollbars are overlays) + var _contentGlueElement; //has always the size of the content element + var _textareaCoverElement; //only applied if target is a textarea element. Used for correct size calculation and for prevention of uncontrolled scrolling + var _scrollbarCornerElement; + var _scrollbarHorizontalElement; + var _scrollbarHorizontalTrackElement; + var _scrollbarHorizontalHandleElement; + var _scrollbarVerticalElement; + var _scrollbarVerticalTrackElement; + var _scrollbarVerticalHandleElement; + var _windowElementNative; + var _documentElementNative; + var _targetElementNative; + var _hostElementNative; + var _sizeAutoObserverElementNative; + var _sizeObserverElementNative; + var _paddingElementNative; + var _viewportElementNative; + var _contentElementNative; + + //Cache: + var _hostSizeCache; + var _contentScrollSizeCache; + var _arrangeContentSizeCache; + var _hasOverflowCache; + var _hideOverflowCache; + var _widthAutoCache; + var _heightAutoCache; + var _cssMaxValueCache; + var _cssBoxSizingCache; + var _cssPaddingCache; + var _cssBorderCache; + var _cssMarginCache; + var _cssDirectionCache; + var _cssDirectionDetectedCache; + var _paddingAbsoluteCache; + var _clipAlwaysCache; + var _contentGlueSizeCache; + var _overflowBehaviorCache; + var _overflowAmountCache; + var _ignoreOverlayScrollbarHidingCache; + var _autoUpdateCache; + var _sizeAutoCapableCache; + var _contentElementScrollSizeChangeDetectedCache; + var _hostElementSizeChangeDetectedCache; + var _scrollbarsVisibilityCache; + var _scrollbarsAutoHideCache; + var _scrollbarsClickScrollingCache; + var _scrollbarsDragScrollingCache; + var _resizeCache; + var _normalizeRTLCache; + var _classNameCache; + var _oldClassName; + var _textareaAutoWrappingCache; + var _textareaInfoCache; + var _textareaSizeCache; + var _textareaDynHeightCache; + var _textareaDynWidthCache; + var _bodyMinSizeCache; + var _displayIsHiddenCache; + var _updateAutoCache = {}; + + //MutationObserver: + var _mutationObserverHost; + var _mutationObserverContent; + var _mutationObserverHostCallback; + var _mutationObserverContentCallback; + var _mutationObserversConnected; + var _mutationObserverAttrsTextarea = ['wrap', 'cols', 'rows']; + var _mutationObserverAttrsHost = [LEXICON.i, LEXICON.c, LEXICON.s, 'open'].concat(_viewportAttrsFromTarget); + + //events: + var _destroyEvents = []; + + //textarea: + var _textareaHasFocus; + + //scrollbars: + var _scrollbarsAutoHideTimeoutId; + var _scrollbarsAutoHideMoveTimeoutId; + var _scrollbarsAutoHideDelay; + var _scrollbarsAutoHideNever; + var _scrollbarsAutoHideScroll; + var _scrollbarsAutoHideMove; + var _scrollbarsAutoHideLeave; + var _scrollbarsHandleHovered; + var _scrollbarsHandlesDefineScrollPos; + + //resize + var _resizeNone; + var _resizeBoth; + var _resizeHorizontal; + var _resizeVertical; + + + //==== Event Listener ====// + + /** + * Adds or removes a event listener from the given element. + * @param element The element to which the event listener shall be applied or removed. + * @param eventNames The name(s) of the events. + * @param listener The method which shall be called. + * @param remove True if the handler shall be removed, false or undefined if the handler shall be added. + */ + function setupResponsiveEventListener(element, eventNames, listener, remove, passive) { + var collected = type(eventNames) == TYPES.a && type(listener) == TYPES.a; + var method = remove ? 'removeEventListener' : 'addEventListener'; + var onOff = remove ? 'off' : 'on'; + var events = collected ? false : eventNames.split(_strSpace) + var i = 0; + + if (collected) { + for (; i < eventNames[LEXICON.l]; i++) + setupResponsiveEventListener(element, eventNames[i], listener[i], remove); + } + else { + for (; i < events[LEXICON.l]; i++) { + if (_supportPassiveEvents) + element[0][method](events[i], listener, { passive: passive || false }); + else + element[onOff](events[i], listener); + } + } + } + + + function addDestroyEventListener(element, eventNames, listener, passive) { + setupResponsiveEventListener(element, eventNames, listener, false, passive); + _destroyEvents.push(COMPATIBILITY.bind(setupResponsiveEventListener, 0, element, eventNames, listener, true, passive)); + } + + //==== Resize Observer ====// + + /** + * Adds or removes a resize observer from the given element. + * @param targetElement The element to which the resize observer shall be added or removed. + * @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. + */ + function setupResizeObserver(targetElement, onElementResizedCallback) { + if (targetElement) { + var resizeObserver = COMPATIBILITY.rO(); + var strAnimationStartEvent = 'animationstart mozAnimationStart webkitAnimationStart MSAnimationStart'; + var strChildNodes = 'childNodes'; + var constScroll = 3333333; + var callback = function () { + targetElement[_strScrollTop](constScroll)[_strScrollLeft](_isRTL ? _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll : constScroll); + onElementResizedCallback(); + }; + //add resize observer: + if (onElementResizedCallback) { + if (_supportResizeObserver) { + var element = targetElement.addClass('observed').append(generateDiv(_classNameResizeObserverElement)).contents()[0]; + var observer = element[_strResizeObserverProperty] = new resizeObserver(callback); + observer.observe(element); + } + else { + if (_msieVersion > 9 || !_autoUpdateRecommended) { + targetElement.prepend( + generateDiv(_classNameResizeObserverElement, + generateDiv({ c: _classNameResizeObserverItemElement, dir: 'ltr' }, + generateDiv(_classNameResizeObserverItemElement, + generateDiv(_classNameResizeObserverItemFinalElement) + ) + + generateDiv(_classNameResizeObserverItemElement, + generateDiv({ c: _classNameResizeObserverItemFinalElement, style: 'width: 200%; height: 200%' }) + ) + ) + ) + ); + + var observerElement = targetElement[0][strChildNodes][0][strChildNodes][0]; + var shrinkElement = FRAMEWORK(observerElement[strChildNodes][1]); + var expandElement = FRAMEWORK(observerElement[strChildNodes][0]); + var expandElementChild = FRAMEWORK(expandElement[0][strChildNodes][0]); + var widthCache = observerElement[LEXICON.oW]; + var heightCache = observerElement[LEXICON.oH]; + var isDirty; + var rAFId; + var currWidth; + var currHeight; + var factor = 2; + var nativeScrollbarSize = globals.nativeScrollbarSize; //care don't make changes to this object!!! + var reset = function () { + /* + var sizeResetWidth = observerElement[LEXICON.oW] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; + var sizeResetHeight = observerElement[LEXICON.oH] + nativeScrollbarSize.x * factor + nativeScrollbarSize.y * factor + _overlayScrollbarDummySize.x + _overlayScrollbarDummySize.y; + var expandChildCSS = {}; + expandChildCSS[_strWidth] = sizeResetWidth; + expandChildCSS[_strHeight] = sizeResetHeight; + expandElementChild.css(expandChildCSS); + + + expandElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); + shrinkElement[_strScrollLeft](sizeResetWidth)[_strScrollTop](sizeResetHeight); + */ + expandElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); + shrinkElement[_strScrollLeft](constScroll)[_strScrollTop](constScroll); + }; + var onResized = function () { + rAFId = 0; + if (!isDirty) + return; + + widthCache = currWidth; + heightCache = currHeight; + callback(); + }; + var onScroll = function (event) { + currWidth = observerElement[LEXICON.oW]; + currHeight = observerElement[LEXICON.oH]; + isDirty = currWidth != widthCache || currHeight != heightCache; + + if (event && isDirty && !rAFId) { + COMPATIBILITY.cAF()(rAFId); + rAFId = COMPATIBILITY.rAF()(onResized); + } + else if (!event) + onResized(); + + reset(); + if (event) { + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + return false; + }; + var expandChildCSS = {}; + var observerElementCSS = {}; + + setTopRightBottomLeft(observerElementCSS, _strEmpty, [ + -((nativeScrollbarSize.y + 1) * factor), + nativeScrollbarSize.x * -factor, + nativeScrollbarSize.y * -factor, + -((nativeScrollbarSize.x + 1) * factor) + ]); + + FRAMEWORK(observerElement).css(observerElementCSS); + expandElement.on(_strScroll, onScroll); + shrinkElement.on(_strScroll, onScroll); + targetElement.on(strAnimationStartEvent, function () { + onScroll(false); + }); + //lets assume that the divs will never be that large and a constant value is enough + expandChildCSS[_strWidth] = constScroll; + expandChildCSS[_strHeight] = constScroll; + expandElementChild.css(expandChildCSS); + + reset(); + } + else { + var attachEvent = _documentElementNative.attachEvent; + var isIE = _msieVersion !== undefined; + if (attachEvent) { + targetElement.prepend(generateDiv(_classNameResizeObserverElement)); + findFirst(targetElement, _strDot + _classNameResizeObserverElement)[0].attachEvent('onresize', callback); + } + else { + var obj = _documentElementNative.createElement(TYPES.o); + obj.setAttribute(LEXICON.ti, '-1'); + obj.setAttribute(LEXICON.c, _classNameResizeObserverElement); + obj.onload = function () { + var wnd = this.contentDocument.defaultView; + wnd.addEventListener('resize', callback); + wnd.document.documentElement.style.display = 'none'; + }; + obj.type = 'text/html'; + if (isIE) + targetElement.prepend(obj); + obj.data = 'about:blank'; + if (!isIE) + targetElement.prepend(obj); + targetElement.on(strAnimationStartEvent, callback); + } + } + } + + if (targetElement[0] === _sizeObserverElementNative) { + var directionChanged = function () { + var dir = _hostElement.css('direction'); + var css = {}; + var scrollLeftValue = 0; + var result = false; + if (dir !== _cssDirectionDetectedCache) { + if (dir === 'ltr') { + css[_strLeft] = 0; + css[_strRight] = _strAuto; + scrollLeftValue = constScroll; + } + else { + css[_strLeft] = _strAuto; + css[_strRight] = 0; + scrollLeftValue = _rtlScrollBehavior.n ? -constScroll : _rtlScrollBehavior.i ? 0 : constScroll; + } + //execution order is important for IE!!! + _sizeObserverElement.children().eq(0).css(css); + _sizeObserverElement[_strScrollLeft](scrollLeftValue)[_strScrollTop](constScroll); + _cssDirectionDetectedCache = dir; + result = true; + } + return result; + }; + directionChanged(); + addDestroyEventListener(targetElement, _strScroll, function (event) { + if (directionChanged()) + update(); + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + return false; + }); + } + } + //remove resize observer: + else { + if (_supportResizeObserver) { + var element = targetElement.contents()[0]; + var resizeObserverObj = element[_strResizeObserverProperty]; + if (resizeObserverObj) { + resizeObserverObj.disconnect(); + delete element[_strResizeObserverProperty]; + } + } + else { + remove(targetElement.children(_strDot + _classNameResizeObserverElement).eq(0)); + } + } + } + } + + /** + * Freezes or unfreezes the given resize observer. + * @param targetElement The element to which the target resize observer is applied. + * @param freeze True if the resize observer shall be frozen, false otherwise. + + function freezeResizeObserver(targetElement, freeze) { + if (targetElement !== undefined) { + if(freeze) { + if (_supportResizeObserver) { + var element = targetElement.contents()[0]; + element[_strResizeObserverProperty].unobserve(element); + } + else { + targetElement = targetElement.children(_strDot + _classNameResizeObserverElement).eq(0); + var w = targetElement.css(_strWidth); + var h = targetElement.css(_strHeight); + var css = {}; + css[_strWidth] = w; + css[_strHeight] = h; + targetElement.css(css); + } + } + else { + if (_supportResizeObserver) { + var element = targetElement.contents()[0]; + element[_strResizeObserverProperty].observe(element); + } + else { + var css = { }; + css[_strHeight] = _strEmpty; + css[_strWidth] = _strEmpty; + targetElement.children(_strDot + _classNameResizeObserverElement).eq(0).css(css); + } + } + } + } + */ + + + //==== Mutation Observers ====// + + /** + * Creates MutationObservers for the host and content Element if they are supported. + */ + function createMutationObservers() { + if (_supportMutationObserver) { + var mutationObserverContentLag = 11; + var mutationObserver = COMPATIBILITY.mO(); + var contentLastUpdate = COMPATIBILITY.now(); + var mutationTarget; + var mutationAttrName; + var contentTimeout; + var now; + var sizeAuto; + var action; + + _mutationObserverHostCallback = function (mutations) { + var doUpdate = false; + var mutation; + var mutatedAttrs = []; + + if (_initialized && !_sleeping) { + each(mutations, function () { + mutation = this; + mutationTarget = mutation.target; + mutationAttrName = mutation.attributeName; + + if(!doUpdate) { + if (mutationAttrName === LEXICON.c) + doUpdate = hostClassNamesChanged(mutation.oldValue, mutationTarget.className); + else if (mutationAttrName === LEXICON.s) + doUpdate = mutation.oldValue !== mutationTarget[LEXICON.s].cssText; + else + doUpdate = true; + } + + mutatedAttrs.push(mutationAttrName); + }); + + updateViewportAttrsFromTarget(mutatedAttrs); + + if (doUpdate) + _base.update(_strAuto); + } + return doUpdate; + }; + _mutationObserverContentCallback = function (mutations) { + var doUpdate = false; + var mutation; + + if (_initialized && !_sleeping) { + each(mutations, function () { + mutation = this; + doUpdate = isUnknownMutation(mutation); + return !doUpdate; + }); + + if (doUpdate) { + now = COMPATIBILITY.now(); + sizeAuto = (_heightAutoCache || _widthAutoCache); + action = function () { + if (!_destroyed) { + contentLastUpdate = now; + + //if cols, rows or wrap attr was changed + if (_isTextarea) + textareaUpdate(); + + if (sizeAuto) + update(); + else + _base.update(_strAuto); + } + }; + clearTimeout(contentTimeout); + if (mutationObserverContentLag <= 0 || now - contentLastUpdate > mutationObserverContentLag || !sizeAuto) + action(); + else + contentTimeout = setTimeout(action, mutationObserverContentLag); + } + } + return doUpdate; + } + + _mutationObserverHost = new mutationObserver(_mutationObserverHostCallback); + _mutationObserverContent = new mutationObserver(_mutationObserverContentCallback); + } + } + + /** + * Connects the MutationObservers if they are supported. + */ + function connectMutationObservers() { + if (_supportMutationObserver && !_mutationObserversConnected) { + _mutationObserverHost.observe(_hostElementNative, { + attributes: true, + attributeOldValue: true, + attributeFilter: _mutationObserverAttrsHost + }); + + _mutationObserverContent.observe(_isTextarea ? _targetElementNative : _contentElementNative, { + attributes: true, + attributeOldValue: true, + subtree: !_isTextarea, + childList: !_isTextarea, + characterData: !_isTextarea, + attributeFilter: _isTextarea ? _mutationObserverAttrsTextarea : _mutationObserverAttrsHost + }); + + _mutationObserversConnected = true; + } + } + + /** + * Disconnects the MutationObservers if they are supported. + */ + function disconnectMutationObservers() { + if (_supportMutationObserver && _mutationObserversConnected) { + _mutationObserverHost.disconnect(); + _mutationObserverContent.disconnect(); + + _mutationObserversConnected = false; + } + } + + + //==== Events of elements ====// + + /** + * This method gets called every time the host element gets resized. IMPORTANT: Padding changes are detected too!! + * It refreshes the hostResizedEventArgs and the hostSizeResizeCache. + * If there are any size changes, the update method gets called. + */ + function hostOnResized() { + if (!_sleeping) { + var changed; + var hostSize = { + w: _sizeObserverElementNative[LEXICON.sW], + h: _sizeObserverElementNative[LEXICON.sH] + }; + + changed = checkCache(hostSize, _hostElementSizeChangeDetectedCache); + _hostElementSizeChangeDetectedCache = hostSize; + if (changed) + update({ _hostSizeChanged: true }); + } + } + + /** + * The mouse enter event of the host element. This event is only needed for the autoHide feature. + */ + function hostOnMouseEnter() { + if (_scrollbarsAutoHideLeave) + refreshScrollbarsAutoHide(true); + } + + /** + * The mouse leave event of the host element. This event is only needed for the autoHide feature. + */ + function hostOnMouseLeave() { + if (_scrollbarsAutoHideLeave && !_bodyElement.hasClass(_classNameDragging)) + refreshScrollbarsAutoHide(false); + } + + /** + * The mouse move event of the host element. This event is only needed for the autoHide "move" feature. + */ + function hostOnMouseMove() { + if (_scrollbarsAutoHideMove) { + refreshScrollbarsAutoHide(true); + clearTimeout(_scrollbarsAutoHideMoveTimeoutId); + _scrollbarsAutoHideMoveTimeoutId = setTimeout(function () { + if (_scrollbarsAutoHideMove && !_destroyed) + refreshScrollbarsAutoHide(false); + }, 100); + } + } + + /** + * Prevents text from deselection if attached to the document element on the mousedown event of a DOM element. + * @param event The select start event. + */ + function documentOnSelectStart(event) { + COMPATIBILITY.prvD(event); + return false; + } + + /** + * A callback which will be called after a img element has downloaded its src asynchronous. + */ + function imgOnLoad() { + update({ _contentSizeChanged: true }); + } + + /** + * Adds or removes mouse & touch events of the host element. (for handling auto-hiding of the scrollbars) + * @param destroy Indicates whether the events shall be added or removed. + */ + function setupHostMouseTouchEvents(destroy) { + setupResponsiveEventListener(_hostElement, + _strMouseTouchMoveEvent, + hostOnMouseMove, + (_scrollbarsAutoHideMove ? destroy : true), true); + setupResponsiveEventListener(_hostElement, + [_strMouseTouchEnter, _strMouseTouchLeave], + [hostOnMouseEnter, hostOnMouseLeave], + (_scrollbarsAutoHideMove ? true : destroy), true); + + //if the plugin is initialized and the mouse is over the host element, make the scrollbars visible + if (!_initialized && !destroy) + _hostElement.one('mouseover', hostOnMouseEnter); + } + + + //==== Update Detection ====// + + /** + * Measures the min width and min height of the body element and refreshes the related cache. + * @returns {boolean} True if the min width or min height has changed, false otherwise. + */ + function bodyMinSizeChanged() { + var bodyMinSize = {}; + if (_isBody && _contentArrangeElement) { + bodyMinSize.w = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strWidth)); + bodyMinSize.h = parseToZeroOrNumber(_contentArrangeElement.css(_strMinMinus + _strHeight)); + bodyMinSize.c = checkCache(bodyMinSize, _bodyMinSizeCache); + bodyMinSize.f = true; //flag for "measured at least once" + } + _bodyMinSizeCache = bodyMinSize; + return !!bodyMinSize.c; + } + + /** + * Returns true if the class names really changed (new class without plugin host prefix) + * @param oldCassNames The old ClassName string. + * @param newClassNames The new ClassName string. + * @returns {boolean} True if the class names has really changed, false otherwise. + */ + function hostClassNamesChanged(oldCassNames, newClassNames) { + var currClasses = (newClassNames !== undefined && newClassNames !== null) ? newClassNames.split(_strSpace) : _strEmpty; + var oldClasses = (oldCassNames !== undefined && oldCassNames !== null) ? oldCassNames.split(_strSpace) : _strEmpty; + if (currClasses === _strEmpty && oldClasses === _strEmpty) + return false; + var diff = getArrayDifferences(oldClasses, currClasses); + var changed = false; + var oldClassNames = _oldClassName !== undefined && _oldClassName !== null ? _oldClassName.split(_strSpace) : [_strEmpty]; + var currClassNames = _classNameCache !== undefined && _classNameCache !== null ? _classNameCache.split(_strSpace) : [_strEmpty]; + + //remove none theme from diff list to prevent update + var idx = inArray(_classNameThemeNone, diff); + var curr; + var i; + var v; + var o; + var c; + + if (idx > -1) + diff.splice(idx, 1); + + for (i = 0; i < diff.length; i++) { + curr = diff[i]; + if (curr.indexOf(_classNameHostElement) !== 0) { + o = true; + c = true; + for (v = 0; v < oldClassNames.length; v++) { + if (curr === oldClassNames[v]) { + o = false; + break; + } + } + for (v = 0; v < currClassNames.length; v++) { + if (curr === currClassNames[v]) { + c = false; + break; + } + } + if (o && c) { + changed = true; + break; + } + } + + } + return changed; + } + + /** + * 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. + * @param mutation The mutation which shall be checked. + * @returns {boolean} True if the mutation is from a unknown element, false otherwise. + */ + function isUnknownMutation(mutation) { + var attributeName = mutation.attributeName; + var mutationTarget = mutation.target; + var mutationType = mutation.type; + var strClosest = 'closest'; + + if (mutationTarget === _contentElementNative) + return attributeName === null; + if (mutationType === 'attributes' && (attributeName === LEXICON.c || attributeName === LEXICON.s) && !_isTextarea) { + //ignore className changes by the plugin + if (attributeName === LEXICON.c && FRAMEWORK(mutationTarget).hasClass(_classNameHostElement)) + return hostClassNamesChanged(mutation.oldValue, mutationTarget.getAttribute(LEXICON.c)); + + //only do it of browser support it natively + if (typeof mutationTarget[strClosest] != TYPES.f) + return true; + if (mutationTarget[strClosest](_strDot + _classNameResizeObserverElement) !== null || + mutationTarget[strClosest](_strDot + _classNameScrollbar) !== null || + mutationTarget[strClosest](_strDot + _classNameScrollbarCorner) !== null) + return false; + } + return true; + } + + /** + * Returns true if the content size was changed since the last time this method was called. + * @returns {boolean} True if the content size was changed, false otherwise. + */ + function updateAutoContentSizeChanged() { + if (_sleeping) + return false; + + var contentMeasureElement = getContentMeasureElement(); + var textareaValueLength = _isTextarea && _widthAutoCache && !_textareaAutoWrappingCache ? _targetElement.val().length : 0; + var setCSS = !_mutationObserversConnected && _widthAutoCache && !_isTextarea; + var css = {}; + var float; + var bodyMinSizeC; + var changed; + var contentElementScrollSize; + + if (setCSS) { + float = _contentElement.css(_strFloat); + css[_strFloat] = _isRTL ? _strRight : _strLeft; + css[_strWidth] = _strAuto; + _contentElement.css(css); + } + contentElementScrollSize = { + w: contentMeasureElement[LEXICON.sW] + textareaValueLength, + h: contentMeasureElement[LEXICON.sH] + textareaValueLength + }; + if (setCSS) { + css[_strFloat] = float; + css[_strWidth] = _strHundredPercent; + _contentElement.css(css); + } + + bodyMinSizeC = bodyMinSizeChanged(); + changed = checkCache(contentElementScrollSize, _contentElementScrollSizeChangeDetectedCache); + + _contentElementScrollSizeChangeDetectedCache = contentElementScrollSize; + + return changed || bodyMinSizeC; + } + + /** + * Returns true when a attribute which the MutationObserver would observe has changed. + * @returns {boolean} True if one of the attributes which a MutationObserver would observe has changed, false or undefined otherwise. + */ + function meaningfulAttrsChanged() { + if (_sleeping || _mutationObserversConnected) + return; + + var elem; + var curr; + var cache; + var changedAttrs = []; + var checks = [ + { + _elem: _hostElement, + _attrs: _mutationObserverAttrsHost.concat(':visible') + }, + { + _elem: _isTextarea ? _targetElement : undefined, + _attrs: _mutationObserverAttrsTextarea + } + ]; + + each(checks, function (index, check) { + elem = check._elem; + if (elem) { + each(check._attrs, function (index, attr) { + curr = attr.charAt(0) === ':' ? elem.is(attr) : elem.attr(attr); + cache = _updateAutoCache[attr]; + + if(checkCache(curr, cache)) { + changedAttrs.push(attr); + } + + _updateAutoCache[attr] = curr; + }); + } + }); + + updateViewportAttrsFromTarget(changedAttrs); + + return changedAttrs[LEXICON.l] > 0; + } + + /** + * Checks is a CSS Property of a child element is affecting the scroll size of the content. + * @param propertyName The CSS property name. + * @returns {boolean} True if the property is affecting the content scroll size, false otherwise. + */ + function isSizeAffectingCSSProperty(propertyName) { + if (!_initialized) + return true; + var flexGrow = 'flex-grow'; + var flexShrink = 'flex-shrink'; + var flexBasis = 'flex-basis'; + var affectingPropsX = [ + _strWidth, + _strMinMinus + _strWidth, + _strMaxMinus + _strWidth, + _strMarginMinus + _strLeft, + _strMarginMinus + _strRight, + _strLeft, + _strRight, + 'font-weight', + 'word-spacing', + flexGrow, + flexShrink, + flexBasis + ]; + var affectingPropsXContentBox = [ + _strPaddingMinus + _strLeft, + _strPaddingMinus + _strRight, + _strBorderMinus + _strLeft + _strWidth, + _strBorderMinus + _strRight + _strWidth + ]; + var affectingPropsY = [ + _strHeight, + _strMinMinus + _strHeight, + _strMaxMinus + _strHeight, + _strMarginMinus + _strTop, + _strMarginMinus + _strBottom, + _strTop, + _strBottom, + 'line-height', + flexGrow, + flexShrink, + flexBasis + ]; + var affectingPropsYContentBox = [ + _strPaddingMinus + _strTop, + _strPaddingMinus + _strBottom, + _strBorderMinus + _strTop + _strWidth, + _strBorderMinus + _strBottom + _strWidth + ]; + var _strS = 's'; + var _strVS = 'v-s'; + var checkX = _overflowBehaviorCache.x === _strS || _overflowBehaviorCache.x === _strVS; + var checkY = _overflowBehaviorCache.y === _strS || _overflowBehaviorCache.y === _strVS; + var sizeIsAffected = false; + var checkPropertyName = function (arr, name) { + for (var i = 0; i < arr[LEXICON.l]; i++) { + if (arr[i] === name) + return true; + } + return false; + }; + + if (checkY) { + sizeIsAffected = checkPropertyName(affectingPropsY, propertyName); + if (!sizeIsAffected && !_isBorderBox) + sizeIsAffected = checkPropertyName(affectingPropsYContentBox, propertyName); + } + if (checkX && !sizeIsAffected) { + sizeIsAffected = checkPropertyName(affectingPropsX, propertyName); + if (!sizeIsAffected && !_isBorderBox) + sizeIsAffected = checkPropertyName(affectingPropsXContentBox, propertyName); + } + return sizeIsAffected; + } + + + //==== Update ====// + + /** + * Sets the attribute values of the viewport element to the values from the target element. + * The value of a attribute is only set if the attribute is whitelisted. + * @attrs attrs The array of attributes which shall be set or undefined if all whitelisted shall be set. + */ + function updateViewportAttrsFromTarget(attrs) { + attrs = attrs || _viewportAttrsFromTarget; + each(attrs, function (index, attr) { + if (COMPATIBILITY.inA(attr, _viewportAttrsFromTarget) > -1) { + var targetAttr = _targetElement.attr(attr); + if(type(targetAttr) == TYPES.s) { + _viewportElement.attr(attr, targetAttr); + } + else { + _viewportElement.removeAttr(attr); + } + } + }); + } + + /** + * Updates the variables and size of the textarea element, and manages the scroll on new line or new character. + */ + function textareaUpdate() { + if (!_sleeping) { + var wrapAttrOff = !_textareaAutoWrappingCache; + var minWidth = _viewportSize.w; + var minHeight = _viewportSize.h; + var css = {}; + var doMeasure = _widthAutoCache || wrapAttrOff; + var origWidth; + var width; + var origHeight; + var height; + + //reset min size + css[_strMinMinus + _strWidth] = _strEmpty; + css[_strMinMinus + _strHeight] = _strEmpty; + + //set width auto + css[_strWidth] = _strAuto; + _targetElement.css(css); + + //measure width + origWidth = _targetElementNative[LEXICON.oW]; + width = doMeasure ? MATH.max(origWidth, _targetElementNative[LEXICON.sW] - 1) : 1; + /*width += (_widthAutoCache ? _marginX + (!_isBorderBox ? wrapAttrOff ? 0 : _paddingX + _borderX : 0) : 0);*/ + + //set measured width + css[_strWidth] = _widthAutoCache ? _strAuto /*width*/ : _strHundredPercent; + css[_strMinMinus + _strWidth] = _strHundredPercent; + + //set height auto + css[_strHeight] = _strAuto; + _targetElement.css(css); + + //measure height + origHeight = _targetElementNative[LEXICON.oH]; + height = MATH.max(origHeight, _targetElementNative[LEXICON.sH] - 1); + + //append correct size values + css[_strWidth] = width; + css[_strHeight] = height; + _textareaCoverElement.css(css); + + //apply min width / min height to prevent textarea collapsing + css[_strMinMinus + _strWidth] = minWidth /*+ (!_isBorderBox && _widthAutoCache ? _paddingX + _borderX : 0)*/; + css[_strMinMinus + _strHeight] = minHeight /*+ (!_isBorderBox && _heightAutoCache ? _paddingY + _borderY : 0)*/; + _targetElement.css(css); + + return { + _originalWidth: origWidth, + _originalHeight: origHeight, + _dynamicWidth: width, + _dynamicHeight: height + }; + } + } + + /** + * Updates the plugin and DOM to the current options. + * This method should only be called if a update is 100% required. + * @param updateHints A objects which contains hints for this update: + * { + * _hostSizeChanged : boolean, + * _contentSizeChanged : boolean, + * _force : boolean, == preventSwallowing + * _changedOptions : { }, == preventSwallowing && preventSleep + * } + */ + function update(updateHints) { + clearTimeout(_swallowedUpdateTimeout); + updateHints = updateHints || {}; + _swallowedUpdateHints._hostSizeChanged |= updateHints._hostSizeChanged; + _swallowedUpdateHints._contentSizeChanged |= updateHints._contentSizeChanged; + _swallowedUpdateHints._force |= updateHints._force; + + var now = COMPATIBILITY.now(); + var hostSizeChanged = !!_swallowedUpdateHints._hostSizeChanged; + var contentSizeChanged = !!_swallowedUpdateHints._contentSizeChanged; + var force = !!_swallowedUpdateHints._force; + var changedOptions = updateHints._changedOptions; + var swallow = _swallowUpdateLag > 0 && _initialized && !_destroyed && !force && !changedOptions && (now - _lastUpdateTime) < _swallowUpdateLag && (!_heightAutoCache && !_widthAutoCache); + var displayIsHidden; + + if (swallow) + _swallowedUpdateTimeout = setTimeout(update, _swallowUpdateLag); + + //abort update due to: + //destroyed + //swallowing + //sleeping + //host is hidden or has false display + if (_destroyed || swallow || (_sleeping && !changedOptions) || (_initialized && !force && (displayIsHidden = _hostElement.is(':hidden'))) || _hostElement.css('display') === 'inline') + return; + + _lastUpdateTime = now; + _swallowedUpdateHints = {}; + + //if scrollbar styling is possible and native scrollbars aren't overlaid the scrollbar styling will be applied which hides the native scrollbars completely. + if (_nativeScrollbarStyling && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { + //native scrollbars are hidden, so change the values to zero + _nativeScrollbarSize.x = 0; + _nativeScrollbarSize.y = 0; + } + else { + //refresh native scrollbar size (in case of zoom) + _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); + } + + // Scrollbar padding is needed for firefox, because firefox hides scrollbar automatically if the size of the div is too small. + // The calculation: [scrollbar size +3 *3] + // (+3 because of possible decoration e.g. borders, margins etc., but only if native scrollbar is NOT a overlaid scrollbar) + // (*3 because (1)increase / (2)decrease -button and (3)resize handle) + _nativeScrollbarMinSize = { + x: (_nativeScrollbarSize.x + (_nativeScrollbarIsOverlaid.x ? 0 : 3)) * 3, + y: (_nativeScrollbarSize.y + (_nativeScrollbarIsOverlaid.y ? 0 : 3)) * 3 + }; + + //changedOptions = changedOptions || { }; + //freezeResizeObserver(_sizeObserverElement, true); + //freezeResizeObserver(_sizeAutoObserverElement, true); + + var checkCacheAutoForce = function () { + return checkCache.apply(this, [].slice.call(arguments).concat([force])); + }; + + //save current scroll offset + var currScroll = { + x: _viewportElement[_strScrollLeft](), + y: _viewportElement[_strScrollTop]() + }; + + var currentPreparedOptionsScrollbars = _currentPreparedOptions.scrollbars; + var currentPreparedOptionsTextarea = _currentPreparedOptions.textarea; + + //scrollbars visibility: + var scrollbarsVisibility = currentPreparedOptionsScrollbars.visibility; + var scrollbarsVisibilityChanged = checkCacheAutoForce(scrollbarsVisibility, _scrollbarsVisibilityCache); + + //scrollbars autoHide: + var scrollbarsAutoHide = currentPreparedOptionsScrollbars.autoHide; + var scrollbarsAutoHideChanged = checkCacheAutoForce(scrollbarsAutoHide, _scrollbarsAutoHideCache); + + //scrollbars click scrolling + var scrollbarsClickScrolling = currentPreparedOptionsScrollbars.clickScrolling; + var scrollbarsClickScrollingChanged = checkCacheAutoForce(scrollbarsClickScrolling, _scrollbarsClickScrollingCache); + + //scrollbars drag scrolling + var scrollbarsDragScrolling = currentPreparedOptionsScrollbars.dragScrolling; + var scrollbarsDragScrollingChanged = checkCacheAutoForce(scrollbarsDragScrolling, _scrollbarsDragScrollingCache); + + //className + var className = _currentPreparedOptions.className; + var classNameChanged = checkCacheAutoForce(className, _classNameCache); + + //resize + var resize = _currentPreparedOptions.resize; + var resizeChanged = checkCacheAutoForce(resize, _resizeCache) && !_isBody; //body can't be resized since the window itself acts as resize possibility. + + //paddingAbsolute + var paddingAbsolute = _currentPreparedOptions.paddingAbsolute; + var paddingAbsoluteChanged = checkCacheAutoForce(paddingAbsolute, _paddingAbsoluteCache); + + //clipAlways + var clipAlways = _currentPreparedOptions.clipAlways; + var clipAlwaysChanged = checkCacheAutoForce(clipAlways, _clipAlwaysCache); + + //sizeAutoCapable + var sizeAutoCapable = _currentPreparedOptions.sizeAutoCapable && !_isBody; //body can never be size auto, because it shall be always as big as the viewport. + var sizeAutoCapableChanged = checkCacheAutoForce(sizeAutoCapable, _sizeAutoCapableCache); + + //showNativeScrollbars + var ignoreOverlayScrollbarHiding = _currentPreparedOptions.nativeScrollbarsOverlaid.showNativeScrollbars; + var ignoreOverlayScrollbarHidingChanged = checkCacheAutoForce(ignoreOverlayScrollbarHiding, _ignoreOverlayScrollbarHidingCache); + + //autoUpdate + var autoUpdate = _currentPreparedOptions.autoUpdate; + var autoUpdateChanged = checkCacheAutoForce(autoUpdate, _autoUpdateCache); + + //overflowBehavior + var overflowBehavior = _currentPreparedOptions.overflowBehavior; + var overflowBehaviorChanged = checkCacheAutoForce(overflowBehavior, _overflowBehaviorCache, force); + + //dynWidth: + var textareaDynWidth = currentPreparedOptionsTextarea.dynWidth; + var textareaDynWidthChanged = checkCacheAutoForce(_textareaDynWidthCache, textareaDynWidth); + + //dynHeight: + var textareaDynHeight = currentPreparedOptionsTextarea.dynHeight; + var textareaDynHeightChanged = checkCacheAutoForce(_textareaDynHeightCache, textareaDynHeight); + + //scrollbars visibility + _scrollbarsAutoHideNever = scrollbarsAutoHide === 'n'; + _scrollbarsAutoHideScroll = scrollbarsAutoHide === 's'; + _scrollbarsAutoHideMove = scrollbarsAutoHide === 'm'; + _scrollbarsAutoHideLeave = scrollbarsAutoHide === 'l'; + + //scrollbars autoHideDelay + _scrollbarsAutoHideDelay = currentPreparedOptionsScrollbars.autoHideDelay; + + //old className + _oldClassName = _classNameCache; + + //resize + _resizeNone = resize === 'n'; + _resizeBoth = resize === 'b'; + _resizeHorizontal = resize === 'h'; + _resizeVertical = resize === 'v'; + + //normalizeRTL + _normalizeRTLCache = _currentPreparedOptions.normalizeRTL; + + //ignore overlay scrollbar hiding + ignoreOverlayScrollbarHiding = ignoreOverlayScrollbarHiding && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y); + + //refresh options cache + _scrollbarsVisibilityCache = scrollbarsVisibility; + _scrollbarsAutoHideCache = scrollbarsAutoHide; + _scrollbarsClickScrollingCache = scrollbarsClickScrolling; + _scrollbarsDragScrollingCache = scrollbarsDragScrolling; + _classNameCache = className; + _resizeCache = resize; + _paddingAbsoluteCache = paddingAbsolute; + _clipAlwaysCache = clipAlways; + _sizeAutoCapableCache = sizeAutoCapable; + _ignoreOverlayScrollbarHidingCache = ignoreOverlayScrollbarHiding; + _autoUpdateCache = autoUpdate; + _overflowBehaviorCache = extendDeep({}, overflowBehavior); + _textareaDynWidthCache = textareaDynWidth; + _textareaDynHeightCache = textareaDynHeight; + _hasOverflowCache = _hasOverflowCache || { x: false, y: false }; + + //set correct class name to the host element + if (classNameChanged) { + removeClass(_hostElement, _oldClassName + _strSpace + _classNameThemeNone); + addClass(_hostElement, className !== undefined && className !== null && className.length > 0 ? className : _classNameThemeNone); + } + + //set correct auto Update + if (autoUpdateChanged) { + if (autoUpdate === true) { + disconnectMutationObservers(); + autoUpdateLoop.add(_base); + } + else if (autoUpdate === null) { + if (_autoUpdateRecommended) { + disconnectMutationObservers(); + autoUpdateLoop.add(_base); + } + else { + autoUpdateLoop.remove(_base); + connectMutationObservers(); + } + } + else { + autoUpdateLoop.remove(_base); + connectMutationObservers(); + } + } + + //activate or deactivate size auto capability + if (sizeAutoCapableChanged) { + if (sizeAutoCapable) { + if (!_contentGlueElement) { + _contentGlueElement = FRAMEWORK(generateDiv(_classNameContentGlueElement)); + _paddingElement.before(_contentGlueElement); + } + else { + _contentGlueElement.show(); + } + if (_sizeAutoObserverAdded) { + _sizeAutoObserverElement.show(); + } + else { + _sizeAutoObserverElement = FRAMEWORK(generateDiv(_classNameSizeAutoObserverElement)); + _sizeAutoObserverElementNative = _sizeAutoObserverElement[0]; + + _contentGlueElement.before(_sizeAutoObserverElement); + var oldSize = { w: -1, h: -1 }; + setupResizeObserver(_sizeAutoObserverElement, function () { + var newSize = { + w: _sizeAutoObserverElementNative[LEXICON.oW], + h: _sizeAutoObserverElementNative[LEXICON.oH] + }; + if (checkCache(newSize, oldSize)) { + if (_initialized && (_heightAutoCache && newSize.h > 0) || (_widthAutoCache && newSize.w > 0)) { + update(); + } + else if (_initialized && (!_heightAutoCache && newSize.h === 0) || (!_widthAutoCache && newSize.w === 0)) { + update(); + } + } + oldSize = newSize; + }); + _sizeAutoObserverAdded = true; + //fix heightAuto detector bug if height is fixed but contentHeight is 0. + //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. + if (_cssCalc !== null) + _sizeAutoObserverElement.css(_strHeight, _cssCalc + '(100% + 1px)'); + } + } + else { + if (_sizeAutoObserverAdded) + _sizeAutoObserverElement.hide(); + if (_contentGlueElement) + _contentGlueElement.hide(); + } + } + + //if force, update all resizeObservers too + if (force) { + _sizeObserverElement.find('*').trigger(_strScroll); + if (_sizeAutoObserverAdded) + _sizeAutoObserverElement.find('*').trigger(_strScroll); + } + + //display hidden: + displayIsHidden = displayIsHidden === undefined ? _hostElement.is(':hidden') : displayIsHidden; + var displayIsHiddenChanged = checkCacheAutoForce(displayIsHidden, _displayIsHiddenCache); + + //textarea AutoWrapping: + var textareaAutoWrapping = _isTextarea ? _targetElement.attr('wrap') !== 'off' : false; + var textareaAutoWrappingChanged = checkCacheAutoForce(textareaAutoWrapping, _textareaAutoWrappingCache); + + //detect direction: + var cssDirection = _hostElement.css('direction'); + var cssDirectionChanged = checkCacheAutoForce(cssDirection, _cssDirectionCache); + + //detect box-sizing: + var boxSizing = _hostElement.css('box-sizing'); + var boxSizingChanged = checkCacheAutoForce(boxSizing, _cssBoxSizingCache); + + //detect padding: + var padding = { + c: force, + t: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strTop)), + r: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strRight)), + b: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strBottom)), + l: parseToZeroOrNumber(_hostElement.css(_strPaddingMinus + _strLeft)) + }; + + //width + height auto detecting var: + var sizeAutoObserverElementBCRect; + //exception occurs in IE8 sometimes (unknown exception) + try { + sizeAutoObserverElementBCRect = _sizeAutoObserverAdded ? _sizeAutoObserverElementNative[LEXICON.bCR]() : null; + } catch (ex) { + return; + } + + _isRTL = cssDirection === 'rtl'; + _isBorderBox = (boxSizing === 'border-box'); + var isRTLLeft = _isRTL ? _strLeft : _strRight; + var isRTLRight = _isRTL ? _strRight : _strLeft; + + //detect width auto: + var widthAutoResizeDetection = false; + var widthAutoObserverDetection = (_sizeAutoObserverAdded && (_hostElement.css(_strFloat) !== 'none' /*|| _isTextarea */)) ? (MATH.round(sizeAutoObserverElementBCRect.right - sizeAutoObserverElementBCRect.left) === 0) && (!paddingAbsolute ? (_hostElementNative[LEXICON.cW] - _paddingX) > 0 : true) : false; + if (sizeAutoCapable && !widthAutoObserverDetection) { + var tmpCurrHostWidth = _hostElementNative[LEXICON.oW]; + var tmpCurrContentGlueWidth = _contentGlueElement.css(_strWidth); + _contentGlueElement.css(_strWidth, _strAuto); + + var tmpNewHostWidth = _hostElementNative[LEXICON.oW]; + _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); + widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; + if (!widthAutoResizeDetection) { + _contentGlueElement.css(_strWidth, tmpCurrHostWidth + 1); + tmpNewHostWidth = _hostElementNative[LEXICON.oW]; + _contentGlueElement.css(_strWidth, tmpCurrContentGlueWidth); + widthAutoResizeDetection = tmpCurrHostWidth !== tmpNewHostWidth; + } + } + var widthAuto = (widthAutoObserverDetection || widthAutoResizeDetection) && sizeAutoCapable && !displayIsHidden; + var widthAutoChanged = checkCacheAutoForce(widthAuto, _widthAutoCache); + var wasWidthAuto = !widthAuto && _widthAutoCache; + + //detect height auto: + var heightAuto = _sizeAutoObserverAdded && sizeAutoCapable && !displayIsHidden ? (MATH.round(sizeAutoObserverElementBCRect.bottom - sizeAutoObserverElementBCRect.top) === 0) /* && (!paddingAbsolute && (_msieVersion > 9 || !_msieVersion) ? true : true) */ : false; + var heightAutoChanged = checkCacheAutoForce(heightAuto, _heightAutoCache); + var wasHeightAuto = !heightAuto && _heightAutoCache; + + //detect border: + //we need the border only if border box and auto size + var strMinusWidth = '-' + _strWidth; + var updateBorderX = (widthAuto && _isBorderBox) || !_isBorderBox; + var updateBorderY = (heightAuto && _isBorderBox) || !_isBorderBox; + var border = { + c: force, + t: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strTop + strMinusWidth), true) : 0, + r: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strRight + strMinusWidth), true) : 0, + b: updateBorderY ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strBottom + strMinusWidth), true) : 0, + l: updateBorderX ? parseToZeroOrNumber(_hostElement.css(_strBorderMinus + _strLeft + strMinusWidth), true) : 0 + }; + + //detect margin: + var margin = { + c: force, + t: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strTop)), + r: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strRight)), + b: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strBottom)), + l: parseToZeroOrNumber(_hostElement.css(_strMarginMinus + _strLeft)) + }; + + //detect css max width & height: + var cssMaxValue = { + h: String(_hostElement.css(_strMaxMinus + _strHeight)), + w: String(_hostElement.css(_strMaxMinus + _strWidth)) + }; + + //vars to apply correct css + var contentElementCSS = {}; + var contentGlueElementCSS = {}; + + //funcs + var getHostSize = function () { + //has to be clientSize because offsetSize respect borders + return { + w: _hostElementNative[LEXICON.cW], + h: _hostElementNative[LEXICON.cH] + }; + }; + var getViewportSize = function () { + //viewport size is padding container because it never has padding, margin and a border + //determine zoom rounding error -> sometimes scrollWidth/Height is smaller than clientWidth/Height + //if this happens add the difference to the viewportSize to compensate the rounding error + return { + w: _paddingElementNative[LEXICON.oW] + MATH.max(0, _contentElementNative[LEXICON.cW] - _contentElementNative[LEXICON.sW]), + h: _paddingElementNative[LEXICON.oH] + MATH.max(0, _contentElementNative[LEXICON.cH] - _contentElementNative[LEXICON.sH]) + }; + }; + + //set info for padding + var paddingAbsoluteX = _paddingX = padding.l + padding.r; + var paddingAbsoluteY = _paddingY = padding.t + padding.b; + paddingAbsoluteX *= paddingAbsolute ? 1 : 0; + paddingAbsoluteY *= paddingAbsolute ? 1 : 0; + padding.c = checkCacheAutoForce(padding, _cssPaddingCache); + + //set info for border + _borderX = border.l + border.r; + _borderY = border.t + border.b; + border.c = checkCacheAutoForce(border, _cssBorderCache); + + //set info for margin + _marginX = margin.l + margin.r; + _marginY = margin.t + margin.b; + margin.c = checkCacheAutoForce(margin, _cssMarginCache); + + //set info for css max value + cssMaxValue.ih = parseToZeroOrNumber(cssMaxValue.h); //ih = integer height + cssMaxValue.iw = parseToZeroOrNumber(cssMaxValue.w); //iw = integer width + cssMaxValue.ch = cssMaxValue.h.indexOf('px') > -1; //ch = correct height + cssMaxValue.cw = cssMaxValue.w.indexOf('px') > -1; //cw = correct width + cssMaxValue.c = checkCacheAutoForce(cssMaxValue, _cssMaxValueCache); + + //refresh cache + _displayIsHiddenCache = displayIsHidden; + _textareaAutoWrappingCache = textareaAutoWrapping; + _cssDirectionCache = cssDirection; + _cssBoxSizingCache = boxSizing; + _widthAutoCache = widthAuto; + _heightAutoCache = heightAuto; + _cssPaddingCache = padding; + _cssBorderCache = border; + _cssMarginCache = margin; + _cssMaxValueCache = cssMaxValue; + + //IEFix direction changed + if (cssDirectionChanged && _sizeAutoObserverAdded) + _sizeAutoObserverElement.css(_strFloat, isRTLRight); + + //apply padding: + if (padding.c || cssDirectionChanged || paddingAbsoluteChanged || widthAutoChanged || heightAutoChanged || boxSizingChanged || sizeAutoCapableChanged) { + var paddingElementCSS = {}; + var textareaCSS = {}; + setTopRightBottomLeft(contentGlueElementCSS, _strMarginMinus, [-padding.t, -padding.r, -padding.b, -padding.l]); + if (paddingAbsolute) { + setTopRightBottomLeft(paddingElementCSS, _strEmpty, [padding.t, padding.r, padding.b, padding.l]); + if (_isTextarea) + setTopRightBottomLeft(textareaCSS, _strPaddingMinus); + else + setTopRightBottomLeft(contentElementCSS, _strPaddingMinus); + } + else { + setTopRightBottomLeft(paddingElementCSS, _strEmpty); + if (_isTextarea) + setTopRightBottomLeft(textareaCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); + else + setTopRightBottomLeft(contentElementCSS, _strPaddingMinus, [padding.t, padding.r, padding.b, padding.l]); + } + _paddingElement.css(paddingElementCSS); + _targetElement.css(textareaCSS); + } + + //viewport size is padding container because it never has padding, margin and a border. + _viewportSize = getViewportSize(); + + //update Textarea + var textareaSize = _isTextarea ? textareaUpdate() : false; + var textareaSizeChanged = _isTextarea && checkCacheAutoForce(textareaSize, _textareaSizeCache); + var textareaDynOrigSize = _isTextarea && textareaSize ? { + w: textareaDynWidth ? textareaSize._dynamicWidth : textareaSize._originalWidth, + h: textareaDynHeight ? textareaSize._dynamicHeight : textareaSize._originalHeight + } : {}; + _textareaSizeCache = textareaSize; + + //fix height auto / width auto in cooperation with current padding & boxSizing behavior: + if (heightAuto && (heightAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c)) { + /* + if (cssMaxValue.ch) + contentElementCSS[_strMaxMinus + _strHeight] = + (cssMaxValue.ch ? (cssMaxValue.ih - paddingAbsoluteY + (_isBorderBox ? -_borderY : _paddingY)) + : _strEmpty); + */ + contentElementCSS[_strHeight] = _strAuto; + } + else if (heightAutoChanged || paddingAbsoluteChanged) { + contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; + contentElementCSS[_strHeight] = _strHundredPercent; + } + if (widthAuto && (widthAutoChanged || paddingAbsoluteChanged || boxSizingChanged || cssMaxValue.c || padding.c || border.c || cssDirectionChanged)) { + /* + if (cssMaxValue.cw) + contentElementCSS[_strMaxMinus + _strWidth] = + (cssMaxValue.cw ? (cssMaxValue.iw - paddingAbsoluteX + (_isBorderBox ? -_borderX : _paddingX)) + + (_nativeScrollbarIsOverlaid.y ? _overlayScrollbarDummySize.y : 0) + : _strEmpty); + */ + contentElementCSS[_strWidth] = _strAuto; + contentGlueElementCSS[_strMaxMinus + _strWidth] = _strHundredPercent; //IE Fix + } + else if (widthAutoChanged || paddingAbsoluteChanged) { + contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; + contentElementCSS[_strWidth] = _strHundredPercent; + contentElementCSS[_strFloat] = _strEmpty; + contentGlueElementCSS[_strMaxMinus + _strWidth] = _strEmpty; //IE Fix + } + if (widthAuto) { + if (!cssMaxValue.cw) + contentElementCSS[_strMaxMinus + _strWidth] = _strEmpty; + //textareaDynOrigSize.w || _strAuto :: doesnt works because applied margin will shift width + contentGlueElementCSS[_strWidth] = _strAuto; + + contentElementCSS[_strWidth] = _strAuto; + contentElementCSS[_strFloat] = isRTLRight; + } + else { + contentGlueElementCSS[_strWidth] = _strEmpty; + } + if (heightAuto) { + if (!cssMaxValue.ch) + contentElementCSS[_strMaxMinus + _strHeight] = _strEmpty; + //textareaDynOrigSize.h || _contentElementNative[LEXICON.cH] :: use for anti scroll jumping + contentGlueElementCSS[_strHeight] = textareaDynOrigSize.h || _contentElementNative[LEXICON.cH]; + } + else { + contentGlueElementCSS[_strHeight] = _strEmpty; + } + if (sizeAutoCapable) + _contentGlueElement.css(contentGlueElementCSS); + _contentElement.css(contentElementCSS); + + //CHECKPOINT HERE ~ + contentElementCSS = {}; + contentGlueElementCSS = {}; + + //if [content(host) client / scroll size, or target element direction, or content(host) max-sizes] changed, or force is true + if (hostSizeChanged || contentSizeChanged || textareaSizeChanged || cssDirectionChanged || boxSizingChanged || paddingAbsoluteChanged || widthAutoChanged || widthAuto || heightAutoChanged || heightAuto || cssMaxValue.c || ignoreOverlayScrollbarHidingChanged || overflowBehaviorChanged || clipAlwaysChanged || resizeChanged || scrollbarsVisibilityChanged || scrollbarsAutoHideChanged || scrollbarsDragScrollingChanged || scrollbarsClickScrollingChanged || textareaDynWidthChanged || textareaDynHeightChanged || textareaAutoWrappingChanged) { + var strOverflow = 'overflow'; + var strOverflowX = strOverflow + '-x'; + var strOverflowY = strOverflow + '-y'; + var strHidden = 'hidden'; + var strVisible = 'visible'; + + //Reset the viewport (very important for natively overlaid scrollbars and zoom change + //don't change the overflow prop as it is very expensive and affects performance !A LOT! + if(!_nativeScrollbarStyling) { + var viewportElementResetCSS = {}; + var resetXTmp = _hasOverflowCache.y && _hideOverflowCache.ys && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.y ? _viewportElement.css(isRTLLeft) : -_nativeScrollbarSize.y) : 0; + var resetBottomTmp = _hasOverflowCache.x && _hideOverflowCache.xs && !ignoreOverlayScrollbarHiding ? (_nativeScrollbarIsOverlaid.x ? _viewportElement.css(_strBottom) : -_nativeScrollbarSize.x) : 0; + setTopRightBottomLeft(viewportElementResetCSS, _strEmpty); + _viewportElement.css(viewportElementResetCSS); + } + + //measure several sizes: + var contentMeasureElement = getContentMeasureElement(); + //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 + var contentSize = { + //use clientSize because natively overlaidScrollbars add borders + w: textareaDynOrigSize.w || contentMeasureElement[LEXICON.cW], + h: textareaDynOrigSize.h || contentMeasureElement[LEXICON.cH] + }; + var scrollSize = { + w: contentMeasureElement[LEXICON.sW], + h: contentMeasureElement[LEXICON.sH] + }; + + //apply the correct viewport style and measure viewport size + if(!_nativeScrollbarStyling) { + viewportElementResetCSS[_strBottom] = wasHeightAuto ? _strEmpty : resetBottomTmp; + viewportElementResetCSS[isRTLLeft] = wasWidthAuto ? _strEmpty : resetXTmp; + _viewportElement.css(viewportElementResetCSS); + } + _viewportSize = getViewportSize(); + + //measure and correct several sizes + var hostSize = getHostSize(); + var contentGlueSize = { + //client/scrollSize + AbsolutePadding -> because padding is only applied to the paddingElement if its absolute, so you have to add it manually + //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 + w: MATH.max((widthAuto ? contentSize.w : scrollSize.w) + paddingAbsoluteX, hostSize.w), + h: MATH.max((heightAuto ? contentSize.h : scrollSize.h) + paddingAbsoluteY, hostSize.h) + }; + contentGlueSize.c = checkCacheAutoForce(contentGlueSize, _contentGlueSizeCache); + _contentGlueSizeCache = contentGlueSize; + + //apply correct contentGlue size + if (sizeAutoCapable) { + //size contentGlue correctly to make sure the element has correct size if the sizing switches to auto + if (contentGlueSize.c || (heightAuto || widthAuto)) { + contentGlueElementCSS[_strWidth] = contentGlueSize.w; + contentGlueElementCSS[_strHeight] = contentGlueSize.h; + + //textarea-sizes are already calculated correctly at this point + if (!_isTextarea) { + contentSize = { + //use clientSize because natively overlaidScrollbars add borders + w: contentMeasureElement[LEXICON.cW], + h: contentMeasureElement[LEXICON.cH] + }; + } + } + var textareaCoverCSS = {}; + var setContentGlueElementCSSfunction = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var wh = scrollbarVars._w_h; + var strWH = scrollbarVars._width_height; + var autoSize = horizontal ? widthAuto : heightAuto; + var borderSize = horizontal ? _borderX : _borderY; + var paddingSize = horizontal ? _paddingX : _paddingY; + var marginSize = horizontal ? _marginX : _marginY; + var maxSize = contentGlueElementCSS[strWH] + (_isBorderBox ? borderSize : -paddingSize); + + //make contentGlue size -1 if element is not auto sized, to make sure that a resize event happens when the element shrinks + if (!autoSize || (!autoSize && border.c)) + contentGlueElementCSS[strWH] = hostSize[wh] - (_isBorderBox ? 0 : paddingSize + borderSize) - 1 - marginSize; + + //if size is auto and host is same size as max size, make content glue size +1 to make sure size changes will be detected + if (autoSize && cssMaxValue['c' + wh] && cssMaxValue['i' + wh] === maxSize) + contentGlueElementCSS[strWH] = maxSize + (_isBorderBox ? 0 : paddingSize) + 1; + + //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) + if (autoSize && (contentSize[wh] < _viewportSize[wh]) && (horizontal && _isTextarea ? !textareaAutoWrapping : true)) { + if (_isTextarea) + textareaCoverCSS[strWH] = parseToZeroOrNumber(_textareaCoverElement.css(strWH)) - 1; + contentGlueElementCSS[strWH] -= 1; + } + + //make sure content glue size is at least 1 + if (contentSize[wh] > 0) + contentGlueElementCSS[strWH] = MATH.max(1, contentGlueElementCSS[strWH]); + }; + setContentGlueElementCSSfunction(true); + setContentGlueElementCSSfunction(false); + + if (_isTextarea) + _textareaCoverElement.css(textareaCoverCSS); + _contentGlueElement.css(contentGlueElementCSS); + } + if (widthAuto) + contentElementCSS[_strWidth] = _strHundredPercent; + if (widthAuto && !_isBorderBox && !_mutationObserversConnected) + contentElementCSS[_strFloat] = 'none'; + + //apply and reset content style + _contentElement.css(contentElementCSS); + contentElementCSS = {}; + + //measure again, but this time all correct sizes: + var contentScrollSize = { + w: contentMeasureElement[LEXICON.sW], + h: contentMeasureElement[LEXICON.sH], + }; + contentScrollSize.c = contentSizeChanged = checkCacheAutoForce(contentScrollSize, _contentScrollSizeCache); + _contentScrollSizeCache = contentScrollSize; + + //refresh viewport size after correct measuring + _viewportSize = getViewportSize(); + + hostSize = getHostSize(); + hostSizeChanged = checkCacheAutoForce(hostSize, _hostSizeCache); + _hostSizeCache = hostSize; + + var hideOverflowForceTextarea = _isTextarea && (_viewportSize.w === 0 || _viewportSize.h === 0); + var previousOverflowAmount = _overflowAmountCache; + var overflowBehaviorIsVS = {}; + var overflowBehaviorIsVH = {}; + var overflowBehaviorIsS = {}; + var overflowAmount = {}; + var hasOverflow = {}; + var hideOverflow = {}; + var canScroll = {}; + var viewportRect = _paddingElementNative[LEXICON.bCR](); + var setOverflowVariables = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var scrollbarVarsInverted = getScrollbarVars(!horizontal); + var xyI = scrollbarVarsInverted._x_y; + var xy = scrollbarVars._x_y; + var wh = scrollbarVars._w_h; + var widthHeight = scrollbarVars._width_height; + var scrollMax = _strScroll + scrollbarVars._Left_Top + 'Max'; + var fractionalOverflowAmount = viewportRect[widthHeight] ? MATH.abs(viewportRect[widthHeight] - _viewportSize[wh]) : 0; + var checkFractionalOverflowAmount = previousOverflowAmount && previousOverflowAmount[xy] > 0 && _viewportElementNative[scrollMax] === 0; + overflowBehaviorIsVS[xy] = overflowBehavior[xy] === 'v-s'; + overflowBehaviorIsVH[xy] = overflowBehavior[xy] === 'v-h'; + overflowBehaviorIsS[xy] = overflowBehavior[xy] === 's'; + overflowAmount[xy] = MATH.max(0, MATH.round((contentScrollSize[wh] - _viewportSize[wh]) * 100) / 100); + overflowAmount[xy] *= (hideOverflowForceTextarea || (checkFractionalOverflowAmount && fractionalOverflowAmount > 0 && fractionalOverflowAmount < 1)) ? 0 : 1; + hasOverflow[xy] = overflowAmount[xy] > 0; + + //hideOverflow: + //x || y : true === overflow is hidden by "overflow: scroll" OR "overflow: hidden" + //xs || ys : true === overflow is hidden by "overflow: scroll" + hideOverflow[xy] = overflowBehaviorIsVS[xy] || overflowBehaviorIsVH[xy] ? (hasOverflow[xyI] && !overflowBehaviorIsVS[xyI] && !overflowBehaviorIsVH[xyI]) : hasOverflow[xy]; + hideOverflow[xy + 's'] = hideOverflow[xy] ? (overflowBehaviorIsS[xy] || overflowBehaviorIsVS[xy]) : false; + + canScroll[xy] = hasOverflow[xy] && hideOverflow[xy + 's']; + }; + setOverflowVariables(true); + setOverflowVariables(false); + + overflowAmount.c = checkCacheAutoForce(overflowAmount, _overflowAmountCache); + _overflowAmountCache = overflowAmount; + hasOverflow.c = checkCacheAutoForce(hasOverflow, _hasOverflowCache); + _hasOverflowCache = hasOverflow; + hideOverflow.c = checkCacheAutoForce(hideOverflow, _hideOverflowCache); + _hideOverflowCache = hideOverflow; + + //if native scrollbar is overlay at x OR y axis, prepare DOM + if (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y) { + var borderDesign = 'px solid transparent'; + var contentArrangeElementCSS = {}; + var arrangeContent = {}; + var arrangeChanged = force; + var setContentElementCSS; + + if (hasOverflow.x || hasOverflow.y) { + arrangeContent.w = _nativeScrollbarIsOverlaid.y && hasOverflow.y ? contentScrollSize.w + _overlayScrollbarDummySize.y : _strEmpty; + arrangeContent.h = _nativeScrollbarIsOverlaid.x && hasOverflow.x ? contentScrollSize.h + _overlayScrollbarDummySize.x : _strEmpty; + arrangeChanged = checkCacheAutoForce(arrangeContent, _arrangeContentSizeCache); + _arrangeContentSizeCache = arrangeContent; + } + + if (hasOverflow.c || hideOverflow.c || contentScrollSize.c || cssDirectionChanged || widthAutoChanged || heightAutoChanged || widthAuto || heightAuto || ignoreOverlayScrollbarHidingChanged) { + contentElementCSS[_strMarginMinus + isRTLRight] = contentElementCSS[_strBorderMinus + isRTLRight] = _strEmpty; + setContentElementCSS = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var scrollbarVarsInverted = getScrollbarVars(!horizontal); + var xy = scrollbarVars._x_y; + var strDirection = horizontal ? _strBottom : isRTLLeft; + var invertedAutoSize = horizontal ? heightAuto : widthAuto; + + if (_nativeScrollbarIsOverlaid[xy] && hasOverflow[xy] && hideOverflow[xy + 's']) { + contentElementCSS[_strMarginMinus + strDirection] = invertedAutoSize ? (ignoreOverlayScrollbarHiding ? _strEmpty : _overlayScrollbarDummySize[xy]) : _strEmpty; + contentElementCSS[_strBorderMinus + strDirection] = ((horizontal ? !invertedAutoSize : true) && !ignoreOverlayScrollbarHiding) ? (_overlayScrollbarDummySize[xy] + borderDesign) : _strEmpty; + } + else { + arrangeContent[scrollbarVarsInverted._w_h] = + contentElementCSS[_strMarginMinus + strDirection] = + contentElementCSS[_strBorderMinus + strDirection] = _strEmpty; + arrangeChanged = true; + } + }; + + if (_nativeScrollbarStyling) { + if (ignoreOverlayScrollbarHiding) + removeClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); + else + addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); + } + else { + setContentElementCSS(true); + setContentElementCSS(false); + } + } + if (ignoreOverlayScrollbarHiding) { + arrangeContent.w = arrangeContent.h = _strEmpty; + arrangeChanged = true; + } + if (arrangeChanged && !_nativeScrollbarStyling) { + contentArrangeElementCSS[_strWidth] = hideOverflow.y ? arrangeContent.w : _strEmpty; + contentArrangeElementCSS[_strHeight] = hideOverflow.x ? arrangeContent.h : _strEmpty; + + if (!_contentArrangeElement) { + _contentArrangeElement = FRAMEWORK(generateDiv(_classNameContentArrangeElement)); + _viewportElement.prepend(_contentArrangeElement); + } + _contentArrangeElement.css(contentArrangeElementCSS); + } + _contentElement.css(contentElementCSS); + } + + var viewportElementCSS = {}; + var paddingElementCSS = {}; + var setViewportCSS; + if (hostSizeChanged || hasOverflow.c || hideOverflow.c || contentScrollSize.c || overflowBehaviorChanged || boxSizingChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged || clipAlwaysChanged || heightAutoChanged) { + viewportElementCSS[isRTLRight] = _strEmpty; + setViewportCSS = function (horizontal) { + var scrollbarVars = getScrollbarVars(horizontal); + var scrollbarVarsInverted = getScrollbarVars(!horizontal); + var xy = scrollbarVars._x_y; + var XY = scrollbarVars._X_Y; + var strDirection = horizontal ? _strBottom : isRTLLeft; + + var reset = function () { + viewportElementCSS[strDirection] = _strEmpty; + _contentBorderSize[scrollbarVarsInverted._w_h] = 0; + }; + if (hasOverflow[xy] && hideOverflow[xy + 's']) { + viewportElementCSS[strOverflow + XY] = _strScroll; + if (ignoreOverlayScrollbarHiding || _nativeScrollbarStyling) { + reset(); + } + else { + viewportElementCSS[strDirection] = -(_nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[xy] : _nativeScrollbarSize[xy]); + _contentBorderSize[scrollbarVarsInverted._w_h] = _nativeScrollbarIsOverlaid[xy] ? _overlayScrollbarDummySize[scrollbarVarsInverted._x_y] : 0; + } + } else { + viewportElementCSS[strOverflow + XY] = _strEmpty; + reset(); + } + }; + setViewportCSS(true); + setViewportCSS(false); + + // if the scroll container is too small and if there is any overflow with no overlay scrollbar (and scrollbar styling isn't possible), + // make viewport element greater in size (Firefox hide Scrollbars fix) + // because firefox starts hiding scrollbars on too small elements + // with this behavior the overflow calculation may be incorrect or the scrollbars would appear suddenly + // https://bugzilla.mozilla.org/show_bug.cgi?id=292284 + if (!_nativeScrollbarStyling + && (_viewportSize.h < _nativeScrollbarMinSize.x || _viewportSize.w < _nativeScrollbarMinSize.y) + && ((hasOverflow.x && hideOverflow.x && !_nativeScrollbarIsOverlaid.x) || (hasOverflow.y && hideOverflow.y && !_nativeScrollbarIsOverlaid.y))) { + viewportElementCSS[_strPaddingMinus + _strTop] = _nativeScrollbarMinSize.x; + viewportElementCSS[_strMarginMinus + _strTop] = -_nativeScrollbarMinSize.x; + + viewportElementCSS[_strPaddingMinus + isRTLRight] = _nativeScrollbarMinSize.y; + viewportElementCSS[_strMarginMinus + isRTLRight] = -_nativeScrollbarMinSize.y; + } + else { + viewportElementCSS[_strPaddingMinus + _strTop] = + viewportElementCSS[_strMarginMinus + _strTop] = + viewportElementCSS[_strPaddingMinus + isRTLRight] = + viewportElementCSS[_strMarginMinus + isRTLRight] = _strEmpty; + } + viewportElementCSS[_strPaddingMinus + isRTLLeft] = + viewportElementCSS[_strMarginMinus + isRTLLeft] = _strEmpty; + + //if there is any overflow (x OR y axis) and this overflow shall be hidden, make overflow hidden, else overflow visible + if ((hasOverflow.x && hideOverflow.x) || (hasOverflow.y && hideOverflow.y) || hideOverflowForceTextarea) { + //only hide if is Textarea + if (_isTextarea && hideOverflowForceTextarea) { + paddingElementCSS[strOverflowX] = + paddingElementCSS[strOverflowY] = strHidden; + } + } + else { + if (!clipAlways || (overflowBehaviorIsVH.x || overflowBehaviorIsVS.x || overflowBehaviorIsVH.y || overflowBehaviorIsVS.y)) { + //only un-hide if Textarea + if (_isTextarea) { + paddingElementCSS[strOverflowX] = + paddingElementCSS[strOverflowY] = _strEmpty; + } + viewportElementCSS[strOverflowX] = + viewportElementCSS[strOverflowY] = strVisible; + } + } + + _paddingElement.css(paddingElementCSS); + _viewportElement.css(viewportElementCSS); + viewportElementCSS = {}; + + //force soft redraw in webkit because without the scrollbars will may appear because DOM wont be redrawn under special conditions + if ((hasOverflow.c || boxSizingChanged || widthAutoChanged || heightAutoChanged) && !(_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)) { + var elementStyle = _contentElementNative[LEXICON.s]; + var dump; + elementStyle.webkitTransform = 'scale(1)'; + elementStyle.display = 'run-in'; + dump = _contentElementNative[LEXICON.oH]; + elementStyle.display = _strEmpty; //|| dump; //use dump to prevent it from deletion if minify + elementStyle.webkitTransform = _strEmpty; + } + /* + //force hard redraw in webkit if native overlaid scrollbars shall appear + if (ignoreOverlayScrollbarHidingChanged && ignoreOverlayScrollbarHiding) { + _hostElement.hide(); + var dump = _hostElementNative[LEXICON.oH]; + _hostElement.show(); + } + */ + } + + //change to direction RTL and width auto Bugfix in Webkit + //without this fix, the DOM still thinks the scrollbar is LTR and thus the content is shifted to the left + contentElementCSS = {}; + if (cssDirectionChanged || widthAutoChanged || heightAutoChanged) { + if (_isRTL && widthAuto) { + var floatTmp = _contentElement.css(_strFloat); + var posLeftWithoutFloat = MATH.round(_contentElement.css(_strFloat, _strEmpty).css(_strLeft, _strEmpty).position().left); + _contentElement.css(_strFloat, floatTmp); + var posLeftWithFloat = MATH.round(_contentElement.position().left); + + if (posLeftWithoutFloat !== posLeftWithFloat) + contentElementCSS[_strLeft] = posLeftWithoutFloat; + } + else { + contentElementCSS[_strLeft] = _strEmpty; + } + } + _contentElement.css(contentElementCSS); + + //handle scroll position + if (_isTextarea && contentSizeChanged) { + var textareaInfo = getTextareaInfo(); + if (textareaInfo) { + var textareaRowsChanged = _textareaInfoCache === undefined ? true : textareaInfo._rows !== _textareaInfoCache._rows; + var cursorRow = textareaInfo._cursorRow; + var cursorCol = textareaInfo._cursorColumn; + var widestRow = textareaInfo._widestRow; + var lastRow = textareaInfo._rows; + var lastCol = textareaInfo._columns; + var cursorPos = textareaInfo._cursorPosition; + var cursorMax = textareaInfo._cursorMax; + var cursorIsLastPosition = (cursorPos >= cursorMax && _textareaHasFocus); + var textareaScrollAmount = { + x: (!textareaAutoWrapping && (cursorCol === lastCol && cursorRow === widestRow)) ? _overflowAmountCache.x : -1, + y: (textareaAutoWrapping ? cursorIsLastPosition || textareaRowsChanged && (previousOverflowAmount ? (currScroll.y === previousOverflowAmount.y) : false) : (cursorIsLastPosition || textareaRowsChanged) && cursorRow === lastRow) ? _overflowAmountCache.y : -1 + }; + currScroll.x = textareaScrollAmount.x > -1 ? (_isRTL && _normalizeRTLCache && _rtlScrollBehavior.i ? 0 : textareaScrollAmount.x) : currScroll.x; //if inverted, scroll to 0 -> normalized this means to max scroll offset. + currScroll.y = textareaScrollAmount.y > -1 ? textareaScrollAmount.y : currScroll.y; + } + _textareaInfoCache = textareaInfo; + } + if (_isRTL && _rtlScrollBehavior.i && _nativeScrollbarIsOverlaid.y && hasOverflow.x && _normalizeRTLCache) + currScroll.x += _contentBorderSize.w || 0; + if (widthAuto) + _hostElement[_strScrollLeft](0); + if (heightAuto) + _hostElement[_strScrollTop](0); + _viewportElement[_strScrollLeft](currScroll.x)[_strScrollTop](currScroll.y); + + //scrollbars management: + var scrollbarsVisibilityVisible = scrollbarsVisibility === 'v'; + var scrollbarsVisibilityHidden = scrollbarsVisibility === 'h'; + var scrollbarsVisibilityAuto = scrollbarsVisibility === 'a'; + + var showScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, true, canScroll.x); + var showScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, true, canScroll.y); + var hideScrollbarH = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, true, false, canScroll.x); + var hideScrollbarV = COMPATIBILITY.bind(refreshScrollbarAppearance, 0, false, false, canScroll.y); + + //manage class name which indicates scrollable overflow + if (hideOverflow.x || hideOverflow.y) + addClass(_hostElement, _classNameHostOverflow); + else + removeClass(_hostElement, _classNameHostOverflow); + if (hideOverflow.x) + addClass(_hostElement, _classNameHostOverflowX); + else + removeClass(_hostElement, _classNameHostOverflowX); + if (hideOverflow.y) + addClass(_hostElement, _classNameHostOverflowY); + else + removeClass(_hostElement, _classNameHostOverflowY); + + //add or remove rtl class name for styling purposes + if (cssDirectionChanged) { + if (_isRTL) + addClass(_hostElement, _classNameHostRTL); + else + removeClass(_hostElement, _classNameHostRTL); + } + + //manage the resize feature (CSS3 resize "polyfill" for this plugin) + if (_isBody) + addClass(_hostElement, _classNameHostResizeDisabled); + if (resizeChanged) { + removeClass(_scrollbarCornerElement, [ + _classNameScrollbarCornerResize, + _classNameScrollbarCornerResizeB, + _classNameScrollbarCornerResizeH, + _classNameScrollbarCornerResizeV].join(_strSpace)); + if (_resizeNone) { + addClass(_hostElement, _classNameHostResizeDisabled); + } + else { + removeClass(_hostElement, _classNameHostResizeDisabled); + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResize); + if (_resizeBoth) + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeB); + else if (_resizeHorizontal) + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeH); + else if (_resizeVertical) + addClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeV); + } + } + + //manage the scrollbars general visibility + the scrollbar interactivity (unusable class name) + if (scrollbarsVisibilityChanged || overflowBehaviorChanged || hideOverflow.c || hasOverflow.c || ignoreOverlayScrollbarHidingChanged) { + if (ignoreOverlayScrollbarHiding) { + if (ignoreOverlayScrollbarHidingChanged) { + removeClass(_hostElement, _classNameHostScrolling); + if (ignoreOverlayScrollbarHiding) { + hideScrollbarH(); + hideScrollbarV(); + } + } + } + else if (scrollbarsVisibilityAuto) { + if (canScroll.x) + showScrollbarH(); + else + hideScrollbarH(); + + if (canScroll.y) + showScrollbarV(); + else + hideScrollbarV(); + } + else if (scrollbarsVisibilityVisible) { + showScrollbarH(); + showScrollbarV(); + } + else if (scrollbarsVisibilityHidden) { + hideScrollbarH(); + hideScrollbarV(); + } + } + + //manage the scrollbars auto hide feature (auto hide them after specific actions) + if (scrollbarsAutoHideChanged || ignoreOverlayScrollbarHidingChanged) { + if (_scrollbarsAutoHideLeave || _scrollbarsAutoHideMove) { + setupHostMouseTouchEvents(true); + setupHostMouseTouchEvents(); + } + else { + setupHostMouseTouchEvents(true); + } + + if (_scrollbarsAutoHideNever) + refreshScrollbarsAutoHide(true); + else + refreshScrollbarsAutoHide(false, true); + } + + //manage scrollbars handle length & offset - don't remove! + if (hostSizeChanged || overflowAmount.c || heightAutoChanged || widthAutoChanged || resizeChanged || boxSizingChanged || paddingAbsoluteChanged || ignoreOverlayScrollbarHidingChanged || cssDirectionChanged) { + refreshScrollbarHandleLength(true); + refreshScrollbarHandleOffset(true); + refreshScrollbarHandleLength(false); + refreshScrollbarHandleOffset(false); + } + + //manage interactivity + if (scrollbarsClickScrollingChanged) + refreshScrollbarsInteractive(true, scrollbarsClickScrolling); + if (scrollbarsDragScrollingChanged) + refreshScrollbarsInteractive(false, scrollbarsDragScrolling); + + //callbacks: + if (cssDirectionChanged) { + dispatchCallback('onDirectionChanged', { + isRTL: _isRTL, + dir: cssDirection + }); + } + if (hostSizeChanged) { + dispatchCallback('onHostSizeChanged', { + width: _hostSizeCache.w, + height: _hostSizeCache.h + }); + } + if (contentSizeChanged) { + dispatchCallback('onContentSizeChanged', { + width: _contentScrollSizeCache.w, + height: _contentScrollSizeCache.h + }); + } + if (hasOverflow.c || hideOverflow.c) { + dispatchCallback('onOverflowChanged', { + x: hasOverflow.x, + y: hasOverflow.y, + xScrollable: hideOverflow.xs, + yScrollable: hideOverflow.ys, + clipped: hideOverflow.x || hideOverflow.y + }); + } + if (overflowAmount.c) { + dispatchCallback('onOverflowAmountChanged', { + x: overflowAmount.x, + y: overflowAmount.y + }); + } + } + + //fix body min size + if (_isBody && _bodyMinSizeCache && (_hasOverflowCache.c || _bodyMinSizeCache.c)) { + //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. + if (!_bodyMinSizeCache.f) + bodyMinSizeChanged(); + if (_nativeScrollbarIsOverlaid.y && _hasOverflowCache.x) + _contentElement.css(_strMinMinus + _strWidth, _bodyMinSizeCache.w + _overlayScrollbarDummySize.y); + if (_nativeScrollbarIsOverlaid.x && _hasOverflowCache.y) + _contentElement.css(_strMinMinus + _strHeight, _bodyMinSizeCache.h + _overlayScrollbarDummySize.x); + _bodyMinSizeCache.c = false; + } + + //freezeResizeObserver(_sizeObserverElement, false); + //freezeResizeObserver(_sizeAutoObserverElement, false); + + dispatchCallback('onUpdated', { forced: force }); + } + + + //==== Options ====// + + /** + * Sets new options but doesn't call the update method. + * @param newOptions The object which contains the new options. + * @returns {*} A object which contains the changed options. + */ + function setOptions(newOptions) { + var validatedOpts = _pluginsOptions._validate(newOptions, _pluginsOptions._template, true, _currentOptions) + + _currentOptions = extendDeep({}, _currentOptions, validatedOpts._default); + _currentPreparedOptions = extendDeep({}, _currentPreparedOptions, validatedOpts._prepared); + + return validatedOpts._prepared; + } + + + //==== Structure ====// + + /** + * Builds or destroys the wrapper and helper DOM elements. + * @param destroy Indicates whether the DOM shall be build or destroyed. + */ + function setupStructureDOM(destroy) { + var strParent = 'parent'; + var classNameResizeObserverHost = 'os-resize-observer-host'; + var classNameTextareaElementFull = _classNameTextareaElement + _strSpace + _classNameTextInherit; + var textareaClass = _isTextarea ? _strSpace + _classNameTextInherit : _strEmpty; + var adoptAttrs = _currentPreparedOptions.textarea.inheritedAttrs; + var adoptAttrsMap = {}; + var applyAdoptedAttrs = function () { + var applyAdoptedAttrsElm = destroy ? _targetElement : _hostElement; + each(adoptAttrsMap, function (key, value) { + if (type(value) == TYPES.s) { + if (key == LEXICON.c) + applyAdoptedAttrsElm.addClass(value); + else + applyAdoptedAttrsElm.attr(key, value); + } + }); + }; + var hostElementClassNames = [ + _classNameHostElement, + _classNameHostTextareaElement, + _classNameHostResizeDisabled, + _classNameHostRTL, + _classNameHostScrollbarHorizontalHidden, + _classNameHostScrollbarVerticalHidden, + _classNameHostTransition, + _classNameHostScrolling, + _classNameHostOverflow, + _classNameHostOverflowX, + _classNameHostOverflowY, + _classNameThemeNone, + _classNameTextareaElement, + _classNameTextInherit, + _classNameCache].join(_strSpace); + var hostElementCSS = {}; + + //get host element as first element, because that's the most upper element and required for the other elements + _hostElement = _hostElement || (_isTextarea ? (_domExists ? _targetElement[strParent]()[strParent]()[strParent]()[strParent]() : FRAMEWORK(generateDiv(_classNameHostTextareaElement))) : _targetElement); + _contentElement = _contentElement || selectOrGenerateDivByClass(_classNameContentElement + textareaClass); + _viewportElement = _viewportElement || selectOrGenerateDivByClass(_classNameViewportElement + textareaClass); + _paddingElement = _paddingElement || selectOrGenerateDivByClass(_classNamePaddingElement + textareaClass); + _sizeObserverElement = _sizeObserverElement || selectOrGenerateDivByClass(classNameResizeObserverHost); + _textareaCoverElement = _textareaCoverElement || (_isTextarea ? selectOrGenerateDivByClass(_classNameTextareaCoverElement) : undefined); + + //on destroy, remove all generated class names from the host element before collecting the adopted attributes + //to prevent adopting generated class names + if (destroy) + removeClass(_hostElement, hostElementClassNames); + + //collect all adopted attributes + adoptAttrs = type(adoptAttrs) == TYPES.s ? adoptAttrs.split(_strSpace) : adoptAttrs; + if (type(adoptAttrs) == TYPES.a && _isTextarea) { + each(adoptAttrs, function (i, v) { + if (type(v) == TYPES.s) { + adoptAttrsMap[v] = destroy ? _hostElement.attr(v) : _targetElement.attr(v); + } + }); + } + + if (!destroy) { + if (_isTextarea) { + if (!_currentPreparedOptions.sizeAutoCapable) { + hostElementCSS[_strWidth] = _targetElement.css(_strWidth); + hostElementCSS[_strHeight] = _targetElement.css(_strHeight); + } + + if (!_domExists) + _targetElement.addClass(_classNameTextInherit).wrap(_hostElement); + + //jQuery clones elements in wrap functions, so we have to select them again + _hostElement = _targetElement[strParent]().css(hostElementCSS); + } + + if (!_domExists) { + //add the correct class to the target element + addClass(_targetElement, _isTextarea ? classNameTextareaElementFull : _classNameHostElement); + + //wrap the content into the generated elements to create the required DOM + _hostElement.wrapInner(_contentElement) + .wrapInner(_viewportElement) + .wrapInner(_paddingElement) + .prepend(_sizeObserverElement); + + //jQuery clones elements in wrap functions, so we have to select them again + _contentElement = findFirst(_hostElement, _strDot + _classNameContentElement); + _viewportElement = findFirst(_hostElement, _strDot + _classNameViewportElement); + _paddingElement = findFirst(_hostElement, _strDot + _classNamePaddingElement); + + if (_isTextarea) { + _contentElement.prepend(_textareaCoverElement); + applyAdoptedAttrs(); + } + } + + if (_nativeScrollbarStyling) + addClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible); + if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y) + addClass(_viewportElement, _classNameViewportNativeScrollbarsOverlaid); + if (_isBody) + addClass(_htmlElement, _classNameHTMLElement); + + _sizeObserverElementNative = _sizeObserverElement[0]; + _hostElementNative = _hostElement[0]; + _paddingElementNative = _paddingElement[0]; + _viewportElementNative = _viewportElement[0]; + _contentElementNative = _contentElement[0]; + + updateViewportAttrsFromTarget(); + } + else { + if (_domExists && _initialized) { + //clear size observer + _sizeObserverElement.children().remove(); + + //remove the style property and classes from already generated elements + each([_paddingElement, _viewportElement, _contentElement, _textareaCoverElement], function (i, elm) { + if (elm) { + removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); + } + }); + + //add classes to the host element which was removed previously to match the expected DOM + addClass(_hostElement, _isTextarea ? _classNameHostTextareaElement : _classNameHostElement); + } + else { + //remove size observer + remove(_sizeObserverElement); + + //unwrap the content to restore DOM + _contentElement.contents() + .unwrap() + .unwrap() + .unwrap(); + + if (_isTextarea) { + _targetElement.unwrap(); + remove(_hostElement); + remove(_textareaCoverElement); + applyAdoptedAttrs(); + } + } + + if (_isTextarea) + _targetElement.removeAttr(LEXICON.s); + + if (_isBody) + removeClass(_htmlElement, _classNameHTMLElement); + } + } + + /** + * Adds or removes all wrapper elements interactivity events. + * @param destroy Indicates whether the Events shall be added or removed. + */ + function setupStructureEvents() { + var textareaKeyDownRestrictedKeyCodes = [ + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 123, //F1 to F12 + 33, 34, //page up, page down + 37, 38, 39, 40, //left, up, right, down arrows + 16, 17, 18, 19, 20, 144 //Shift, Ctrl, Alt, Pause, CapsLock, NumLock + ]; + var textareaKeyDownKeyCodesList = []; + var textareaUpdateIntervalID; + var scrollStopTimeoutId; + var scrollStopDelay = 175; + var strFocus = 'focus'; + + function updateTextarea(doClearInterval) { + textareaUpdate(); + _base.update(_strAuto); + if (doClearInterval && _autoUpdateRecommended) + clearInterval(textareaUpdateIntervalID); + } + function textareaOnScroll(event) { + _targetElement[_strScrollLeft](_rtlScrollBehavior.i && _normalizeRTLCache ? 9999999 : 0); + _targetElement[_strScrollTop](0); + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + return false; + } + function textareaOnDrop(event) { + setTimeout(function () { + if (!_destroyed) + updateTextarea(); + }, 50); + } + function textareaOnFocus() { + _textareaHasFocus = true; + addClass(_hostElement, strFocus); + } + function textareaOnFocusout() { + _textareaHasFocus = false; + textareaKeyDownKeyCodesList = []; + removeClass(_hostElement, strFocus); + updateTextarea(true); + } + function textareaOnKeyDown(event) { + var keyCode = event.keyCode; + + if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { + if (!textareaKeyDownKeyCodesList[LEXICON.l]) { + updateTextarea(); + textareaUpdateIntervalID = setInterval(updateTextarea, 1000 / 60); + } + if (inArray(keyCode, textareaKeyDownKeyCodesList) < 0) + textareaKeyDownKeyCodesList.push(keyCode); + } + } + function textareaOnKeyUp(event) { + var keyCode = event.keyCode; + var index = inArray(keyCode, textareaKeyDownKeyCodesList); + + if (inArray(keyCode, textareaKeyDownRestrictedKeyCodes) < 0) { + if (index > -1) + textareaKeyDownKeyCodesList.splice(index, 1); + if (!textareaKeyDownKeyCodesList[LEXICON.l]) + updateTextarea(true); + } + } + function contentOnTransitionEnd(event) { + if (_autoUpdateCache === true) + return; + event = event.originalEvent || event; + if (isSizeAffectingCSSProperty(event.propertyName)) + _base.update(_strAuto); + } + function viewportOnScroll(event) { + if (!_sleeping) { + if (scrollStopTimeoutId !== undefined) + clearTimeout(scrollStopTimeoutId); + else { + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(true); + + if (!nativeOverlayScrollbarsAreActive()) + addClass(_hostElement, _classNameHostScrolling); + + dispatchCallback('onScrollStart', event); + } + + //if a scrollbars handle gets dragged, the mousemove event is responsible for refreshing the handle offset + //because if CSS scroll-snap is used, the handle offset gets only refreshed on every snap point + //this looks laggy & clunky, it looks much better if the offset refreshes with the mousemove + if (!_scrollbarsHandlesDefineScrollPos) { + refreshScrollbarHandleOffset(true); + refreshScrollbarHandleOffset(false); + } + dispatchCallback('onScroll', event); + + scrollStopTimeoutId = setTimeout(function () { + if (!_destroyed) { + //OnScrollStop: + clearTimeout(scrollStopTimeoutId); + scrollStopTimeoutId = undefined; + + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(false); + + if (!nativeOverlayScrollbarsAreActive()) + removeClass(_hostElement, _classNameHostScrolling); + + dispatchCallback('onScrollStop', event); + } + }, scrollStopDelay); + } + } + + + if (_isTextarea) { + if (_msieVersion > 9 || !_autoUpdateRecommended) { + addDestroyEventListener(_targetElement, 'input', updateTextarea); + } + else { + addDestroyEventListener(_targetElement, + [_strKeyDownEvent, _strKeyUpEvent], + [textareaOnKeyDown, textareaOnKeyUp]); + } + + addDestroyEventListener(_targetElement, + [_strScroll, 'drop', strFocus, strFocus + 'out'], + [textareaOnScroll, textareaOnDrop, textareaOnFocus, textareaOnFocusout]); + } + else { + addDestroyEventListener(_contentElement, _strTransitionEndEvent, contentOnTransitionEnd); + } + addDestroyEventListener(_viewportElement, _strScroll, viewportOnScroll, true); + } + + + //==== Scrollbars ====// + + /** + * Builds or destroys all scrollbar DOM elements (scrollbar, track, handle) + * @param destroy Indicates whether the DOM shall be build or destroyed. + */ + function setupScrollbarsDOM(destroy) { + var selectOrGenerateScrollbarDOM = function (isHorizontal) { + var scrollbarClassName = isHorizontal ? _classNameScrollbarHorizontal : _classNameScrollbarVertical; + var scrollbar = selectOrGenerateDivByClass(_classNameScrollbar + _strSpace + scrollbarClassName, true); + var track = selectOrGenerateDivByClass(_classNameScrollbarTrack, scrollbar); + var handle = selectOrGenerateDivByClass(_classNameScrollbarHandle, scrollbar); + + if (!_domExists && !destroy) { + scrollbar.append(track); + track.append(handle); + } + + return { + _scrollbar: scrollbar, + _track: track, + _handle: handle + }; + }; + function resetScrollbarDOM(isHorizontal) { + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbar = scrollbarVars._scrollbar; + var track = scrollbarVars._track; + var handle = scrollbarVars._handle; + + if (_domExists && _initialized) { + each([scrollbar, track, handle], function (i, elm) { + removeClass(elm.removeAttr(LEXICON.s), _classNamesDynamicDestroy); + }); + } + else { + remove(scrollbar || selectOrGenerateScrollbarDOM(isHorizontal)._scrollbar); + } + } + var horizontalElements; + var verticalElements; + + if (!destroy) { + horizontalElements = selectOrGenerateScrollbarDOM(true); + verticalElements = selectOrGenerateScrollbarDOM(); + + _scrollbarHorizontalElement = horizontalElements._scrollbar; + _scrollbarHorizontalTrackElement = horizontalElements._track; + _scrollbarHorizontalHandleElement = horizontalElements._handle; + _scrollbarVerticalElement = verticalElements._scrollbar; + _scrollbarVerticalTrackElement = verticalElements._track; + _scrollbarVerticalHandleElement = verticalElements._handle; + + if (!_domExists) { + _paddingElement.after(_scrollbarVerticalElement); + _paddingElement.after(_scrollbarHorizontalElement); + } + } + else { + resetScrollbarDOM(true); + resetScrollbarDOM(); + } + } + + /** + * Initializes all scrollbar interactivity events. (track and handle dragging, clicking, scrolling) + * @param isHorizontal True if the target scrollbar is the horizontal scrollbar, false if the target scrollbar is the vertical scrollbar. + */ + function setupScrollbarEvents(isHorizontal) { + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbarVarsInfo = scrollbarVars._info; + var insideIFrame = _windowElementNative.top !== _windowElementNative; + var xy = scrollbarVars._x_y; + var XY = scrollbarVars._X_Y; + var scroll = _strScroll + scrollbarVars._Left_Top; + var strActive = 'active'; + var strSnapHandle = 'snapHandle'; + var scrollDurationFactor = 1; + var increaseDecreaseScrollAmountKeyCodes = [16, 17]; //shift, ctrl + var trackTimeout; + var mouseDownScroll; + var mouseDownOffset; + var mouseDownInvertedScale; + + function getPointerPosition(event) { + return _msieVersion && insideIFrame ? event['screen' + XY] : COMPATIBILITY.page(event)[xy]; //use screen coordinates in EDGE & IE because the page values are incorrect in frames. + } + function getPreparedScrollbarsOption(name) { + return _currentPreparedOptions.scrollbars[name]; + } + function increaseTrackScrollAmount() { + scrollDurationFactor = 0.5; + } + function decreaseTrackScrollAmount() { + scrollDurationFactor = 1; + } + function documentKeyDown(event) { + if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) + increaseTrackScrollAmount(); + } + function documentKeyUp(event) { + if (inArray(event.keyCode, increaseDecreaseScrollAmountKeyCodes) > -1) + decreaseTrackScrollAmount(); + } + function onMouseTouchDownContinue(event) { + var originalEvent = event.originalEvent || event; + var isTouchEvent = originalEvent.touches !== undefined; + return _sleeping || _destroyed || nativeOverlayScrollbarsAreActive() || !_scrollbarsDragScrollingCache || (isTouchEvent && !getPreparedScrollbarsOption('touchSupport')) ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; + } + function documentDragMove(event) { + if (onMouseTouchDownContinue(event)) { + var trackLength = scrollbarVarsInfo._trackLength; + var handleLength = scrollbarVarsInfo._handleLength; + var scrollRange = scrollbarVarsInfo._maxScroll; + var scrollRaw = (getPointerPosition(event) - mouseDownOffset) * mouseDownInvertedScale; + var scrollDeltaPercent = scrollRaw / (trackLength - handleLength); + var scrollDelta = (scrollRange * scrollDeltaPercent); + scrollDelta = isFinite(scrollDelta) ? scrollDelta : 0; + if (_isRTL && isHorizontal && !_rtlScrollBehavior.i) + scrollDelta *= -1; + + _viewportElement[scroll](MATH.round(mouseDownScroll + scrollDelta)); + + if (_scrollbarsHandlesDefineScrollPos) + refreshScrollbarHandleOffset(isHorizontal, mouseDownScroll + scrollDelta); + + if (!_supportPassiveEvents) + COMPATIBILITY.prvD(event); + } + else + documentMouseTouchUp(event); + } + function documentMouseTouchUp(event) { + event = event || event.originalEvent; + + setupResponsiveEventListener(_documentElement, + [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], + [documentDragMove, documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart], + true); + + if (_scrollbarsHandlesDefineScrollPos) + refreshScrollbarHandleOffset(isHorizontal, true); + + _scrollbarsHandlesDefineScrollPos = false; + removeClass(_bodyElement, _classNameDragging); + removeClass(scrollbarVars._handle, strActive); + removeClass(scrollbarVars._track, strActive); + removeClass(scrollbarVars._scrollbar, strActive); + + mouseDownScroll = undefined; + mouseDownOffset = undefined; + mouseDownInvertedScale = 1; + + decreaseTrackScrollAmount(); + + if (trackTimeout !== undefined) { + _base.scrollStop(); + clearTimeout(trackTimeout); + trackTimeout = undefined; + } + + if (event) { + var rect = _hostElementNative[LEXICON.bCR](); + var mouseInsideHost = event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom; + + //if mouse is outside host element + if (!mouseInsideHost) + hostOnMouseLeave(); + + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(false); + } + } + function onHandleMouseTouchDown(event) { + if (onMouseTouchDownContinue(event)) + onHandleMouseTouchDownAction(event); + } + function onHandleMouseTouchDownAction(event) { + mouseDownScroll = _viewportElement[scroll](); + mouseDownScroll = isNaN(mouseDownScroll) ? 0 : mouseDownScroll; + if (_isRTL && isHorizontal && !_rtlScrollBehavior.n || !_isRTL) + mouseDownScroll = mouseDownScroll < 0 ? 0 : mouseDownScroll; + + mouseDownInvertedScale = getHostElementInvertedScale()[xy]; + mouseDownOffset = getPointerPosition(event); + + _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); + addClass(_bodyElement, _classNameDragging); + addClass(scrollbarVars._handle, strActive); + addClass(scrollbarVars._scrollbar, strActive); + + setupResponsiveEventListener(_documentElement, + [_strMouseTouchMoveEvent, _strMouseTouchUpEvent, _strSelectStartEvent], + [documentDragMove, documentMouseTouchUp, documentOnSelectStart]); + + if (_msieVersion || !_documentMixed) + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + function onTrackMouseTouchDown(event) { + if (onMouseTouchDownContinue(event)) { + var scrollDistance = MATH.round(_viewportSize[scrollbarVars._w_h]); + var trackOffset = scrollbarVars._track.offset()[scrollbarVars._left_top]; + var ctrlKey = event.ctrlKey; + var instantScroll = event.shiftKey; + var instantScrollTransition = instantScroll && ctrlKey; + var isFirstIteration = true; + var easing = 'linear'; + var decreaseScroll; + var finishedCondition; + var scrollActionFinsished = function (transition) { + if (_scrollbarsHandlesDefineScrollPos) + refreshScrollbarHandleOffset(isHorizontal, transition); + }; + var scrollActionInstantFinished = function () { + scrollActionFinsished(); + onHandleMouseTouchDownAction(event); + }; + var scrollAction = function () { + if (!_destroyed) { + var mouseOffset = (mouseDownOffset - trackOffset) * mouseDownInvertedScale; + var handleOffset = scrollbarVarsInfo._handleOffset; + var trackLength = scrollbarVarsInfo._trackLength; + var handleLength = scrollbarVarsInfo._handleLength; + var scrollRange = scrollbarVarsInfo._maxScroll; + var currScroll = scrollbarVarsInfo._currentScroll; + var scrollDuration = 270 * scrollDurationFactor; + var timeoutDelay = isFirstIteration ? MATH.max(400, scrollDuration) : scrollDuration; + var instantScrollPosition = scrollRange * ((mouseOffset - (handleLength / 2)) / (trackLength - handleLength)); // 100% * positionPercent + var rtlIsNormal = _isRTL && isHorizontal && ((!_rtlScrollBehavior.i && !_rtlScrollBehavior.n) || _normalizeRTLCache); + var decreaseScrollCondition = rtlIsNormal ? handleOffset < mouseOffset : handleOffset > mouseOffset; + var scrollObj = {}; + var animationObj = { + easing: easing, + step: function (now) { + if (_scrollbarsHandlesDefineScrollPos) { + _viewportElement[scroll](now); //https://github.com/jquery/jquery/issues/4340 + refreshScrollbarHandleOffset(isHorizontal, now); + } + } + }; + instantScrollPosition = isFinite(instantScrollPosition) ? instantScrollPosition : 0; + instantScrollPosition = _isRTL && isHorizontal && !_rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; + + //_base.scrollStop(); + + if (instantScroll) { + _viewportElement[scroll](instantScrollPosition); //scroll instantly to new position + if (instantScrollTransition) { + //get the scroll position after instant scroll (in case CSS Snap Points are used) to get the correct snapped scroll position + //and the animation stops at the correct point + instantScrollPosition = _viewportElement[scroll](); + //scroll back to the position before instant scrolling so animation can be performed + _viewportElement[scroll](currScroll); + + instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.i ? (scrollRange - instantScrollPosition) : instantScrollPosition; + instantScrollPosition = rtlIsNormal && _rtlScrollBehavior.n ? -instantScrollPosition : instantScrollPosition; + + scrollObj[xy] = instantScrollPosition; + _base.scroll(scrollObj, extendDeep(animationObj, { + duration: 130, + complete: scrollActionInstantFinished + })); + } + else + scrollActionInstantFinished(); + } + else { + decreaseScroll = isFirstIteration ? decreaseScrollCondition : decreaseScroll; + finishedCondition = rtlIsNormal + ? (decreaseScroll ? handleOffset + handleLength >= mouseOffset : handleOffset <= mouseOffset) + : (decreaseScroll ? handleOffset <= mouseOffset : handleOffset + handleLength >= mouseOffset); + + if (finishedCondition) { + clearTimeout(trackTimeout); + _base.scrollStop(); + trackTimeout = undefined; + scrollActionFinsished(true); + } + else { + trackTimeout = setTimeout(scrollAction, timeoutDelay); + + scrollObj[xy] = (decreaseScroll ? '-=' : '+=') + scrollDistance; + _base.scroll(scrollObj, extendDeep(animationObj, { + duration: scrollDuration + })); + } + isFirstIteration = false; + } + } + }; + if (ctrlKey) + increaseTrackScrollAmount(); + + mouseDownInvertedScale = getHostElementInvertedScale()[xy]; + mouseDownOffset = COMPATIBILITY.page(event)[xy]; + + _scrollbarsHandlesDefineScrollPos = !getPreparedScrollbarsOption(strSnapHandle); + addClass(_bodyElement, _classNameDragging); + addClass(scrollbarVars._track, strActive); + addClass(scrollbarVars._scrollbar, strActive); + + setupResponsiveEventListener(_documentElement, + [_strMouseTouchUpEvent, _strKeyDownEvent, _strKeyUpEvent, _strSelectStartEvent], + [documentMouseTouchUp, documentKeyDown, documentKeyUp, documentOnSelectStart]); + + scrollAction(); + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + } + function onTrackMouseTouchEnter(event) { + //make sure both scrollbars will stay visible if one scrollbar is hovered if autoHide is "scroll" or "move". + _scrollbarsHandleHovered = true; + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(true); + } + function onTrackMouseTouchLeave(event) { + _scrollbarsHandleHovered = false; + if (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove) + refreshScrollbarsAutoHide(false); + } + function onScrollbarMouseTouchDown(event) { + COMPATIBILITY.stpP(event); + } + + addDestroyEventListener(scrollbarVars._handle, + _strMouseTouchDownEvent, + onHandleMouseTouchDown); + addDestroyEventListener(scrollbarVars._track, + [_strMouseTouchDownEvent, _strMouseTouchEnter, _strMouseTouchLeave], + [onTrackMouseTouchDown, onTrackMouseTouchEnter, onTrackMouseTouchLeave]); + addDestroyEventListener(scrollbarVars._scrollbar, + _strMouseTouchDownEvent, + onScrollbarMouseTouchDown); + + if (_supportTransition) { + addDestroyEventListener(scrollbarVars._scrollbar, _strTransitionEndEvent, function (event) { + if (event.target !== scrollbarVars._scrollbar[0]) + return; + refreshScrollbarHandleLength(isHorizontal); + refreshScrollbarHandleOffset(isHorizontal); + }); + } + } + + /** + * Shows or hides the given scrollbar and applied a class name which indicates if the scrollbar is scrollable or not. + * @param isHorizontal True if the horizontal scrollbar is the target, false if the vertical scrollbar is the target. + * @param shallBeVisible True if the scrollbar shall be shown, false if hidden. + * @param canScroll True if the scrollbar is scrollable, false otherwise. + */ + function refreshScrollbarAppearance(isHorizontal, shallBeVisible, canScroll) { + var scrollbarClassName = isHorizontal ? _classNameHostScrollbarHorizontalHidden : _classNameHostScrollbarVerticalHidden; + var scrollbarElement = isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement; + + if (shallBeVisible) + removeClass(_hostElement, scrollbarClassName); + else + addClass(_hostElement, scrollbarClassName); + + if (canScroll) + removeClass(scrollbarElement, _classNameScrollbarUnusable); + else + addClass(scrollbarElement, _classNameScrollbarUnusable); + } + + /** + * Autoshows / autohides both scrollbars with. + * @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. + * @param delayfree True if the scrollbars shall be hidden without a delay, false or undefined otherwise. + */ + function refreshScrollbarsAutoHide(shallBeVisible, delayfree) { + clearTimeout(_scrollbarsAutoHideTimeoutId); + if (shallBeVisible) { + //if(_hasOverflowCache.x && _hideOverflowCache.xs) + removeClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); + //if(_hasOverflowCache.y && _hideOverflowCache.ys) + removeClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); + } + else { + var anyActive; + var strActive = 'active'; + var hide = function () { + if (!_scrollbarsHandleHovered && !_destroyed) { + anyActive = _scrollbarHorizontalHandleElement.hasClass(strActive) || _scrollbarVerticalHandleElement.hasClass(strActive); + if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) + addClass(_scrollbarHorizontalElement, _classNameScrollbarAutoHidden); + if (!anyActive && (_scrollbarsAutoHideScroll || _scrollbarsAutoHideMove || _scrollbarsAutoHideLeave)) + addClass(_scrollbarVerticalElement, _classNameScrollbarAutoHidden); + } + }; + if (_scrollbarsAutoHideDelay > 0 && delayfree !== true) + _scrollbarsAutoHideTimeoutId = setTimeout(hide, _scrollbarsAutoHideDelay); + else + hide(); + } + } + + /** + * Refreshes the handle length of the given scrollbar. + * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. + */ + function refreshScrollbarHandleLength(isHorizontal) { + var handleCSS = {}; + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbarVarsInfo = scrollbarVars._info; + var digit = 1000000; + //get and apply intended handle length + var handleRatio = MATH.min(1, (_hostSizeCache[scrollbarVars._w_h] - (_paddingAbsoluteCache ? (isHorizontal ? _paddingX : _paddingY) : 0)) / _contentScrollSizeCache[scrollbarVars._w_h]); + handleCSS[scrollbarVars._width_height] = (MATH.floor(handleRatio * 100 * digit) / digit) + '%'; //the last * digit / digit is for flooring to the 4th digit + + if (!nativeOverlayScrollbarsAreActive()) + scrollbarVars._handle.css(handleCSS); + + //measure the handle length to respect min & max length + scrollbarVarsInfo._handleLength = scrollbarVars._handle[0]['offset' + scrollbarVars._Width_Height]; + scrollbarVarsInfo._handleLengthRatio = handleRatio; + } + + /** + * Refreshes the handle offset of the given scrollbar. + * @param isHorizontal True if the horizontal scrollbar handle shall be refreshed, false if the vertical one shall be refreshed. + * @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) + */ + function refreshScrollbarHandleOffset(isHorizontal, scrollOrTransition) { + var transition = type(scrollOrTransition) == TYPES.b; + var transitionDuration = 250; + var isRTLisHorizontal = _isRTL && isHorizontal; + var scrollbarVars = getScrollbarVars(isHorizontal); + var scrollbarVarsInfo = scrollbarVars._info; + var strTranslateBrace = 'translate('; + var strTransform = VENDORS._cssProperty('transform'); + var strTransition = VENDORS._cssProperty('transition'); + var nativeScroll = isHorizontal ? _viewportElement[_strScrollLeft]() : _viewportElement[_strScrollTop](); + var currentScroll = scrollOrTransition === undefined || transition ? nativeScroll : scrollOrTransition; + + //measure the handle length to respect min & max length + var handleLength = scrollbarVarsInfo._handleLength; + var trackLength = scrollbarVars._track[0]['offset' + scrollbarVars._Width_Height]; + var handleTrackDiff = trackLength - handleLength; + var handleCSS = {}; + var transformOffset; + var translateValue; + + //DONT use the variable '_contentScrollSizeCache[scrollbarVars._w_h]' instead of '_viewportElement[0]['scroll' + scrollbarVars._Width_Height]' + // because its a bit behind during the small delay when content size updates + //(delay = mutationObserverContentLag, if its 0 then this var could be used) + var maxScroll = (_viewportElementNative[_strScroll + scrollbarVars._Width_Height] - _viewportElementNative['client' + scrollbarVars._Width_Height]) * (_rtlScrollBehavior.n && isRTLisHorizontal ? -1 : 1); //* -1 if rtl scroll max is negative + var getScrollRatio = function (base) { + return isNaN(base / maxScroll) ? 0 : MATH.max(0, MATH.min(1, base / maxScroll)); + }; + var getHandleOffset = function (scrollRatio) { + var offset = handleTrackDiff * scrollRatio; + offset = isNaN(offset) ? 0 : offset; + offset = (isRTLisHorizontal && !_rtlScrollBehavior.i) ? (trackLength - handleLength - offset) : offset; + offset = MATH.max(0, offset); + return offset; + }; + var scrollRatio = getScrollRatio(nativeScroll); + var unsnappedScrollRatio = getScrollRatio(currentScroll); + var handleOffset = getHandleOffset(unsnappedScrollRatio); + var snappedHandleOffset = getHandleOffset(scrollRatio); + + scrollbarVarsInfo._maxScroll = maxScroll; + scrollbarVarsInfo._currentScroll = nativeScroll; + scrollbarVarsInfo._currentScrollRatio = scrollRatio; + + if (_supportTransform) { + transformOffset = isRTLisHorizontal ? -(trackLength - handleLength - handleOffset) : handleOffset; //in px + //transformOffset = (transformOffset / trackLength * 100) * (trackLength / handleLength); //in % + translateValue = isHorizontal ? strTranslateBrace + transformOffset + 'px, 0)' : strTranslateBrace + '0, ' + transformOffset + 'px)'; + + handleCSS[strTransform] = translateValue; + + //apply or clear up transition + if (_supportTransition) + handleCSS[strTransition] = transition && MATH.abs(handleOffset - scrollbarVarsInfo._handleOffset) > 1 ? getCSSTransitionString(scrollbarVars._handle) + ', ' + (strTransform + _strSpace + transitionDuration + 'ms') : _strEmpty; + } + else + handleCSS[scrollbarVars._left_top] = handleOffset; + + + //only apply css if offset has changed and overflow exists. + if (!nativeOverlayScrollbarsAreActive()) { + scrollbarVars._handle.css(handleCSS); + + //clear up transition + if (_supportTransform && _supportTransition && transition) { + scrollbarVars._handle.one(_strTransitionEndEvent, function () { + if (!_destroyed) + scrollbarVars._handle.css(strTransition, _strEmpty); + }); + } + } + + scrollbarVarsInfo._handleOffset = handleOffset; + scrollbarVarsInfo._snappedHandleOffset = snappedHandleOffset; + scrollbarVarsInfo._trackLength = trackLength; + } + + /** + * Refreshes the interactivity of the given scrollbar element. + * @param isTrack True if the track element is the target, false if the handle element is the target. + * @param value True for interactivity false for no interactivity. + */ + function refreshScrollbarsInteractive(isTrack, value) { + var action = value ? 'removeClass' : 'addClass'; + var element1 = isTrack ? _scrollbarHorizontalTrackElement : _scrollbarHorizontalHandleElement; + var element2 = isTrack ? _scrollbarVerticalTrackElement : _scrollbarVerticalHandleElement; + var className = isTrack ? _classNameScrollbarTrackOff : _classNameScrollbarHandleOff; + + element1[action](className); + element2[action](className); + } + + /** + * Returns a object which is used for fast access for specific variables. + * @param isHorizontal True if the horizontal scrollbar vars shall be accessed, false if the vertical scrollbar vars shall be accessed. + * @returns {{wh: string, WH: string, lt: string, _wh: string, _lt: string, t: *, h: *, c: {}, s: *}} + */ + function getScrollbarVars(isHorizontal) { + return { + _width_height: isHorizontal ? _strWidth : _strHeight, + _Width_Height: isHorizontal ? 'Width' : 'Height', + _left_top: isHorizontal ? _strLeft : _strTop, + _Left_Top: isHorizontal ? 'Left' : 'Top', + _x_y: isHorizontal ? _strX : _strY, + _X_Y: isHorizontal ? 'X' : 'Y', + _w_h: isHorizontal ? 'w' : 'h', + _l_t: isHorizontal ? 'l' : 't', + _track: isHorizontal ? _scrollbarHorizontalTrackElement : _scrollbarVerticalTrackElement, + _handle: isHorizontal ? _scrollbarHorizontalHandleElement : _scrollbarVerticalHandleElement, + _scrollbar: isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement, + _info: isHorizontal ? _scrollHorizontalInfo : _scrollVerticalInfo + }; + } + + + //==== Scrollbar Corner ====// + + /** + * Builds or destroys the scrollbar corner DOM element. + * @param destroy Indicates whether the DOM shall be build or destroyed. + */ + function setupScrollbarCornerDOM(destroy) { + _scrollbarCornerElement = _scrollbarCornerElement || selectOrGenerateDivByClass(_classNameScrollbarCorner, true); + + if (!destroy) { + if (!_domExists) { + _hostElement.append(_scrollbarCornerElement); + } + } + else { + if (_domExists && _initialized) { + removeClass(_scrollbarCornerElement.removeAttr(LEXICON.s), _classNamesDynamicDestroy); + } + else { + remove(_scrollbarCornerElement); + } + } + } + + /** + * Initializes all scrollbar corner interactivity events. + */ + function setupScrollbarCornerEvents() { + var insideIFrame = _windowElementNative.top !== _windowElementNative; + var mouseDownPosition = {}; + var mouseDownSize = {}; + var mouseDownInvertedScale = {}; + var reconnectMutationObserver; + + function documentDragMove(event) { + if (onMouseTouchDownContinue(event)) { + var pageOffset = getCoordinates(event); + var hostElementCSS = {}; + if (_resizeHorizontal || _resizeBoth) + hostElementCSS[_strWidth] = (mouseDownSize.w + (pageOffset.x - mouseDownPosition.x) * mouseDownInvertedScale.x); + if (_resizeVertical || _resizeBoth) + hostElementCSS[_strHeight] = (mouseDownSize.h + (pageOffset.y - mouseDownPosition.y) * mouseDownInvertedScale.y); + _hostElement.css(hostElementCSS); + COMPATIBILITY.stpP(event); + } + else { + documentMouseTouchUp(event); + } + } + function documentMouseTouchUp(event) { + var eventIsTrusted = event !== undefined; + + setupResponsiveEventListener(_documentElement, + [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], + [documentOnSelectStart, documentDragMove, documentMouseTouchUp], + true); + + removeClass(_bodyElement, _classNameDragging); + if (_scrollbarCornerElement.releaseCapture) + _scrollbarCornerElement.releaseCapture(); + + if (eventIsTrusted) { + if (reconnectMutationObserver) + connectMutationObservers(); + _base.update(_strAuto); + } + reconnectMutationObserver = false; + } + function onMouseTouchDownContinue(event) { + var originalEvent = event.originalEvent || event; + var isTouchEvent = originalEvent.touches !== undefined; + return _sleeping || _destroyed ? false : COMPATIBILITY.mBtn(event) === 1 || isTouchEvent; + } + function getCoordinates(event) { + return _msieVersion && insideIFrame ? { x: event.screenX, y: event.screenY } : COMPATIBILITY.page(event); + } + + addDestroyEventListener(_scrollbarCornerElement, _strMouseTouchDownEvent, function (event) { + if (onMouseTouchDownContinue(event) && !_resizeNone) { + if (_mutationObserversConnected) { + reconnectMutationObserver = true; + disconnectMutationObservers(); + } + + mouseDownPosition = getCoordinates(event); + + mouseDownSize.w = _hostElementNative[LEXICON.oW] - (!_isBorderBox ? _paddingX : 0); + mouseDownSize.h = _hostElementNative[LEXICON.oH] - (!_isBorderBox ? _paddingY : 0); + mouseDownInvertedScale = getHostElementInvertedScale(); + + setupResponsiveEventListener(_documentElement, + [_strSelectStartEvent, _strMouseTouchMoveEvent, _strMouseTouchUpEvent], + [documentOnSelectStart, documentDragMove, documentMouseTouchUp]); + + addClass(_bodyElement, _classNameDragging); + if (_scrollbarCornerElement.setCapture) + _scrollbarCornerElement.setCapture(); + + COMPATIBILITY.prvD(event); + COMPATIBILITY.stpP(event); + } + }); + } + + + //==== Utils ====// + + /** + * Calls the callback with the given name. The Context of this callback is always _base (this). + * @param name The name of the target which shall be called. + * @param args The args with which the callback shall be called. + */ + function dispatchCallback(name, args) { + if (_initialized) { + var callback = _currentPreparedOptions.callbacks[name]; + var extensionOnName = name; + var ext; + + if (extensionOnName.substr(0, 2) === 'on') + extensionOnName = extensionOnName.substr(2, 1).toLowerCase() + extensionOnName.substr(3); + + if (type(callback) == TYPES.f) + callback.call(_base, args); + + each(_extensions, function () { + ext = this; + if (type(ext.on) == TYPES.f) + ext.on(extensionOnName, args); + }); + } + else if (!_destroyed) + _callbacksInitQeueue.push({ n: name, a: args }); + } + + /** + * Sets the "top, right, bottom, left" properties, with a given prefix, of the given css object. + * @param targetCSSObject The css object to which the values shall be applied. + * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix) + * @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]. + * If this argument is undefined the value '' (empty string) will be applied to all properties. + */ + function setTopRightBottomLeft(targetCSSObject, prefix, values) { + if (values === undefined) + values = [_strEmpty, _strEmpty, _strEmpty, _strEmpty]; + + targetCSSObject[prefix + _strTop] = values[0]; + targetCSSObject[prefix + _strRight] = values[1]; + targetCSSObject[prefix + _strBottom] = values[2]; + targetCSSObject[prefix + _strLeft] = values[3]; + } + + /** + * Returns the computed CSS transition string from the given element. + * @param element The element from which the transition string shall be returned. + * @returns {string} The CSS transition string from the given element. + */ + function getCSSTransitionString(element) { + var transitionStr = VENDORS._cssProperty('transition'); + var assembledValue = element.css(transitionStr); + if (assembledValue) + return assembledValue; + var regExpString = '\\s*(' + '([^,(]+(\\(.+?\\))?)+' + ')[\\s,]*'; + var regExpMain = new RegExp(regExpString); + var regExpValidate = new RegExp('^(' + regExpString + ')+$'); + var properties = 'property duration timing-function delay'.split(' '); + var result = []; + var strResult; + var valueArray; + var i = 0; + var j; + var splitCssStyleByComma = function (str) { + strResult = []; + if (!str.match(regExpValidate)) + return str; + while (str.match(regExpMain)) { + strResult.push(RegExp.$1); + str = str.replace(regExpMain, _strEmpty); + } + + return strResult; + }; + for (; i < properties[LEXICON.l]; i++) { + valueArray = splitCssStyleByComma(element.css(transitionStr + '-' + properties[i])); + for (j = 0; j < valueArray[LEXICON.l]; j++) + result[j] = (result[j] ? result[j] + _strSpace : _strEmpty) + valueArray[j]; + } + return result.join(', '); + } + + /** + * Calculates the host-elements inverted scale. (invertedScale = 1 / scale) + * @returns {{x: number, y: number}} The scale of the host-element. + */ + function getHostElementInvertedScale() { + var rect = _paddingElementNative[LEXICON.bCR](); + return { + x: _supportTransform ? 1 / (MATH.round(rect.width) / _paddingElementNative[LEXICON.oW]) || 1 : 1, + y: _supportTransform ? 1 / (MATH.round(rect.height) / _paddingElementNative[LEXICON.oH]) || 1 : 1 + }; + } + + /** + * Checks whether the given object is a HTMLElement. + * @param o The object which shall be checked. + * @returns {boolean} True the given object is a HTMLElement, false otherwise. + */ + function isHTMLElement(o) { + var strOwnerDocument = 'ownerDocument'; + var strHTMLElement = 'HTMLElement'; + var wnd = o && o[strOwnerDocument] ? (o[strOwnerDocument].parentWindow || window) : window; + return ( + typeof wnd[strHTMLElement] == TYPES.o ? o instanceof wnd[strHTMLElement] : //DOM2 + o && typeof o == TYPES.o && o !== null && o.nodeType === 1 && typeof o.nodeName == TYPES.s + ); + } + + /** + * Compares 2 arrays and returns the differences between them as a array. + * @param a1 The first array which shall be compared. + * @param a2 The second array which shall be compared. + * @returns {Array} The differences between the two arrays. + */ + function getArrayDifferences(a1, a2) { + var a = []; + var diff = []; + var i; + var k; + for (i = 0; i < a1.length; i++) + a[a1[i]] = true; + for (i = 0; i < a2.length; i++) { + if (a[a2[i]]) + delete a[a2[i]]; + else + a[a2[i]] = true; + } + for (k in a) + diff.push(k); + return diff; + } + + /** + * Returns Zero or the number to which the value can be parsed. + * @param value The value which shall be parsed. + * @param toFloat Indicates whether the number shall be parsed to a float. + */ + function parseToZeroOrNumber(value, toFloat) { + var num = toFloat ? parseFloat(value) : parseInt(value, 10); + return isNaN(num) ? 0 : num; + } + + /** + * Gets several information of the textarea and returns them as a object or undefined if the browser doesn't support it. + * @returns {{cursorRow: Number, cursorCol, rows: Number, cols: number, wRow: number, pos: number, max : number}} or undefined if not supported. + */ + function getTextareaInfo() { + //read needed values + var textareaCursorPosition = _targetElementNative.selectionStart; + if (textareaCursorPosition === undefined) + return; + + var textareaValue = _targetElement.val(); + var textareaLength = textareaValue[LEXICON.l]; + var textareaRowSplit = textareaValue.split('\n'); + var textareaLastRow = textareaRowSplit[LEXICON.l]; + var textareaCurrentCursorRowSplit = textareaValue.substr(0, textareaCursorPosition).split('\n'); + var widestRow = 0; + var textareaLastCol = 0; + var cursorRow = textareaCurrentCursorRowSplit[LEXICON.l]; + var cursorCol = textareaCurrentCursorRowSplit[textareaCurrentCursorRowSplit[LEXICON.l] - 1][LEXICON.l]; + var rowCols; + var i; + + //get widest Row and the last column of the textarea + for (i = 0; i < textareaRowSplit[LEXICON.l]; i++) { + rowCols = textareaRowSplit[i][LEXICON.l]; + if (rowCols > textareaLastCol) { + widestRow = i + 1; + textareaLastCol = rowCols; + } + } + + return { + _cursorRow: cursorRow, //cursorRow + _cursorColumn: cursorCol, //cursorCol + _rows: textareaLastRow, //rows + _columns: textareaLastCol, //cols + _widestRow: widestRow, //wRow + _cursorPosition: textareaCursorPosition, //pos + _cursorMax: textareaLength //max + }; + } + + /** + * Determines whether native overlay scrollbars are active. + * @returns {boolean} True if native overlay scrollbars are active, false otherwise. + */ + function nativeOverlayScrollbarsAreActive() { + return (_ignoreOverlayScrollbarHidingCache && (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y)); + } + + /** + * Gets the element which is used to measure the content size. + * @returns {*} TextareaCover if target element is textarea else the ContentElement. + */ + function getContentMeasureElement() { + return _isTextarea ? _textareaCoverElement[0] : _contentElementNative; + } + + /** + * Generates a string which represents a HTML div with the given classes or attributes. + * @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".) + * @param content The content of the div as string. + * @returns {string} The concated string which represents a HTML div and its content. + */ + function generateDiv(classesOrAttrs, content) { + return '
' + + (content || _strEmpty) + + '
'; + } + + /** + * Selects or generates a div with the given class attribute. + * @param className The class names (divided by spaces) of the div which shall be selected or generated. + * @param selectParentOrOnlyChildren The parent element from which of the element shall be selected. (if undefined or boolean its hostElement) + * If its a boolean it decides whether only the children of the host element shall be selected. + * @returns {*} The generated or selected element. + */ + function selectOrGenerateDivByClass(className, selectParentOrOnlyChildren) { + var onlyChildren = type(selectParentOrOnlyChildren) == TYPES.b; + var selectParent = onlyChildren ? _hostElement : (selectParentOrOnlyChildren || _hostElement); + + return (_domExists && !selectParent[LEXICON.l]) + ? null + : _domExists + ? selectParent[onlyChildren ? 'children' : 'find'](_strDot + className.replace(/\s/g, _strDot)).eq(0) + : FRAMEWORK(generateDiv(className)) + } + + /** + * Gets the value of the given property from the given object. + * @param obj The object from which the property value shall be got. + * @param path The property of which the value shall be got. + * @returns {*} Returns the value of the searched property or undefined of the property wasn't found. + */ + function getObjectPropVal(obj, path) { + var splits = path.split(_strDot); + var i = 0; + var val; + for (; i < splits.length; i++) { + if (!obj[LEXICON.hOP](splits[i])) + return; + val = obj[splits[i]]; + if (i < splits.length && type(val) == TYPES.o) + obj = val; + } + return val; + } + + /** + * Sets the value of the given property from the given object. + * @param obj The object from which the property value shall be set. + * @param path The property of which the value shall be set. + * @param val The value of the property which shall be set. + */ + function setObjectPropVal(obj, path, val) { + var splits = path.split(_strDot); + var splitsLength = splits.length; + var i = 0; + var extendObj = {}; + var extendObjRoot = extendObj; + for (; i < splitsLength; i++) + extendObj = extendObj[splits[i]] = i + 1 < splitsLength ? {} : val; + FRAMEWORK.extend(obj, extendObjRoot, true); + } + + + //==== Utils Cache ====// + + /** + * Compares two values or objects and returns true if they aren't equal. + * @param current The first value or object which shall be compared. + * @param cache The second value or object which shall be compared. + * @param force If true the returned value is always true. + * @returns {boolean} True if both values or objects aren't equal or force is true, false otherwise. + */ + function checkCache(current, cache, force) { + if (force) + return force; + if (type(current) == TYPES.o && type(cache) == TYPES.o) { + for (var prop in current) { + if (prop !== 'c') { + if (current[LEXICON.hOP](prop) && cache[LEXICON.hOP](prop)) { + if (checkCache(current[prop], cache[prop])) + return true; + } + else { + return true; + } + } + } + } + else { + return current !== cache; + } + return false; + } + + + //==== Shortcuts ====// + + /** + * jQuery extend method shortcut with a appended "true" as first argument. + */ + function extendDeep() { + return FRAMEWORK.extend.apply(this, [true].concat([].slice.call(arguments))); + } + + /** + * jQuery addClass method shortcut. + */ + function addClass(el, classes) { + return _frameworkProto.addClass.call(el, classes); + } + + /** + * jQuery removeClass method shortcut. + */ + function removeClass(el, classes) { + return _frameworkProto.removeClass.call(el, classes); + } + + /** + * jQuery remove method shortcut. + */ + function remove(el) { + return _frameworkProto.remove.call(el); + } + + /** + * Finds the first child element with the given selector of the given element. + * @param el The root element from which the selector shall be valid. + * @param selector The selector of the searched element. + * @returns {*} The first element which is a child of the given element and matches the givens selector. + */ + function findFirst(el, selector) { + return _frameworkProto.find.call(el, selector).eq(0); + } + + + //==== API ====// + + /** + * 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. + * This behavior can be reset by calling the update method. + */ + _base.sleep = function () { + _sleeping = true; + }; + + /** + * Updates the plugin and DOM to the current options. + * This method should only be called if a update is 100% required. + * @param force True if every property shall be updated and the cache shall be ignored. + * !INTERNAL USAGE! : force can be a string "auto", "sync" or "zoom" too + * 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. + * 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. + * if "zoom" then a update takes place where it's assumed that content and host size changed + * @returns {boolean|undefined} + * If force is "sync" then a boolean is returned which indicates whether a update was needed due to pending changes. + * If force is "auto" then a boolean is returned whether a update was needed due to attribute or size changes. + * undefined otherwise. + */ + _base.update = function (force) { + if (_destroyed) + return; + + var attrsChanged; + var contentSizeC; + var isString = type(force) == TYPES.s; + var imgElementSelector = 'img'; + var imgElementLoadEvent = 'load'; + var doUpdateAuto; + var mutHost; + var mutContent; + + if (isString) { + if (force === _strAuto) { + attrsChanged = meaningfulAttrsChanged(); + contentSizeC = updateAutoContentSizeChanged(); + doUpdateAuto = attrsChanged || contentSizeC; + if (doUpdateAuto) { + update({ + _contentSizeChanged: contentSizeC, + _changedOptions: _initialized ? undefined : _currentPreparedOptions + }); + } + } + else if (force === _strSync) { + if (_mutationObserversConnected) { + mutHost = _mutationObserverHostCallback(_mutationObserverHost.takeRecords()); + mutContent = _mutationObserverContentCallback(_mutationObserverContent.takeRecords()); + } + else { + mutHost = _base.update(_strAuto); + } + } + else if (force === 'zoom') { + update({ + _hostSizeChanged: true, + _contentSizeChanged: true + }); + } + } + else { + force = _sleeping || force; + _sleeping = false; + if (!_base.update(_strSync) || force) + update({ _force: force }); + } + if (!_isTextarea) { + _contentElement.find(imgElementSelector).each(function (i, el) { + var index = COMPATIBILITY.inA(el, _imgs); + if (index === -1) + FRAMEWORK(el).off(imgElementLoadEvent, imgOnLoad).on(imgElementLoadEvent, imgOnLoad); + }); + } + return doUpdateAuto || mutHost || mutContent; + }; + + /** + Gets or sets the current options. The update method will be called automatically if new options were set. + * @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. + * @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. + * @returns {*} + */ + _base.options = function (newOptions, value) { + var option = {}; + var changedOps; + + //return current options if newOptions are undefined or empty + if (FRAMEWORK.isEmptyObject(newOptions) || !FRAMEWORK.isPlainObject(newOptions)) { + if (type(newOptions) == TYPES.s) { + if (arguments.length > 1) { + setObjectPropVal(option, newOptions, value); + changedOps = setOptions(option); + } + else + return getObjectPropVal(_currentOptions, newOptions); + } + else + return _currentOptions; + } + else { + changedOps = setOptions(newOptions); + } + + if (!FRAMEWORK.isEmptyObject(changedOps)) { + update({ _changedOptions: changedOps }); + } + }; + + /** + * Restore the DOM, disconnects all observers, remove all resize observers and put the instance to sleep. + */ + _base.destroy = function () { + if (_destroyed) + return; + + //remove this instance from auto update loop + autoUpdateLoop.remove(_base); + + //disconnect all mutation observers + disconnectMutationObservers(); + + //remove all resize observers + setupResizeObserver(_sizeObserverElement); + setupResizeObserver(_sizeAutoObserverElement); + + //remove all extensions + for (var extName in _extensions) + _base.removeExt(extName); + + //remove all 'destroy' events + while (_destroyEvents[LEXICON.l] > 0) + _destroyEvents.pop()(); + + //remove all events from host element + setupHostMouseTouchEvents(true); + + //remove all helper / detection elements + if (_contentGlueElement) + remove(_contentGlueElement); + if (_contentArrangeElement) + remove(_contentArrangeElement); + if (_sizeAutoObserverAdded) + remove(_sizeAutoObserverElement); + + //remove all generated DOM + setupScrollbarsDOM(true); + setupScrollbarCornerDOM(true); + setupStructureDOM(true); + + //remove all generated image load events + for (var i = 0; i < _imgs[LEXICON.l]; i++) + FRAMEWORK(_imgs[i]).off('load', imgOnLoad); + _imgs = undefined; + + _destroyed = true; + _sleeping = true; + + //remove this instance from the instances list + INSTANCES(pluginTargetElement, 0); + dispatchCallback('onDestroyed'); + + //remove all properties and methods + //for (var property in _base) + // delete _base[property]; + //_base = undefined; + }; + + /** + * Scrolls to a given position or element. + * @param coordinates + * 1. Can be "coordinates" which looks like: + * { x : ?, y : ? } OR Object with x and y properties + * { left : ?, top : ? } OR Object with left and top properties + * { l : ?, t : ? } OR Object with l and t properties + * [ ?, ? ] OR Array where the first two element are the coordinates (first is x, second is y) + * ? A single value which stays for both axis + * A value can be a number, a string or a calculation. + * + * Operators: + * [NONE] The current scroll will be overwritten by the value. + * '+=' The value will be added to the current scroll offset + * '-=' The value will be subtracted from the current scroll offset + * '*=' The current scroll wil be multiplicated by the value. + * '/=' The current scroll wil be divided by the value. + * + * Units: + * [NONE] The value is the final scroll amount. final = (value * 1) + * 'px' Same as none + * '%' The value is dependent on the current scroll value. final = ((currentScrollValue / 100) * value) + * 'vw' The value is multiplicated by the viewport width. final = (value * viewportWidth) + * 'vh' The value is multiplicated by the viewport height. final = (value * viewportHeight) + * + * example final values: + * 200, '200px', '50%', '1vw', '1vh', '+=200', '/=1vw', '*=2px', '-=5vh', '+=33%', '+= 50% - 2px', '-= 1vw - 50%' + * + * 2. Can be a HTML or jQuery element: + * The final scroll offset is the offset (without margin) of the given HTML / jQuery element. + * + * 3. Can be a object with a HTML or jQuery element with additional settings: + * { + * el : [HTMLElement, jQuery element], MUST be specified, else this object isn't valid. + * scroll : [string, array, object], Default value is 'always'. + * block : [string, array, object], Default value is 'begin'. + * margin : [number, boolean, array, object] Default value is false. + * } + * + * Possible scroll settings are: + * 'always' Scrolls always. + * 'ifneeded' Scrolls only if the element isnt fully in view. + * 'never' Scrolls never. + * + * Possible block settings are: + * 'begin' Both axis shall be docked to the "begin" edge. - The element will be docked to the top and left edge of the viewport. + * '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.) + * 'center' Both axis shall be docked to "center". - The element will be centered in the viewport. + * 'nearest' The element will be docked to the nearest edge(s). + * + * Possible margin settings are: -- The actual margin of the element wont be affect, this option affects only the final scroll offset. + * [BOOLEAN] If true the css margin of the element will be used, if false no margin will be used. + * [NUMBER] The margin will be used for all edges. + * + * @param duration The duration of the scroll animation, OR a jQuery animation configuration object. + * @param easing The animation easing. + * @param complete The animation complete callback. + * @returns {{ + * position: {x: number, y: number}, + * ratio: {x: number, y: number}, + * max: {x: number, y: number}, + * handleOffset: {x: number, y: number}, + * handleLength: {x: number, y: number}, + * handleLengthRatio: {x: number, y: number}, t + * rackLength: {x: number, y: number}, + * isRTL: boolean, + * isRTLNormalized: boolean + * }} + */ + _base.scroll = function (coordinates, duration, easing, complete) { + if (arguments.length === 0 || coordinates === undefined) { + var infoX = _scrollHorizontalInfo; + var infoY = _scrollVerticalInfo; + var normalizeInvert = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.i; + var normalizeNegate = _normalizeRTLCache && _isRTL && _rtlScrollBehavior.n; + var scrollX = infoX._currentScroll; + var scrollXRatio = infoX._currentScrollRatio; + var maxScrollX = infoX._maxScroll; + scrollXRatio = normalizeInvert ? 1 - scrollXRatio : scrollXRatio; + scrollX = normalizeInvert ? maxScrollX - scrollX : scrollX; + scrollX *= normalizeNegate ? -1 : 1; + maxScrollX *= normalizeNegate ? -1 : 1; + + return { + position: { + x: scrollX, + y: infoY._currentScroll + }, + ratio: { + x: scrollXRatio, + y: infoY._currentScrollRatio + }, + max: { + x: maxScrollX, + y: infoY._maxScroll + }, + handleOffset: { + x: infoX._handleOffset, + y: infoY._handleOffset + }, + handleLength: { + x: infoX._handleLength, + y: infoY._handleLength + }, + handleLengthRatio: { + x: infoX._handleLengthRatio, + y: infoY._handleLengthRatio + }, + trackLength: { + x: infoX._trackLength, + y: infoY._trackLength + }, + snappedHandleOffset: { + x: infoX._snappedHandleOffset, + y: infoY._snappedHandleOffset + }, + isRTL: _isRTL, + isRTLNormalized: _normalizeRTLCache + }; + } + + _base.update(_strSync); + + var normalizeRTL = _normalizeRTLCache; + var coordinatesXAxisProps = [_strX, _strLeft, 'l']; + var coordinatesYAxisProps = [_strY, _strTop, 't']; + var coordinatesOperators = ['+=', '-=', '*=', '/=']; + var durationIsObject = type(duration) == TYPES.o; + var completeCallback = durationIsObject ? duration.complete : complete; + var i; + var finalScroll = {}; + var specialEasing = {}; + var doScrollLeft; + var doScrollTop; + var animationOptions; + var strEnd = 'end'; + var strBegin = 'begin'; + var strCenter = 'center'; + var strNearest = 'nearest'; + var strAlways = 'always'; + var strNever = 'never'; + var strIfNeeded = 'ifneeded'; + var strLength = LEXICON.l; + var settingsAxis; + var settingsScroll; + var settingsBlock; + var settingsMargin; + var finalElement; + var elementObjSettingsAxisValues = [_strX, _strY, 'xy', 'yx']; + var elementObjSettingsBlockValues = [strBegin, strEnd, strCenter, strNearest]; + var elementObjSettingsScrollValues = [strAlways, strNever, strIfNeeded]; + var coordinatesIsElementObj = coordinates[LEXICON.hOP]('el'); + var possibleElement = coordinatesIsElementObj ? coordinates.el : coordinates; + var possibleElementIsJQuery = possibleElement instanceof FRAMEWORK || JQUERY ? possibleElement instanceof JQUERY : false; + var possibleElementIsHTMLElement = possibleElementIsJQuery ? false : isHTMLElement(possibleElement); + var updateScrollbarInfos = function () { + if (doScrollLeft) + refreshScrollbarHandleOffset(true); + if (doScrollTop) + refreshScrollbarHandleOffset(false); + }; + var proxyCompleteCallback = type(completeCallback) != TYPES.f ? undefined : function () { + updateScrollbarInfos(); + completeCallback(); + }; + function checkSettingsStringValue(currValue, allowedValues) { + for (i = 0; i < allowedValues[strLength]; i++) { + if (currValue === allowedValues[i]) + return true; + } + return false; + } + function getRawScroll(isX, coordinates) { + var coordinateProps = isX ? coordinatesXAxisProps : coordinatesYAxisProps; + coordinates = type(coordinates) == TYPES.s || type(coordinates) == TYPES.n ? [coordinates, coordinates] : coordinates; + + if (type(coordinates) == TYPES.a) + return isX ? coordinates[0] : coordinates[1]; + else if (type(coordinates) == TYPES.o) { + //decides RTL normalization "hack" with .n + //normalizeRTL = type(coordinates.n) == TYPES.b ? coordinates.n : normalizeRTL; + for (i = 0; i < coordinateProps[strLength]; i++) + if (coordinateProps[i] in coordinates) + return coordinates[coordinateProps[i]]; + } + } + function getFinalScroll(isX, rawScroll) { + var isString = type(rawScroll) == TYPES.s; + var operator; + var amount; + var scrollInfo = isX ? _scrollHorizontalInfo : _scrollVerticalInfo; + var currScroll = scrollInfo._currentScroll; + var maxScroll = scrollInfo._maxScroll; + var mult = ' * '; + var finalValue; + var isRTLisX = _isRTL && isX; + var normalizeShortcuts = isRTLisX && _rtlScrollBehavior.n && !normalizeRTL; + var strReplace = 'replace'; + var evalFunc = eval; + var possibleOperator; + if (isString) { + //check operator + if (rawScroll[strLength] > 2) { + possibleOperator = rawScroll.substr(0, 2); + if (inArray(possibleOperator, coordinatesOperators) > -1) + operator = possibleOperator; + } + + //calculate units and shortcuts + rawScroll = operator ? rawScroll.substr(2) : rawScroll; + rawScroll = rawScroll + [strReplace](/min/g, 0) //'min' = 0% + [strReplace](//g, (normalizeShortcuts ? '-' : _strEmpty) + _strHundredPercent) //'>' = 100% + [strReplace](/px/g, _strEmpty) + [strReplace](/%/g, mult + (maxScroll * (isRTLisX && _rtlScrollBehavior.n ? -1 : 1) / 100.0)) + [strReplace](/vw/g, mult + _viewportSize.w) + [strReplace](/vh/g, mult + _viewportSize.h); + amount = parseToZeroOrNumber(isNaN(rawScroll) ? parseToZeroOrNumber(evalFunc(rawScroll), true).toFixed() : rawScroll); + } + else { + amount = rawScroll; + } + + if (amount !== undefined && !isNaN(amount) && type(amount) == TYPES.n) { + var normalizeIsRTLisX = normalizeRTL && isRTLisX; + var operatorCurrScroll = currScroll * (normalizeIsRTLisX && _rtlScrollBehavior.n ? -1 : 1); + var invert = normalizeIsRTLisX && _rtlScrollBehavior.i; + var negate = normalizeIsRTLisX && _rtlScrollBehavior.n; + operatorCurrScroll = invert ? (maxScroll - operatorCurrScroll) : operatorCurrScroll; + switch (operator) { + case '+=': + finalValue = operatorCurrScroll + amount; + break; + case '-=': + finalValue = operatorCurrScroll - amount; + break; + case '*=': + finalValue = operatorCurrScroll * amount; + break; + case '/=': + finalValue = operatorCurrScroll / amount; + break; + default: + finalValue = amount; + break; + } + finalValue = invert ? maxScroll - finalValue : finalValue; + finalValue *= negate ? -1 : 1; + finalValue = isRTLisX && _rtlScrollBehavior.n ? MATH.min(0, MATH.max(maxScroll, finalValue)) : MATH.max(0, MATH.min(maxScroll, finalValue)); + } + return finalValue === currScroll ? undefined : finalValue; + } + function getPerAxisValue(value, valueInternalType, defaultValue, allowedValues) { + var resultDefault = [defaultValue, defaultValue]; + var valueType = type(value); + var valueArrLength; + var valueArrItem; + + //value can be [ string, or array of two strings ] + if (valueType == valueInternalType) { + value = [value, value]; + } + else if (valueType == TYPES.a) { + valueArrLength = value[strLength]; + if (valueArrLength > 2 || valueArrLength < 1) + value = resultDefault; + else { + if (valueArrLength === 1) + value[1] = defaultValue; + for (i = 0; i < valueArrLength; i++) { + valueArrItem = value[i]; + if (type(valueArrItem) != valueInternalType || !checkSettingsStringValue(valueArrItem, allowedValues)) { + value = resultDefault; + break; + } + } + } + } + else if (valueType == TYPES.o) + value = [value[_strX] || defaultValue, value[_strY] || defaultValue]; + else + value = resultDefault; + return { x: value[0], y: value[1] }; + } + function generateMargin(marginTopRightBottomLeftArray) { + var result = []; + var currValue; + var currValueType; + var valueDirections = [_strTop, _strRight, _strBottom, _strLeft]; + for (i = 0; i < marginTopRightBottomLeftArray[strLength]; i++) { + if (i === valueDirections[strLength]) + break; + currValue = marginTopRightBottomLeftArray[i]; + currValueType = type(currValue); + if (currValueType == TYPES.b) + result.push(currValue ? parseToZeroOrNumber(finalElement.css(_strMarginMinus + valueDirections[i])) : 0); + else + result.push(currValueType == TYPES.n ? currValue : 0); + } + return result; + } + + if (possibleElementIsJQuery || possibleElementIsHTMLElement) { + //get settings + var margin = coordinatesIsElementObj ? coordinates.margin : 0; + var axis = coordinatesIsElementObj ? coordinates.axis : 0; + var scroll = coordinatesIsElementObj ? coordinates.scroll : 0; + var block = coordinatesIsElementObj ? coordinates.block : 0; + var marginDefault = [0, 0, 0, 0]; + var marginType = type(margin); + var marginLength; + finalElement = possibleElementIsJQuery ? possibleElement : FRAMEWORK(possibleElement); + + if (finalElement[strLength] > 0) { + //margin can be [ boolean, number, array of 2, array of 4, object ] + if (marginType == TYPES.n || marginType == TYPES.b) + margin = generateMargin([margin, margin, margin, margin]); + else if (marginType == TYPES.a) { + marginLength = margin[strLength]; + if (marginLength === 2) + margin = generateMargin([margin[0], margin[1], margin[0], margin[1]]); + else if (marginLength >= 4) + margin = generateMargin(margin); + else + margin = marginDefault; + } + else if (marginType == TYPES.o) + margin = generateMargin([margin[_strTop], margin[_strRight], margin[_strBottom], margin[_strLeft]]); + else + margin = marginDefault; + + //block = type(block) === TYPES.b ? block ? [ strNearest, strBegin ] : [ strNearest, strEnd ] : block; + settingsAxis = checkSettingsStringValue(axis, elementObjSettingsAxisValues) ? axis : 'xy'; + settingsScroll = getPerAxisValue(scroll, TYPES.s, strAlways, elementObjSettingsScrollValues); + settingsBlock = getPerAxisValue(block, TYPES.s, strBegin, elementObjSettingsBlockValues); + settingsMargin = margin; + + var viewportScroll = { + l: _scrollHorizontalInfo._currentScroll, + t: _scrollVerticalInfo._currentScroll + }; + // use padding element instead of viewport element because padding element has never padding, margin or position applied. + var viewportOffset = _paddingElement.offset(); + + //get coordinates + var elementOffset = finalElement.offset(); + var doNotScroll = { + x: settingsScroll.x == strNever || settingsAxis == _strY, + y: settingsScroll.y == strNever || settingsAxis == _strX + }; + elementOffset[_strTop] -= settingsMargin[0]; + elementOffset[_strLeft] -= settingsMargin[3]; + var elementScrollCoordinates = { + x: MATH.round(elementOffset[_strLeft] - viewportOffset[_strLeft] + viewportScroll.l), + y: MATH.round(elementOffset[_strTop] - viewportOffset[_strTop] + viewportScroll.t) + }; + if (_isRTL) { + if (!_rtlScrollBehavior.n && !_rtlScrollBehavior.i) + elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + viewportScroll.l); + if (_rtlScrollBehavior.n && normalizeRTL) + elementScrollCoordinates.x *= -1; + if (_rtlScrollBehavior.i && normalizeRTL) + elementScrollCoordinates.x = MATH.round(viewportOffset[_strLeft] - elementOffset[_strLeft] + (_scrollHorizontalInfo._maxScroll - viewportScroll.l)); + } + + //measuring is required + if (settingsBlock.x != strBegin || settingsBlock.y != strBegin || settingsScroll.x == strIfNeeded || settingsScroll.y == strIfNeeded || _isRTL) { + var measuringElm = finalElement[0]; + var rawElementSize = _supportTransform ? measuringElm[LEXICON.bCR]() : { + width: measuringElm[LEXICON.oW], + height: measuringElm[LEXICON.oH] + }; + var elementSize = { + w: rawElementSize[_strWidth] + settingsMargin[3] + settingsMargin[1], + h: rawElementSize[_strHeight] + settingsMargin[0] + settingsMargin[2] + }; + var finalizeBlock = function (isX) { + var vars = getScrollbarVars(isX); + var wh = vars._w_h; + var lt = vars._left_top; + var xy = vars._x_y; + var blockIsEnd = settingsBlock[xy] == (isX ? _isRTL ? strBegin : strEnd : strEnd); + var blockIsCenter = settingsBlock[xy] == strCenter; + var blockIsNearest = settingsBlock[xy] == strNearest; + var scrollNever = settingsScroll[xy] == strNever; + var scrollIfNeeded = settingsScroll[xy] == strIfNeeded; + var vpSize = _viewportSize[wh]; + var vpOffset = viewportOffset[lt]; + var elSize = elementSize[wh]; + var elOffset = elementOffset[lt]; + var divide = blockIsCenter ? 2 : 1; + var elementCenterOffset = elOffset + (elSize / 2); + var viewportCenterOffset = vpOffset + (vpSize / 2); + var isInView = + elSize <= vpSize + && elOffset >= vpOffset + && elOffset + elSize <= vpOffset + vpSize; + + if (scrollNever) + doNotScroll[xy] = true; + else if (!doNotScroll[xy]) { + if (blockIsNearest || scrollIfNeeded) { + doNotScroll[xy] = scrollIfNeeded ? isInView : false; + blockIsEnd = elSize < vpSize ? elementCenterOffset > viewportCenterOffset : elementCenterOffset < viewportCenterOffset; + } + elementScrollCoordinates[xy] -= blockIsEnd || blockIsCenter ? ((vpSize / divide) - (elSize / divide)) * (isX && _isRTL && normalizeRTL ? -1 : 1) : 0; + } + }; + finalizeBlock(true); + finalizeBlock(false); + } + + if (doNotScroll.y) + delete elementScrollCoordinates.y; + if (doNotScroll.x) + delete elementScrollCoordinates.x; + + coordinates = elementScrollCoordinates; + } + } + + finalScroll[_strScrollLeft] = getFinalScroll(true, getRawScroll(true, coordinates)); + finalScroll[_strScrollTop] = getFinalScroll(false, getRawScroll(false, coordinates)); + doScrollLeft = finalScroll[_strScrollLeft] !== undefined; + doScrollTop = finalScroll[_strScrollTop] !== undefined; + + if ((doScrollLeft || doScrollTop) && (duration > 0 || durationIsObject)) { + if (durationIsObject) { + duration.complete = proxyCompleteCallback; + _viewportElement.animate(finalScroll, duration); + } + else { + animationOptions = { + duration: duration, + complete: proxyCompleteCallback + }; + if (type(easing) == TYPES.a || FRAMEWORK.isPlainObject(easing)) { + specialEasing[_strScrollLeft] = easing[0] || easing.x; + specialEasing[_strScrollTop] = easing[1] || easing.y; + animationOptions.specialEasing = specialEasing; + } + else { + animationOptions.easing = easing; + } + _viewportElement.animate(finalScroll, animationOptions); + } + } + else { + if (doScrollLeft) + _viewportElement[_strScrollLeft](finalScroll[_strScrollLeft]); + if (doScrollTop) + _viewportElement[_strScrollTop](finalScroll[_strScrollTop]); + updateScrollbarInfos(); + } + }; + + /** + * Stops all scroll animations. + * @returns {*} The current OverlayScrollbars instance (for chaining). + */ + _base.scrollStop = function (param1, param2, param3) { + _viewportElement.stop(param1, param2, param3); + return _base; + }; + + /** + * Returns all relevant elements. + * @param elementName The name of the element which shall be returned. + * @returns {{target: *, host: *, padding: *, viewport: *, content: *, scrollbarHorizontal: {scrollbar: *, track: *, handle: *}, scrollbarVertical: {scrollbar: *, track: *, handle: *}, scrollbarCorner: *} | *} + */ + _base.getElements = function (elementName) { + var obj = { + target: _targetElementNative, + host: _hostElementNative, + padding: _paddingElementNative, + viewport: _viewportElementNative, + content: _contentElementNative, + scrollbarHorizontal: { + scrollbar: _scrollbarHorizontalElement[0], + track: _scrollbarHorizontalTrackElement[0], + handle: _scrollbarHorizontalHandleElement[0] + }, + scrollbarVertical: { + scrollbar: _scrollbarVerticalElement[0], + track: _scrollbarVerticalTrackElement[0], + handle: _scrollbarVerticalHandleElement[0] + }, + scrollbarCorner: _scrollbarCornerElement[0] + }; + return type(elementName) == TYPES.s ? getObjectPropVal(obj, elementName) : obj; + }; + + /** + * Returns a object which describes the current state of this instance. + * @param stateProperty A specific property from the state object which shall be returned. + * @returns {{widthAuto, heightAuto, overflowAmount, hideOverflow, hasOverflow, contentScrollSize, viewportSize, hostSize, autoUpdate} | *} + */ + _base.getState = function (stateProperty) { + function prepare(obj) { + if (!FRAMEWORK.isPlainObject(obj)) + return obj; + var extended = extendDeep({}, obj); + var changePropertyName = function (from, to) { + if (extended[LEXICON.hOP](from)) { + extended[to] = extended[from]; + delete extended[from]; + } + }; + changePropertyName('w', _strWidth); //change w to width + changePropertyName('h', _strHeight); //change h to height + delete extended.c; //delete c (the 'changed' prop) + return extended; + }; + var obj = { + destroyed: !!prepare(_destroyed), + sleeping: !!prepare(_sleeping), + autoUpdate: prepare(!_mutationObserversConnected), + widthAuto: prepare(_widthAutoCache), + heightAuto: prepare(_heightAutoCache), + padding: prepare(_cssPaddingCache), + overflowAmount: prepare(_overflowAmountCache), + hideOverflow: prepare(_hideOverflowCache), + hasOverflow: prepare(_hasOverflowCache), + contentScrollSize: prepare(_contentScrollSizeCache), + viewportSize: prepare(_viewportSize), + hostSize: prepare(_hostSizeCache), + documentMixed: prepare(_documentMixed) + }; + return type(stateProperty) == TYPES.s ? getObjectPropVal(obj, stateProperty) : obj; + }; + + /** + * Gets all or specific extension instance. + * @param extName The name of the extension from which the instance shall be got. + * @returns {{}} The instance of the extension with the given name or undefined if the instance couldn't be found. + */ + _base.ext = function (extName) { + var result; + var privateMethods = _extensionsPrivateMethods.split(' '); + var i = 0; + if (type(extName) == TYPES.s) { + if (_extensions[LEXICON.hOP](extName)) { + result = extendDeep({}, _extensions[extName]); + for (; i < privateMethods.length; i++) + delete result[privateMethods[i]]; + } + } + else { + result = {}; + for (i in _extensions) + result[i] = extendDeep({}, _base.ext(i)); + } + return result; + }; + + /** + * Adds a extension to this instance. + * @param extName The name of the extension which shall be added. + * @param extensionOptions The extension options which shall be used. + * @returns {{}} The instance of the added extension or undefined if the extension couldn't be added properly. + */ + _base.addExt = function (extName, extensionOptions) { + var registeredExtensionObj = _plugin.extension(extName); + var instance; + var instanceAdded; + var instanceContract; + var contractResult; + var contractFulfilled = true; + if (registeredExtensionObj) { + if (!_extensions[LEXICON.hOP](extName)) { + instance = registeredExtensionObj.extensionFactory.call(_base, + extendDeep({}, registeredExtensionObj.defaultOptions), + FRAMEWORK, + COMPATIBILITY); + + if (instance) { + instanceContract = instance.contract; + if (type(instanceContract) == TYPES.f) { + contractResult = instanceContract(window); + contractFulfilled = type(contractResult) == TYPES.b ? contractResult : contractFulfilled; + } + if (contractFulfilled) { + _extensions[extName] = instance; + instanceAdded = instance.added; + if (type(instanceAdded) == TYPES.f) + instanceAdded(extensionOptions); + + return _base.ext(extName); + } + } + } + else + return _base.ext(extName); + } + else + console.warn("A extension with the name \"" + extName + "\" isn't registered."); + }; + + /** + * Removes a extension from this instance. + * @param extName The name of the extension which shall be removed. + * @returns {boolean} True if the extension was removed, false otherwise e.g. if the extension wasn't added before. + */ + _base.removeExt = function (extName) { + var instance = _extensions[extName]; + var instanceRemoved; + if (instance) { + delete _extensions[extName]; + + instanceRemoved = instance.removed; + if (type(instanceRemoved) == TYPES.f) + instanceRemoved(); + + return true; + } + return false; + }; + + /** + * Constructs the plugin. + * @param targetElement The element to which the plugin shall be applied. + * @param options The initial options of the plugin. + * @param extensions The extension(s) which shall be added right after the initialization. + * @returns {boolean} True if the plugin was successfully initialized, false otherwise. + */ + function construct(targetElement, options, extensions) { + _defaultOptions = globals.defaultOptions; + _nativeScrollbarStyling = globals.nativeScrollbarStyling; + _nativeScrollbarSize = extendDeep({}, globals.nativeScrollbarSize); + _nativeScrollbarIsOverlaid = extendDeep({}, globals.nativeScrollbarIsOverlaid); + _overlayScrollbarDummySize = extendDeep({}, globals.overlayScrollbarDummySize); + _rtlScrollBehavior = extendDeep({}, globals.rtlScrollBehavior); + + //parse & set options but don't update + setOptions(extendDeep({}, _defaultOptions, options)); + + _cssCalc = globals.cssCalc; + _msieVersion = globals.msie; + _autoUpdateRecommended = globals.autoUpdateRecommended; + _supportTransition = globals.supportTransition; + _supportTransform = globals.supportTransform; + _supportPassiveEvents = globals.supportPassiveEvents; + _supportResizeObserver = globals.supportResizeObserver; + _supportMutationObserver = globals.supportMutationObserver; + _restrictedMeasuring = globals.restrictedMeasuring; + _documentElement = FRAMEWORK(targetElement.ownerDocument); + _documentElementNative = _documentElement[0]; + _windowElement = FRAMEWORK(_documentElementNative.defaultView || _documentElementNative.parentWindow); + _windowElementNative = _windowElement[0]; + _htmlElement = findFirst(_documentElement, 'html'); + _bodyElement = findFirst(_htmlElement, 'body'); + _targetElement = FRAMEWORK(targetElement); + _targetElementNative = _targetElement[0]; + _isTextarea = _targetElement.is('textarea'); + _isBody = _targetElement.is('body'); + _documentMixed = _documentElementNative !== document; + + /* On a div Element The if checks only whether: + * - the targetElement has the class "os-host" + * - the targetElement has a a child with the class "os-padding" + * + * If that's the case, its assumed the DOM has already the following structure: + * (The ".os-host" element is the targetElement) + * + *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * + * ===================================================================================== + * + * On a Textarea Element The if checks only whether: + * - the targetElement has the class "os-textarea" + * - the targetElement is inside a element with the class "os-content" + * + * If that's the case, its assumed the DOM has already the following structure: + * (The ".os-textarea" (textarea) element is the targetElement) + * + *
+ *
+ *
+ *
+ *
+ *
+ * + *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ */ + _domExists = _isTextarea + ? _targetElement.hasClass(_classNameTextareaElement) && _targetElement.parent().hasClass(_classNameContentElement) + : _targetElement.hasClass(_classNameHostElement) && _targetElement.children(_strDot + _classNamePaddingElement)[LEXICON.l]; + + var initBodyScroll; + var bodyMouseTouchDownListener; + + //check if the plugin hasn't to be initialized + if (_nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y && !_currentPreparedOptions.nativeScrollbarsOverlaid.initialize) { + dispatchCallback('onInitializationWithdrawn'); + if (_domExists) { + setupStructureDOM(true); + setupScrollbarsDOM(true); + setupScrollbarCornerDOM(true); + } + + _destroyed = true; + _sleeping = true; + + return _base; + } + + if (_isBody) { + initBodyScroll = {}; + initBodyScroll.l = MATH.max(_targetElement[_strScrollLeft](), _htmlElement[_strScrollLeft](), _windowElement[_strScrollLeft]()); + initBodyScroll.t = MATH.max(_targetElement[_strScrollTop](), _htmlElement[_strScrollTop](), _windowElement[_strScrollTop]()); + + bodyMouseTouchDownListener = function () { + _viewportElement.removeAttr(LEXICON.ti); + setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, true, true); + } + } + + //build OverlayScrollbars DOM + setupStructureDOM(); + setupScrollbarsDOM(); + setupScrollbarCornerDOM(); + + //create OverlayScrollbars events + setupStructureEvents(); + setupScrollbarEvents(true); + setupScrollbarEvents(false); + setupScrollbarCornerEvents(); + + //create mutation observers + createMutationObservers(); + + //build resize observer for the host element + setupResizeObserver(_sizeObserverElement, hostOnResized); + + if (_isBody) { + //apply the body scroll to handle it right in the update method + _viewportElement[_strScrollLeft](initBodyScroll.l)[_strScrollTop](initBodyScroll.t); + + //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 + if (document.activeElement == targetElement && _viewportElementNative.focus) { + //set a tabindex to make the viewportElement focusable + _viewportElement.attr(LEXICON.ti, '-1'); + _viewportElementNative.focus(); + + /* the tabindex has to be removed due to; + * If you set the tabindex attribute on an
, then its child content cannot be scrolled with the arrow keys unless you set tabindex on the content, too + * https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex + */ + setupResponsiveEventListener(_viewportElement, _strMouseTouchDownEvent, bodyMouseTouchDownListener, false, true); + } + } + + //update for the first time & initialize cache + _base.update(_strAuto); + + //the plugin is initialized now! + _initialized = true; + dispatchCallback('onInitialized'); + + //call all callbacks which would fire before the initialized was complete + each(_callbacksInitQeueue, function (index, value) { dispatchCallback(value.n, value.a); }); + _callbacksInitQeueue = []; + + //add extensions + if (type(extensions) == TYPES.s) + extensions = [extensions]; + if (COMPATIBILITY.isA(extensions)) + each(extensions, function (index, value) { _base.addExt(value); }); + else if (FRAMEWORK.isPlainObject(extensions)) + each(extensions, function (key, value) { _base.addExt(key, value); }); + + //add the transition class for transitions AFTER the first update & AFTER the applied extensions (for preventing unwanted transitions) + setTimeout(function () { + if (_supportTransition && !_destroyed) + addClass(_hostElement, _classNameHostTransition); + }, 333); + + return _base; + } + + if (_plugin.valid(construct(pluginTargetElement, options, extensions))) { + INSTANCES(pluginTargetElement, _base); + } + + return _base; + } + + /** + * Initializes a new OverlayScrollbarsInstance object or changes options if already initialized or returns the current instance. + * @param pluginTargetElements The elements to which the Plugin shall be initialized. + * @param options The custom options with which the plugin shall be initialized. + * @param extensions The extension(s) which shall be added right after initialization. + * @returns {*} + */ + _plugin = window[PLUGINNAME] = function (pluginTargetElements, options, extensions) { + if (arguments[LEXICON.l] === 0) + return this; + + var arr = []; + var optsIsPlainObj = FRAMEWORK.isPlainObject(options); + var inst; + var result; + + //pluginTargetElements is null or undefined + if (!pluginTargetElements) + return optsIsPlainObj || !options ? result : arr; + + /* + pluginTargetElements will be converted to: + 1. A jQueryElement Array + 2. A HTMLElement Array + 3. A Array with a single HTML Element + so pluginTargetElements is always a array. + */ + pluginTargetElements = pluginTargetElements[LEXICON.l] != undefined ? pluginTargetElements : [pluginTargetElements[0] || pluginTargetElements]; + initOverlayScrollbarsStatics(); + + if (pluginTargetElements[LEXICON.l] > 0) { + if (optsIsPlainObj) { + FRAMEWORK.each(pluginTargetElements, function (i, v) { + inst = v; + if (inst !== undefined) + arr.push(OverlayScrollbarsInstance(inst, options, extensions, _pluginsGlobals, _pluginsAutoUpdateLoop)); + }); + } + else { + FRAMEWORK.each(pluginTargetElements, function (i, v) { + inst = INSTANCES(v); + if ((options === '!' && _plugin.valid(inst)) || (COMPATIBILITY.type(options) == TYPES.f && options(v, inst))) + arr.push(inst); + else if (options === undefined) + arr.push(inst); + }); + } + result = arr[LEXICON.l] === 1 ? arr[0] : arr; + } + return result; + }; + + /** + * Returns a object which contains global information about the plugin and each instance of it. + * The returned object is just a copy, that means that changes to the returned object won't have any effect to the original object. + */ + _plugin.globals = function () { + initOverlayScrollbarsStatics(); + var globals = FRAMEWORK.extend(true, {}, _pluginsGlobals); + delete globals['msie']; + return globals; + }; + + /** + * Gets or Sets the default options for each new plugin initialization. + * @param newDefaultOptions The object with which the default options shall be extended. + */ + _plugin.defaultOptions = function (newDefaultOptions) { + initOverlayScrollbarsStatics(); + var currDefaultOptions = _pluginsGlobals.defaultOptions; + if (newDefaultOptions === undefined) + return FRAMEWORK.extend(true, {}, currDefaultOptions); + + //set the new default options + _pluginsGlobals.defaultOptions = FRAMEWORK.extend(true, {}, currDefaultOptions, _pluginsOptions._validate(newDefaultOptions, _pluginsOptions._template, true, currDefaultOptions)._default); + }; + + /** + * Checks whether the passed instance is a non-destroyed OverlayScrollbars instance. + * @param osInstance The potential OverlayScrollbars instance which shall be checked. + * @returns {boolean} True if the passed value is a non-destroyed OverlayScrollbars instance, false otherwise. + */ + _plugin.valid = function (osInstance) { + return osInstance instanceof _plugin && !osInstance.getState().destroyed; + }; + + /** + * Registers, Unregisters or returns a extension. + * Register: Pass the name and the extension. (defaultOptions is optional) + * Unregister: Pass the name and anything except a function as extension parameter. + * Get extension: Pass the name of the extension which shall be got. + * Get all extensions: Pass no arguments. + * @param extensionName The name of the extension which shall be registered, unregistered or returned. + * @param extension A function which generates the instance of the extension or anything other to remove a already registered extension. + * @param defaultOptions The default options which shall be used for the registered extension. + */ + _plugin.extension = function (extensionName, extension, defaultOptions) { + var extNameTypeString = COMPATIBILITY.type(extensionName) == TYPES.s; + var argLen = arguments[LEXICON.l]; + var i = 0; + if (argLen < 1 || !extNameTypeString) { + //return a copy of all extension objects + return FRAMEWORK.extend(true, { length: _pluginsExtensions[LEXICON.l] }, _pluginsExtensions); + } + else if (extNameTypeString) { + if (COMPATIBILITY.type(extension) == TYPES.f) { + //register extension + _pluginsExtensions.push({ + name: extensionName, + extensionFactory: extension, + defaultOptions: defaultOptions + }); + } + else { + for (; i < _pluginsExtensions[LEXICON.l]; i++) { + if (_pluginsExtensions[i].name === extensionName) { + if (argLen > 1) + _pluginsExtensions.splice(i, 1); //remove extension + else + return FRAMEWORK.extend(true, {}, _pluginsExtensions[i]); //return extension with the given name + } + } + } + } + }; + + return _plugin; + })(); + + if (JQUERY && JQUERY.fn) { + /** + * The jQuery initialization interface. + * @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. + * @param extensions The extension(s) which shall be added right after initialization. + * @returns {*} After initialization it returns the jQuery element array, else it returns the instance(s) of the elements which are selected. + */ + JQUERY.fn.overlayScrollbars = function (options, extensions) { + var _elements = this; + if (JQUERY.isPlainObject(options)) { + JQUERY.each(_elements, function () { PLUGIN(this, options, extensions); }); + return _elements; + } + else + return PLUGIN(_elements, options); + }; + } + return PLUGIN; + } )); \ No newline at end of file diff --git a/plugins/select2/js/i18n/af.js b/plugins/select2/js/i18n/af.js index 60a2ef329..32e5ac7de 100644 --- a/plugins/select2/js/i18n/af.js +++ b/plugins/select2/js/i18n/af.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Verwyders asseblief "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Voer asseblief "+(e.minimum-e.input.length)+" of meer karakters"},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var n="Kies asseblief net "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"},removeAllItems:function(){return"Verwyder alle items"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ar.js b/plugins/select2/js/i18n/ar.js index 5866da06a..64e1caad3 100644 --- a/plugins/select2/js/i18n/ar.js +++ b/plugins/select2/js/i18n/ar.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(n){return"الرجاء حذف "+(n.input.length-n.maximum)+" عناصر"},inputTooShort:function(n){return"الرجاء إضافة "+(n.minimum-n.input.length)+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(n){return"تستطيع إختيار "+n.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"},removeAllItems:function(){return"قم بإزالة كل العناصر"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/az.js b/plugins/select2/js/i18n/az.js index f15047a50..1d52c260f 100644 --- a/plugins/select2/js/i18n/az.js +++ b/plugins/select2/js/i18n/az.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/az",[],function(){return{inputTooLong:function(n){return n.input.length-n.maximum+" simvol silin"},inputTooShort:function(n){return n.minimum-n.input.length+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(n){return"Sadəcə "+n.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"},removeAllItems:function(){return"Bütün elementləri sil"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/bg.js b/plugins/select2/js/i18n/bg.js index ad8915ee4..73b730a70 100644 --- a/plugins/select2/js/i18n/bg.js +++ b/plugins/select2/js/i18n/bg.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bg",[],function(){return{inputTooLong:function(n){var e=n.input.length-n.maximum,u="Моля въведете с "+e+" по-малко символ";return e>1&&(u+="a"),u},inputTooShort:function(n){var e=n.minimum-n.input.length,u="Моля въведете още "+e+" символ";return e>1&&(u+="a"),u},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(n){var e="Можете да направите до "+n.maximum+" ";return n.maximum>1?e+="избора":e+="избор",e},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"},removeAllItems:function(){return"Премахнете всички елементи"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/bn.js b/plugins/select2/js/i18n/bn.js index e2a3926a9..2d17b9d8e 100644 --- a/plugins/select2/js/i18n/bn.js +++ b/plugins/select2/js/i18n/bn.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bn",[],function(){return{errorLoading:function(){return"ফলাফলগুলি লোড করা যায়নি।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।";return 1!=e&&(u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।"),u},inputTooShort:function(n){return n.minimum-n.input.length+" টি অক্ষর অথবা অধিক অক্ষর লিখুন।"},loadingMore:function(){return"আরো ফলাফল লোড হচ্ছে ..."},maximumSelected:function(n){var e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।";return 1!=n.maximum&&(e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।"),e},noResults:function(){return"কোন ফলাফল পাওয়া যায়নি।"},searching:function(){return"অনুসন্ধান করা হচ্ছে ..."}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/bs.js b/plugins/select2/js/i18n/bs.js index 89a88988f..46b084d75 100644 --- a/plugins/select2/js/i18n/bs.js +++ b/plugins/select2/js/i18n/bs.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/bs",[],function(){function e(e,n,r,t){return e%10==1&&e%100!=11?n:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(n){var r=n.input.length-n.maximum,t="Obrišite "+r+" simbol";return t+=e(r,"","a","a")},inputTooShort:function(n){var r=n.minimum-n.input.length,t="Ukucajte bar još "+r+" simbol";return t+=e(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(n){var r="Možete izabrati samo "+n.maximum+" stavk";return r+=e(n.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Uklonite sve stavke"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ca.js b/plugins/select2/js/i18n/ca.js index 9e9e5ab97..82dbbb7a2 100644 --- a/plugins/select2/js/i18n/ca.js +++ b/plugins/select2/js/i18n/ca.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Si us plau, elimina "+n+" car";return r+=1==n?"àcter":"àcters"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Si us plau, introdueix "+n+" car";return r+=1==n?"àcter":"àcters"},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var n="Només es pot seleccionar "+e.maximum+" element";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"},removeAllItems:function(){return"Treu tots els elements"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/cs.js b/plugins/select2/js/i18n/cs.js index 3b05cec10..7116d6c1d 100644 --- a/plugins/select2/js/i18n/cs.js +++ b/plugins/select2/js/i18n/cs.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/cs",[],function(){function e(e,n){switch(e){case 2:return n?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadejte o jeden znak méně.":t<=4?"Prosím, zadejte o "+e(t,!0)+" znaky méně.":"Prosím, zadejte o "+t+" znaků méně."},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadejte ještě jeden znak.":t<=4?"Prosím, zadejte ještě další "+e(t,!0)+" znaky.":"Prosím, zadejte ještě dalších "+t+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(n){var t=n.maximum;return 1==t?"Můžete zvolit jen jednu položku.":t<=4?"Můžete zvolit maximálně "+e(t,!1)+" položky.":"Můžete zvolit maximálně "+t+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"},removeAllItems:function(){return"Odstraňte všechny položky"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/da.js b/plugins/select2/js/i18n/da.js index cfa74f485..cda32c34a 100644 --- a/plugins/select2/js/i18n/da.js +++ b/plugins/select2/js/i18n/da.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){return"Angiv venligst "+(e.input.length-e.maximum)+" tegn mindre"},inputTooShort:function(e){return"Angiv venligst "+(e.minimum-e.input.length)+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var n="Du kan kun vælge "+e.maximum+" emne";return 1!=e.maximum&&(n+="r"),n},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/de.js b/plugins/select2/js/i18n/de.js index 57e210f81..c2e61e580 100644 --- a/plugins/select2/js/i18n/de.js +++ b/plugins/select2/js/i18n/de.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){return"Bitte "+(e.input.length-e.maximum)+" Zeichen weniger eingeben"},inputTooShort:function(e){return"Bitte "+(e.minimum-e.input.length)+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var n="Sie können nur "+e.maximum+" Element";return 1!=e.maximum&&(n+="e"),n+=" auswählen"},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"},removeAllItems:function(){return"Entferne alle Elemente"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/dsb.js b/plugins/select2/js/i18n/dsb.js index 7bee0a002..02f283aba 100644 --- a/plugins/select2/js/i18n/dsb.js +++ b/plugins/select2/js/i18n/dsb.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/dsb",[],function(){var n=["znamuško","znamušce","znamuška","znamuškow"],e=["zapisk","zapiska","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Pšosym lašuj "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Pšosym zapódaj nanejmjenjej "+a+" "+u(a,n)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(n){return"Móžoš jano "+n.maximum+" "+u(n.maximum,e)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/el.js b/plugins/select2/js/i18n/el.js index d345ab213..d4922a1df 100644 --- a/plugins/select2/js/i18n/el.js +++ b/plugins/select2/js/i18n/el.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(n){var e=n.input.length-n.maximum,u="Παρακαλώ διαγράψτε "+e+" χαρακτήρ";return 1==e&&(u+="α"),1!=e&&(u+="ες"),u},inputTooShort:function(n){return"Παρακαλώ συμπληρώστε "+(n.minimum-n.input.length)+" ή περισσότερους χαρακτήρες"},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(n){var e="Μπορείτε να επιλέξετε μόνο "+n.maximum+" επιλογ";return 1==n.maximum&&(e+="ή"),1!=n.maximum&&(e+="ές"),e},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"},removeAllItems:function(){return"Καταργήστε όλα τα στοιχεία"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/en.js b/plugins/select2/js/i18n/en.js index 5b99c9668..3b1928573 100644 --- a/plugins/select2/js/i18n/en.js +++ b/plugins/select2/js/i18n/en.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Please delete "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Please enter "+(e.minimum-e.input.length)+" or more characters"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var n="You can only select "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No results found"},searching:function(){return"Searching…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/es.js b/plugins/select2/js/i18n/es.js index 2354519b8..68afd6d25 100644 --- a/plugins/select2/js/i18n/es.js +++ b/plugins/select2/js/i18n/es.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Por favor, elimine "+n+" car";return r+=1==n?"ácter":"acteres"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Por favor, introduzca "+n+" car";return r+=1==n?"ácter":"acteres"},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var n="Sólo puede seleccionar "+e.maximum+" elemento";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Eliminar todos los elementos"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/et.js b/plugins/select2/js/i18n/et.js index af186735b..070b61a26 100644 --- a/plugins/select2/js/i18n/et.js +++ b/plugins/select2/js/i18n/et.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var n=e.input.length-e.maximum,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" vähem"},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" rohkem"},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var n="Saad vaid "+e.maximum+" tulemus";return 1==e.maximum?n+="e":n+="t",n+=" valida"},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"},removeAllItems:function(){return"Eemalda kõik esemed"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/eu.js b/plugins/select2/js/i18n/eu.js index 96751ad4b..90d5e73f8 100644 --- a/plugins/select2/js/i18n/eu.js +++ b/plugins/select2/js/i18n/eu.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gutxiago"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gehiago"},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return 1===e.maximum?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"},removeAllItems:function(){return"Kendu elementu guztiak"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/fa.js b/plugins/select2/js/i18n/fa.js index 0180ad1b7..e1ffdbed0 100644 --- a/plugins/select2/js/i18n/fa.js +++ b/plugins/select2/js/i18n/fa.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(n){return"لطفاً "+(n.input.length-n.maximum)+" کاراکتر را حذف نمایید"},inputTooShort:function(n){return"لطفاً تعداد "+(n.minimum-n.input.length)+" کاراکتر یا بیشتر وارد نمایید"},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(n){return"شما تنها می‌توانید "+n.maximum+" آیتم را انتخاب نمایید"},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."},removeAllItems:function(){return"همه موارد را حذف کنید"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/fi.js b/plugins/select2/js/i18n/fi.js index 630144e10..ffed1247d 100644 --- a/plugins/select2/js/i18n/fi.js +++ b/plugins/select2/js/i18n/fi.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(n){return"Ole hyvä ja anna "+(n.input.length-n.maximum)+" merkkiä vähemmän"},inputTooShort:function(n){return"Ole hyvä ja anna "+(n.minimum-n.input.length)+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(n){return"Voit valita ainoastaan "+n.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"},removeAllItems:function(){return"Poista kaikki kohteet"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/fr.js b/plugins/select2/js/i18n/fr.js index 5c7c285f9..dd02f973f 100644 --- a/plugins/select2/js/i18n/fr.js +++ b/plugins/select2/js/i18n/fr.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var n=e.input.length-e.maximum;return"Supprimez "+n+" caractère"+(n>1?"s":"")},inputTooShort:function(e){var n=e.minimum-e.input.length;return"Saisissez au moins "+n+" caractère"+(n>1?"s":"")},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1?"s":"")},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"},removeAllItems:function(){return"Supprimer tous les éléments"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/gl.js b/plugins/select2/js/i18n/gl.js index 6a78d84c9..208a00570 100644 --- a/plugins/select2/js/i18n/gl.js +++ b/plugins/select2/js/i18n/gl.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var n=e.input.length-e.maximum;return 1===n?"Elimine un carácter":"Elimine "+n+" caracteres"},inputTooShort:function(e){var n=e.minimum-e.input.length;return 1===n?"Engada un carácter":"Engada "+n+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return 1===e.maximum?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Elimina todos os elementos"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/he.js b/plugins/select2/js/i18n/he.js index 2904dd221..25a8805aa 100644 --- a/plugins/select2/js/i18n/he.js +++ b/plugins/select2/js/i18n/he.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="נא למחוק ";return r+=1===e?"תו אחד":e+" תווים"},inputTooShort:function(n){var e=n.minimum-n.input.length,r="נא להכניס ";return r+=1===e?"תו אחד":e+" תווים",r+=" או יותר"},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(n){var e="באפשרותך לבחור עד ";return 1===n.maximum?e+="פריט אחד":e+=n.maximum+" פריטים",e},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"},removeAllItems:function(){return"הסר את כל הפריטים"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/hi.js b/plugins/select2/js/i18n/hi.js index 9428c29cf..f3ed79843 100644 --- a/plugins/select2/js/i18n/hi.js +++ b/plugins/select2/js/i18n/hi.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(n){var e=n.input.length-n.maximum,r=e+" अक्षर को हटा दें";return e>1&&(r=e+" अक्षरों को हटा दें "),r},inputTooShort:function(n){return"कृपया "+(n.minimum-n.input.length)+" या अधिक अक्षर दर्ज करें"},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(n){return"आप केवल "+n.maximum+" आइटम का चयन कर सकते हैं"},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."},removeAllItems:function(){return"सभी वस्तुओं को हटा दें"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/hr.js b/plugins/select2/js/i18n/hr.js index 3a5ede48f..cb3268db1 100644 --- a/plugins/select2/js/i18n/hr.js +++ b/plugins/select2/js/i18n/hr.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hr",[],function(){function n(n){var e=" "+n+" znak";return n%10<5&&n%10>0&&(n%100<5||n%100>19)?n%10>1&&(e+="a"):e+="ova",e}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(e){return"Unesite "+n(e.input.length-e.maximum)},inputTooShort:function(e){return"Unesite još "+n(e.minimum-e.input.length)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(n){return"Maksimalan broj odabranih stavki je "+n.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Ukloni sve stavke"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/hsb.js b/plugins/select2/js/i18n/hsb.js index 160318e8e..3d5bf09db 100644 --- a/plugins/select2/js/i18n/hsb.js +++ b/plugins/select2/js/i18n/hsb.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hsb",[],function(){var n=["znamješko","znamješce","znamješka","znamješkow"],e=["zapisk","zapiskaj","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Prošu zhašej "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Prošu zapodaj znajmjeńša "+a+" "+u(a,n)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(n){return"Móžeš jenož "+n.maximum+" "+u(n.maximum,e)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/hu.js b/plugins/select2/js/i18n/hu.js index 73debe098..4893aa2f7 100644 --- a/plugins/select2/js/i18n/hu.js +++ b/plugins/select2/js/i18n/hu.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){return"Túl hosszú. "+(e.input.length-e.maximum)+" karakterrel több, mint kellene."},inputTooShort:function(e){return"Túl rövid. Még "+(e.minimum-e.input.length)+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"},removeAllItems:function(){return"Távolítson el minden elemet"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/hy.js b/plugins/select2/js/i18n/hy.js index d7f11dcd0..823000714 100644 --- a/plugins/select2/js/i18n/hy.js +++ b/plugins/select2/js/i18n/hy.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(n){return"Խնդրում ենք հեռացնել "+(n.input.length-n.maximum)+" նշան"},inputTooShort:function(n){return"Խնդրում ենք մուտքագրել "+(n.minimum-n.input.length)+" կամ ավել նշաններ"},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(n){return"Դուք կարող եք ընտրել առավելագույնը "+n.maximum+" կետ"},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"},removeAllItems:function(){return"Հեռացնել բոլոր տարրերը"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/id.js b/plugins/select2/js/i18n/id.js index f9479b602..4a0b3bf00 100644 --- a/plugins/select2/js/i18n/id.js +++ b/plugins/select2/js/i18n/id.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(n){return"Hapuskan "+(n.input.length-n.maximum)+" huruf"},inputTooShort:function(n){return"Masukkan "+(n.minimum-n.input.length)+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(n){return"Anda hanya dapat memilih "+n.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Hapus semua item"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/is.js b/plugins/select2/js/i18n/is.js index b6770703e..cca5bbecf 100644 --- a/plugins/select2/js/i18n/is.js +++ b/plugins/select2/js/i18n/is.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/is",[],function(){return{inputTooLong:function(n){var t=n.input.length-n.maximum,e="Vinsamlegast styttið texta um "+t+" staf";return t<=1?e:e+"i"},inputTooShort:function(n){var t=n.minimum-n.input.length,e="Vinsamlegast skrifið "+t+" staf";return t>1&&(e+="i"),e+=" í viðbót"},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(n){return"Þú getur aðeins valið "+n.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"},removeAllItems:function(){return"Fjarlægðu öll atriði"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/it.js b/plugins/select2/js/i18n/it.js index 05f87cf04..507c7d9f2 100644 --- a/plugins/select2/js/i18n/it.js +++ b/plugins/select2/js/i18n/it.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Per favore cancella "+n+" caratter";return t+=1!==n?"i":"e"},inputTooShort:function(e){return"Per favore inserisci "+(e.minimum-e.input.length)+" o più caratteri"},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var n="Puoi selezionare solo "+e.maximum+" element";return 1!==e.maximum?n+="i":n+="o",n},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"},removeAllItems:function(){return"Rimuovi tutti gli oggetti"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ja.js b/plugins/select2/js/i18n/ja.js index 3f546061e..451025e2c 100644 --- a/plugins/select2/js/i18n/ja.js +++ b/plugins/select2/js/i18n/ja.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(n){return n.input.length-n.maximum+" 文字を削除してください"},inputTooShort:function(n){return"少なくとも "+(n.minimum-n.input.length)+" 文字を入力してください"},loadingMore:function(){return"読み込み中…"},maximumSelected:function(n){return n.maximum+" 件しか選択できません"},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"},removeAllItems:function(){return"すべてのアイテムを削除"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ka.js b/plugins/select2/js/i18n/ka.js index 5d3ca4acc..60c593b70 100644 --- a/plugins/select2/js/i18n/ka.js +++ b/plugins/select2/js/i18n/ka.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ka",[],function(){return{errorLoading:function(){return"მონაცემების ჩატვირთვა შეუძლებელია."},inputTooLong:function(n){return"გთხოვთ აკრიფეთ "+(n.input.length-n.maximum)+" სიმბოლოთი ნაკლები"},inputTooShort:function(n){return"გთხოვთ აკრიფეთ "+(n.minimum-n.input.length)+" სიმბოლო ან მეტი"},loadingMore:function(){return"მონაცემების ჩატვირთვა…"},maximumSelected:function(n){return"თქვენ შეგიძლიათ აირჩიოთ არაუმეტეს "+n.maximum+" ელემენტი"},noResults:function(){return"რეზულტატი არ მოიძებნა"},searching:function(){return"ძიება…"},removeAllItems:function(){return"ამოიღე ყველა ელემენტი"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/km.js b/plugins/select2/js/i18n/km.js index bd78a0d3e..4dca94f41 100644 --- a/plugins/select2/js/i18n/km.js +++ b/plugins/select2/js/i18n/km.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(n){return"សូមលុបចេញ "+(n.input.length-n.maximum)+" អក្សរ"},inputTooShort:function(n){return"សូមបញ្ចូល"+(n.minimum-n.input.length)+" អក្សរ រឺ ច្រើនជាងនេះ"},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(n){return"អ្នកអាចជ្រើសរើសបានតែ "+n.maximum+" ជម្រើសប៉ុណ្ណោះ"},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."},removeAllItems:function(){return"លុបធាតុទាំងអស់"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ko.js b/plugins/select2/js/i18n/ko.js index 91a470aa6..f2880fb00 100644 --- a/plugins/select2/js/i18n/ko.js +++ b/plugins/select2/js/i18n/ko.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(n){return"너무 깁니다. "+(n.input.length-n.maximum)+" 글자 지워주세요."},inputTooShort:function(n){return"너무 짧습니다. "+(n.minimum-n.input.length)+" 글자 더 입력해주세요."},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(n){return"최대 "+n.maximum+"개까지만 선택 가능합니다."},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"},removeAllItems:function(){return"모든 항목 삭제"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/lt.js b/plugins/select2/js/i18n/lt.js index ece6f6927..f6a42155a 100644 --- a/plugins/select2/js/i18n/lt.js +++ b/plugins/select2/js/i18n/lt.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/lt",[],function(){function n(n,e,i,t){return n%10==1&&(n%100<11||n%100>19)?e:n%10>=2&&n%10<=9&&(n%100<11||n%100>19)?i:t}return{inputTooLong:function(e){var i=e.input.length-e.maximum,t="Pašalinkite "+i+" simbol";return t+=n(i,"į","ius","ių")},inputTooShort:function(e){var i=e.minimum-e.input.length,t="Įrašykite dar "+i+" simbol";return t+=n(i,"į","ius","ių")},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(e){var i="Jūs galite pasirinkti tik "+e.maximum+" element";return i+=n(e.maximum,"ą","us","ų")},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"},removeAllItems:function(){return"Pašalinti visus elementus"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/lv.js b/plugins/select2/js/i18n/lv.js index 815d799b0..806dc5c43 100644 --- a/plugins/select2/js/i18n/lv.js +++ b/plugins/select2/js/i18n/lv.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/lv",[],function(){function e(e,n,u,i){return 11===e?n:e%10==1?u:i}return{inputTooLong:function(n){var u=n.input.length-n.maximum,i="Lūdzu ievadiet par "+u;return(i+=" simbol"+e(u,"iem","u","iem"))+" mazāk"},inputTooShort:function(n){var u=n.minimum-n.input.length,i="Lūdzu ievadiet vēl "+u;return i+=" simbol"+e(u,"us","u","us")},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(n){var u="Jūs varat izvēlēties ne vairāk kā "+n.maximum;return u+=" element"+e(n.maximum,"us","u","us")},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"},removeAllItems:function(){return"Noņemt visus vienumus"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/mk.js b/plugins/select2/js/i18n/mk.js index 79e870e4f..cb7b84a26 100644 --- a/plugins/select2/js/i18n/mk.js +++ b/plugins/select2/js/i18n/mk.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/mk",[],function(){return{inputTooLong:function(n){var e=(n.input.length,n.maximum,"Ве молиме внесете "+n.maximum+" помалку карактер");return 1!==n.maximum&&(e+="и"),e},inputTooShort:function(n){var e=(n.minimum,n.input.length,"Ве молиме внесете уште "+n.maximum+" карактер");return 1!==n.maximum&&(e+="и"),e},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(n){var e="Можете да изберете само "+n.maximum+" ставк";return 1===n.maximum?e+="а":e+="и",e},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"},removeAllItems:function(){return"Отстрани ги сите предмети"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ms.js b/plugins/select2/js/i18n/ms.js index d3feef2b5..6bd7eaa3e 100644 --- a/plugins/select2/js/i18n/ms.js +++ b/plugins/select2/js/i18n/ms.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(n){return"Sila hapuskan "+(n.input.length-n.maximum)+" aksara"},inputTooShort:function(n){return"Sila masukkan "+(n.minimum-n.input.length)+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(n){return"Anda hanya boleh memilih "+n.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Keluarkan semua item"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/nb.js b/plugins/select2/js/i18n/nb.js index 953ff21e4..25d89c687 100644 --- a/plugins/select2/js/i18n/nb.js +++ b/plugins/select2/js/i18n/nb.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){return"Vennligst fjern "+(e.input.length-e.maximum)+" tegn"},inputTooShort:function(e){return"Vennligst skriv inn "+(e.minimum-e.input.length)+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ne.js b/plugins/select2/js/i18n/ne.js index 536fbab84..1c39f6721 100644 --- a/plugins/select2/js/i18n/ne.js +++ b/plugins/select2/js/i18n/ne.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ne",[],function(){return{errorLoading:function(){return"नतिजाहरु देखाउन सकिएन।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="कृपया "+e+" अक्षर मेटाउनुहोस्।";return 1!=e&&(u+="कृपया "+e+" अक्षरहरु मेटाउनुहोस्।"),u},inputTooShort:function(n){return"कृपया बाँकी रहेका "+(n.minimum-n.input.length)+" वा अरु धेरै अक्षरहरु भर्नुहोस्।"},loadingMore:function(){return"अरु नतिजाहरु भरिँदैछन् …"},maximumSelected:function(n){var e="तँपाई "+n.maximum+" वस्तु मात्र छान्न पाउँनुहुन्छ।";return 1!=n.maximum&&(e="तँपाई "+n.maximum+" वस्तुहरु मात्र छान्न पाउँनुहुन्छ।"),e},noResults:function(){return"कुनै पनि नतिजा भेटिएन।"},searching:function(){return"खोजि हुँदैछ…"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/nl.js b/plugins/select2/js/i18n/nl.js index 776c2df6a..2b74058d2 100644 --- a/plugins/select2/js/i18n/nl.js +++ b/plugins/select2/js/i18n/nl.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){return"Gelieve "+(e.input.length-e.maximum)+" karakters te verwijderen"},inputTooShort:function(e){return"Gelieve "+(e.minimum-e.input.length)+" of meer karakters in te voeren"},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var n=1==e.maximum?"kan":"kunnen",r="Er "+n+" maar "+e.maximum+" item";return 1!=e.maximum&&(r+="s"),r+=" worden geselecteerd"},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"},removeAllItems:function(){return"Verwijder alle items"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/pl.js b/plugins/select2/js/i18n/pl.js index 7790a50c3..4ca5748c3 100644 --- a/plugins/select2/js/i18n/pl.js +++ b/plugins/select2/js/i18n/pl.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/pl",[],function(){var n=["znak","znaki","znaków"],e=["element","elementy","elementów"],r=function(n,e){return 1===n?e[0]:n>1&&n<=4?e[1]:n>=5?e[2]:void 0};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Usuń "+t+" "+r(t,n)},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Podaj przynajmniej "+t+" "+r(t,n)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(n){return"Możesz zaznaczyć tylko "+n.maximum+" "+r(n.maximum,e)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"},removeAllItems:function(){return"Usuń wszystkie przedmioty"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ps.js b/plugins/select2/js/i18n/ps.js index 9d2cd8ca9..9b008e4c1 100644 --- a/plugins/select2/js/i18n/ps.js +++ b/plugins/select2/js/i18n/ps.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="د مهربانۍ لمخي "+e+" توری ړنګ کړئ";return 1!=e&&(r=r.replace("توری","توري")),r},inputTooShort:function(n){return"لږ تر لږه "+(n.minimum-n.input.length)+" يا ډېر توري وليکئ"},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(n){var e="تاسو يوازي "+n.maximum+" قلم په نښه کولای سی";return 1!=n.maximum&&(e=e.replace("قلم","قلمونه")),e},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."},removeAllItems:function(){return"ټول توکي لرې کړئ"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/pt-BR.js b/plugins/select2/js/i18n/pt-BR.js index f26c8133f..c991e2550 100644 --- a/plugins/select2/js/i18n/pt-BR.js +++ b/plugins/select2/js/i18n/pt-BR.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Apague "+n+" caracter";return 1!=n&&(r+="es"),r},inputTooShort:function(e){return"Digite "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var n="Você só pode selecionar "+e.maximum+" ite";return 1==e.maximum?n+="m":n+="ns",n},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/pt.js b/plugins/select2/js/i18n/pt.js index 2068a7c28..b5da1a6b4 100644 --- a/plugins/select2/js/i18n/pt.js +++ b/plugins/select2/js/i18n/pt.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var r=e.input.length-e.maximum,n="Por favor apague "+r+" ";return n+=1!=r?"caracteres":"caractere"},inputTooShort:function(e){return"Introduza "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var r="Apenas pode seleccionar "+e.maximum+" ";return r+=1!=e.maximum?"itens":"item"},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ro.js b/plugins/select2/js/i18n/ro.js index 4bff1c64b..1ba7b40be 100644 --- a/plugins/select2/js/i18n/ro.js +++ b/plugins/select2/js/i18n/ro.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return 1!==t&&(n+="e"),n},inputTooShort:function(e){return"Vă rugăm să introduceți "+(e.minimum-e.input.length)+" sau mai multe caractere"},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",1!==e.maximum&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"},removeAllItems:function(){return"Eliminați toate elementele"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/ru.js b/plugins/select2/js/i18n/ru.js index 267b995ff..63a7d66c3 100644 --- a/plugins/select2/js/i18n/ru.js +++ b/plugins/select2/js/i18n/ru.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ru",[],function(){function n(n,e,r,u){return n%10<5&&n%10>0&&n%100<5||n%100>20?n%10>1?r:e:u}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Пожалуйста, введите на "+r+" символ";return u+=n(r,"","a","ов"),u+=" меньше"},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Пожалуйста, введите ещё хотя бы "+r+" символ";return u+=n(r,"","a","ов")},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(e){var r="Вы можете выбрать не более "+e.maximum+" элемент";return r+=n(e.maximum,"","a","ов")},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"},removeAllItems:function(){return"Удалить все элементы"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/sk.js b/plugins/select2/js/i18n/sk.js index 64346a7a3..5049528ad 100644 --- a/plugins/select2/js/i18n/sk.js +++ b/plugins/select2/js/i18n/sk.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{errorLoading:function(){return"Výsledky sa nepodarilo načítať."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadajte o jeden znak menej":t>=2&&t<=4?"Prosím, zadajte o "+e[t](!0)+" znaky menej":"Prosím, zadajte o "+t+" znakov menej"},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadajte ešte jeden znak":t<=4?"Prosím, zadajte ešte ďalšie "+e[t](!0)+" znaky":"Prosím, zadajte ešte ďalších "+t+" znakov"},loadingMore:function(){return"Načítanie ďalších výsledkov…"},maximumSelected:function(n){return 1==n.maximum?"Môžete zvoliť len jednu položku":n.maximum>=2&&n.maximum<=4?"Môžete zvoliť najviac "+e[n.maximum](!1)+" položky":"Môžete zvoliť najviac "+n.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"},removeAllItems:function(){return"Odstráňte všetky položky"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/sl.js b/plugins/select2/js/i18n/sl.js index 9b26c39ad..4d0b7d3e3 100644 --- a/plugins/select2/js/i18n/sl.js +++ b/plugins/select2/js/i18n/sl.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Prosim zbrišite "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Prosim vpišite še "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var n="Označite lahko največ "+e.maximum+" predmet";return 2==e.maximum?n+="a":1!=e.maximum&&(n+="e"),n},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"},removeAllItems:function(){return"Odstranite vse elemente"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/sq.js b/plugins/select2/js/i18n/sq.js index 4999d21f8..59162024e 100644 --- a/plugins/select2/js/i18n/sq.js +++ b/plugins/select2/js/i18n/sq.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sq",[],function(){return{errorLoading:function(){return"Rezultatet nuk mund të ngarkoheshin."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Të lutem fshi "+n+" karakter";return 1!=n&&(t+="e"),t},inputTooShort:function(e){return"Të lutem shkruaj "+(e.minimum-e.input.length)+" ose më shumë karaktere"},loadingMore:function(){return"Duke ngarkuar më shumë rezultate…"},maximumSelected:function(e){var n="Mund të zgjedhësh vetëm "+e.maximum+" element";return 1!=e.maximum&&(n+="e"),n},noResults:function(){return"Nuk u gjet asnjë rezultat"},searching:function(){return"Duke kërkuar…"},removeAllItems:function(){return"Hiq të gjitha sendet"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/sr-Cyrl.js b/plugins/select2/js/i18n/sr-Cyrl.js index 34fb00599..ce13ce8f9 100644 --- a/plugins/select2/js/i18n/sr-Cyrl.js +++ b/plugins/select2/js/i18n/sr-Cyrl.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr-Cyrl",[],function(){function n(n,e,r,u){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:u}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Обришите "+r+" симбол";return u+=n(r,"","а","а")},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Укуцајте бар још "+r+" симбол";return u+=n(r,"","а","а")},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(e){var r="Можете изабрати само "+e.maximum+" ставк";return r+=n(e.maximum,"у","е","и")},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/sr.js b/plugins/select2/js/i18n/sr.js index 2293b5875..dd407a06d 100644 --- a/plugins/select2/js/i18n/sr.js +++ b/plugins/select2/js/i18n/sr.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr",[],function(){function n(n,e,r,t){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(e){var r=e.input.length-e.maximum,t="Obrišite "+r+" simbol";return t+=n(r,"","a","a")},inputTooShort:function(e){var r=e.minimum-e.input.length,t="Ukucajte bar još "+r+" simbol";return t+=n(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(e){var r="Možete izabrati samo "+e.maximum+" stavk";return r+=n(e.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/sv.js b/plugins/select2/js/i18n/sv.js index ab5cd50c3..1bc8724a7 100644 --- a/plugins/select2/js/i18n/sv.js +++ b/plugins/select2/js/i18n/sv.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(n){return"Vänligen sudda ut "+(n.input.length-n.maximum)+" tecken"},inputTooShort:function(n){return"Vänligen skriv in "+(n.minimum-n.input.length)+" eller fler tecken"},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(n){return"Du kan max välja "+n.maximum+" element"},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"},removeAllItems:function(){return"Ta bort alla objekt"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/th.js b/plugins/select2/js/i18n/th.js index 5458cc09d..63eab7114 100644 --- a/plugins/select2/js/i18n/th.js +++ b/plugins/select2/js/i18n/th.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/th",[],function(){return{errorLoading:function(){return"ไม่สามารถค้นข้อมูลได้"},inputTooLong:function(n){return"โปรดลบออก "+(n.input.length-n.maximum)+" ตัวอักษร"},inputTooShort:function(n){return"โปรดพิมพ์เพิ่มอีก "+(n.minimum-n.input.length)+" ตัวอักษร"},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(n){return"คุณสามารถเลือกได้ไม่เกิน "+n.maximum+" รายการ"},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"},removeAllItems:function(){return"ลบรายการทั้งหมด"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/tk.js b/plugins/select2/js/i18n/tk.js index 2c8274d00..30255ff37 100644 --- a/plugins/select2/js/i18n/tk.js +++ b/plugins/select2/js/i18n/tk.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/tk",[],function(){return{errorLoading:function(){return"Netije ýüklenmedi."},inputTooLong:function(e){return e.input.length-e.maximum+" harp bozuň."},inputTooShort:function(e){return"Ýene-de iň az "+(e.minimum-e.input.length)+" harp ýazyň."},loadingMore:function(){return"Köpräk netije görkezilýär…"},maximumSelected:function(e){return"Diňe "+e.maximum+" sanysyny saýlaň."},noResults:function(){return"Netije tapylmady."},searching:function(){return"Gözlenýär…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/tr.js b/plugins/select2/js/i18n/tr.js index 5ab03b9be..fc4c0bf05 100644 --- a/plugins/select2/js/i18n/tr.js +++ b/plugins/select2/js/i18n/tr.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(n){return n.input.length-n.maximum+" karakter daha girmelisiniz"},inputTooShort:function(n){return"En az "+(n.minimum-n.input.length)+" karakter daha girmelisiniz"},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(n){return"Sadece "+n.maximum+" seçim yapabilirsiniz"},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"},removeAllItems:function(){return"Tüm öğeleri kaldır"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/uk.js b/plugins/select2/js/i18n/uk.js index cf3febb2b..63697e388 100644 --- a/plugins/select2/js/i18n/uk.js +++ b/plugins/select2/js/i18n/uk.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/uk",[],function(){function n(n,e,u,r){return n%100>10&&n%100<15?r:n%10==1?e:n%10>1&&n%10<5?u:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(e){return"Будь ласка, видаліть "+(e.input.length-e.maximum)+" "+n(e.maximum,"літеру","літери","літер")},inputTooShort:function(n){return"Будь ласка, введіть "+(n.minimum-n.input.length)+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(e){return"Ви можете вибрати лише "+e.maximum+" "+n(e.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"},removeAllItems:function(){return"Видалити всі елементи"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/vi.js b/plugins/select2/js/i18n/vi.js index 90848f324..24f3bc2d6 100644 --- a/plugins/select2/js/i18n/vi.js +++ b/plugins/select2/js/i18n/vi.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/vi",[],function(){return{inputTooLong:function(n){return"Vui lòng xóa bớt "+(n.input.length-n.maximum)+" ký tự"},inputTooShort:function(n){return"Vui lòng nhập thêm từ "+(n.minimum-n.input.length)+" ký tự trở lên"},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(n){return"Chỉ có thể chọn được "+n.maximum+" lựa chọn"},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"},removeAllItems:function(){return"Xóa tất cả các mục"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/zh-CN.js b/plugins/select2/js/i18n/zh-CN.js index 4b98e42e9..2c5649d31 100644 --- a/plugins/select2/js/i18n/zh-CN.js +++ b/plugins/select2/js/i18n/zh-CN.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}}),n.define,n.require}(); \ No newline at end of file diff --git a/plugins/select2/js/i18n/zh-TW.js b/plugins/select2/js/i18n/zh-TW.js index 39b1a4e85..570a56693 100644 --- a/plugins/select2/js/i18n/zh-TW.js +++ b/plugins/select2/js/i18n/zh-TW.js @@ -1,3 +1,3 @@ -/*! Select2 4.0.12 | https://github.com/select2/select2/blob/master/LICENSE.md */ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(n){return"請刪掉"+(n.input.length-n.maximum)+"個字元"},inputTooShort:function(n){return"請再輸入"+(n.minimum-n.input.length)+"個字元"},loadingMore:function(){return"載入中…"},maximumSelected:function(n){return"你只能選擇最多"+n.maximum+"項"},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"},removeAllItems:function(){return"刪除所有項目"}}}),n.define,n.require}(); \ No newline at end of file