summaryrefslogtreecommitdiff
path: root/src/main/resources/static/plugins/overlayScrollbars
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/resources/static/plugins/overlayScrollbars')
-rw-r--r--src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.css635
-rw-r--r--src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.min.css13
-rw-r--r--src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.js6661
-rw-r--r--src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.min.js13
-rw-r--r--src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js5578
-rw-r--r--src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js13
6 files changed, 12913 insertions, 0 deletions
diff --git a/src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.css b/src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.css
new file mode 100644
index 0000000..dc9f812
--- /dev/null
+++ b/src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.css
@@ -0,0 +1,635 @@
+/*!
+ * OverlayScrollbars
+ * https://github.com/KingSora/OverlayScrollbars
+ *
+ * Version: 1.13.0
+ *
+ * Copyright KingSora | Rene Haas.
+ * https://github.com/KingSora
+ *
+ * Released under the MIT license.
+ * Date: 02.08.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: 0;
+}
+.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.observed {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+.os-resize-observer-host > .os-resize-observer,
+.os-resize-observer-host.observed > .os-resize-observer {
+ height: 200%;
+ width: 200%;
+ padding: inherit;
+ border: inherit;
+ margin: 0;
+ display: block;
+ box-sizing: content-box;
+}
+.os-resize-observer-host.observed > .os-resize-observer,
+.os-resize-observer-host.observed > .os-resize-observer:before {
+ display: flex;
+ position: relative;
+ flex-grow: 1;
+ flex-shrink: 0;
+ flex-basis: auto;
+ box-sizing: border-box;
+}
+.os-resize-observer-host.observed > .os-resize-observer:before {
+ content: '';
+ box-sizing: content-box;
+ padding: inherit;
+ border: inherit;
+ margin: 0;
+}
+.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/src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.min.css b/src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.min.css
new file mode 100644
index 0000000..d577690
--- /dev/null
+++ b/src/main/resources/static/plugins/overlayScrollbars/css/OverlayScrollbars.min.css
@@ -0,0 +1,13 @@
+/*!
+ * OverlayScrollbars
+ * https://github.com/KingSora/OverlayScrollbars
+ *
+ * Version: 1.13.0
+ *
+ * Copyright KingSora | Rene Haas.
+ * https://github.com/KingSora
+ *
+ * Released under the MIT license.
+ * Date: 02.08.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:0}.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.observed{display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start}.os-resize-observer-host>.os-resize-observer,.os-resize-observer-host.observed>.os-resize-observer{height:200%;width:200%;padding:inherit;border:inherit;margin:0;display:block;box-sizing:content-box}.os-resize-observer-host.observed>.os-resize-observer,.os-resize-observer-host.observed>.os-resize-observer:before{display:flex;position:relative;flex-grow:1;flex-shrink:0;flex-basis:auto;box-sizing:border-box}.os-resize-observer-host.observed>.os-resize-observer:before{content:'';box-sizing:content-box;padding:inherit;border:inherit;margin:0}.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/src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.js b/src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.js
new file mode 100644
index 0000000..1de8174
--- /dev/null
+++ b/src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.js
@@ -0,0 +1,6661 @@
+/*!
+ * OverlayScrollbars
+ * https://github.com/KingSora/OverlayScrollbars
+ *
+ * Version: 1.13.0
+ *
+ * Copyright KingSora | Rene Haas.
+ * https://github.com/KingSora
+ *
+ * Released under the MIT license.
+ * Date: 02.08.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;
+ },
+ _cssPropertyValue: function (property, values, suffix) {
+ var name = property + ' ' + values;
+ var result = cssCache[name];
+
+ if (cssCache[LEXICON.hOP](name))
+ return result;
+
+ var dummyStyle = document.createElement('div')[LEXICON.s];
+ var possbleValues = values.split(' ');
+ var preparedSuffix = suffix || '';
+ var i = 0;
+ var v = -1;
+ var prop;
+
+ for (; i < possbleValues[LEXICON.l]; i++) {
+ for (; v < VENDORS._cssPrefixes[LEXICON.l]; v++) {
+ prop = v < 0 ? possbleValues[i] : VENDORS._cssPrefixes[v] + possbleValues[i];
+ dummyStyle.cssText = property + ':' + prop + preparedSuffix;
+ if (dummyStyle[LEXICON.l]) {
+ result = prop;
+ 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 (COMPATIBILITY.isA(child)) {
+ 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 updateOnLoadTemplate = [['img'], [TYPES.s, TYPES.a, TYPES.z]];
+ 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
+ updateOnLoad: updateOnLoadTemplate, //string || array || null
+ 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 = !COMPATIBILITY.isA(templateValue) ? [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('<div id="os-dummy-scrollbar-size"><div></div></div>');
+ 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: VENDORS._cssPropertyValue('width', 'calc', '(1px)') || 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'),
+ supportTransition: !!VENDORS._cssProperty('transition'),
+ 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 _strMouseEnter = 'mouseenter';
+ var _strMouseLeave = '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 _classNameHostElementForeign = _classNameHostElement + '-foreign';
+ 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 _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 _updateOnLoadEventName = 'load';
+ var _updateOnLoadElms = [];
+
+ //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 _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 _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.
+ * @param passiveOrOptions The options for the event.
+ */
+ function setupResponsiveEventListener(element, eventNames, listener, remove, passiveOrOptions) {
+ var collected = COMPATIBILITY.isA(eventNames) && COMPATIBILITY.isA(listener);
+ var method = remove ? 'removeEventListener' : 'addEventListener';
+ var onOff = remove ? 'off' : 'on';
+ var events = collected ? false : eventNames.split(_strSpace)
+ var i = 0;
+
+ var passiveOrOptionsIsObj = FRAMEWORK.isPlainObject(passiveOrOptions);
+ var passive = (_supportPassiveEvents && (passiveOrOptionsIsObj ? (passiveOrOptions._passive) : passiveOrOptions)) || false;
+ var capture = passiveOrOptionsIsObj && (passiveOrOptions._capture || false);
+ var nativeParam = _supportPassiveEvents ? {
+ passive: passive,
+ capture: capture,
+ } : capture;
+
+ if (collected) {
+ for (; i < eventNames[LEXICON.l]; i++)
+ setupResponsiveEventListener(element, eventNames[i], listener[i], remove, passiveOrOptions);
+ }
+ else {
+ for (; i < events[LEXICON.l]; i++) {
+ if(_supportPassiveEvents) {
+ element[0][method](events[i], listener, nativeParam);
+ }
+ 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 mutationIsClass;
+ var oldMutationVal;
+ var newClassVal;
+ var hostClassNameRegex;
+ var contentTimeout;
+ var now;
+ var sizeAuto;
+ var action;
+
+ _mutationObserverHostCallback = function (mutations) {
+
+ var doUpdate = false;
+ var doUpdateForce = false;
+ var mutation;
+ var mutatedAttrs = [];
+
+ if (_initialized && !_sleeping) {
+ each(mutations, function () {
+ mutation = this;
+ mutationTarget = mutation.target;
+ mutationAttrName = mutation.attributeName;
+ mutationIsClass = mutationAttrName === LEXICON.c;
+ oldMutationVal = mutation.oldValue;
+ newClassVal = mutationTarget.className;
+
+ if (_domExists && mutationIsClass && !doUpdateForce) {
+ // if old class value contains _classNameHostElementForeign and new class value doesn't
+ if (oldMutationVal.indexOf(_classNameHostElementForeign) > -1 && newClassVal.indexOf(_classNameHostElementForeign) < 0) {
+ hostClassNameRegex = createHostClassNameRegExp(true);
+ _hostElementNative.className = newClassVal.split(_strSpace).concat(oldMutationVal.split(_strSpace).filter(function (name) {
+ return name.match(hostClassNameRegex);
+ })).join(_strSpace);
+ doUpdate = doUpdateForce = true;
+ }
+ }
+
+ if (!doUpdate) {
+ doUpdate = mutationIsClass
+ ? hostClassNamesChanged(oldMutationVal, newClassVal)
+ : mutationAttrName === LEXICON.s
+ ? oldMutationVal !== mutationTarget[LEXICON.s].cssText
+ : true;
+ }
+
+ mutatedAttrs.push(mutationAttrName);
+ });
+
+ updateViewportAttrsFromTarget(mutatedAttrs);
+
+ if (doUpdate)
+ _base.update(doUpdateForce || _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 element has loaded.
+ */
+ function updateOnLoadCallback(event) {
+ var elm = FRAMEWORK(event.target);
+
+ eachUpdateOnLoad(function (i, updateOnLoadSelector) {
+ if (elm.is(updateOnLoadSelector)) {
+ 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) {
+ if (!destroy)
+ setupHostMouseTouchEvents(true);
+
+ setupResponsiveEventListener(_hostElement,
+ _strMouseTouchMoveEvent.split(_strSpace)[0],
+ hostOnMouseMove,
+ (!_scrollbarsAutoHideMove || destroy), true);
+ setupResponsiveEventListener(_hostElement,
+ [_strMouseEnter, _strMouseLeave],
+ [hostOnMouseEnter, hostOnMouseLeave],
+ (!_scrollbarsAutoHideLeave || 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 oldClassNames The old ClassName string or array.
+ * @param newClassNames The new ClassName string or array.
+ * @returns {boolean} True if the class names has really changed, false otherwise.
+ */
+ function hostClassNamesChanged(oldClassNames, newClassNames) {
+ var currClasses = typeof newClassNames == TYPES.s ? newClassNames.split(_strSpace) : [];
+ var oldClasses = typeof oldClassNames == TYPES.s ? oldClassNames.split(_strSpace) : [];
+ var diff = getArrayDifferences(oldClasses, currClasses);
+
+ // remove none theme from diff list to prevent update
+ var idx = inArray(_classNameThemeNone, diff);
+ var i;
+ var regex;
+
+ if (idx > -1)
+ diff.splice(idx, 1);
+
+ if (diff[LEXICON.l] > 0) {
+ regex = createHostClassNameRegExp(true, true);
+ for (i = 0; i < diff.length; i++) {
+ if (!diff[i].match(regex)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 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.className);
+
+ //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 || (autoUpdate === null && _autoUpdateRecommended)) {
+ disconnectMutationObservers();
+ autoUpdateLoop.add(_base);
+ }
+ else {
+ autoUpdateLoop.remove(_base);
+ connectMutationObservers();
+ }
+ }
+
+ //activate or deactivate size auto capability
+ if (sizeAutoCapableChanged) {
+ if (sizeAutoCapable) {
+ if (_contentGlueElement) {
+ _contentGlueElement.show();
+ }
+ else {
+ _contentGlueElement = FRAMEWORK(generateDiv(_classNameContentGlueElement));
+ _paddingElement.before(_contentGlueElement);
+ }
+ 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;
+
+ //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 = getTopRightBottomLeftHost(_strPaddingMinus);
+
+ //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 updateBorderX = (widthAuto && _isBorderBox) || !_isBorderBox;
+ var updateBorderY = (heightAuto && _isBorderBox) || !_isBorderBox;
+ var border = getTopRightBottomLeftHost(_strBorderMinus, '-' + _strWidth, !updateBorderX, !updateBorderY)
+
+ //detect margin:
+ var margin = getTopRightBottomLeftHost(_strMarginMinus);
+
+ //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);
+
+ //refresh cache
+ _textareaAutoWrappingCache = textareaAutoWrapping;
+ _cssDirectionCache = cssDirection;
+ _cssBoxSizingCache = boxSizing;
+ _widthAutoCache = widthAuto;
+ _heightAutoCache = heightAuto;
+ _cssPaddingCache = padding;
+ _cssBorderCache = border;
+ _cssMarginCache = margin;
+
+ //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 = {};
+ var paddingValues = [padding.t, padding.r, padding.b, padding.l];
+
+ setTopRightBottomLeft(contentGlueElementCSS, _strMarginMinus, [-padding.t, -padding.r, -padding.b, -padding.l]);
+ if (paddingAbsolute) {
+ setTopRightBottomLeft(paddingElementCSS, _strEmpty, paddingValues);
+ setTopRightBottomLeft(_isTextarea ? textareaCSS : contentElementCSS, _strPaddingMinus);
+ }
+ else {
+ setTopRightBottomLeft(paddingElementCSS, _strEmpty);
+ setTopRightBottomLeft(_isTextarea ? textareaCSS : contentElementCSS, _strPaddingMinus, paddingValues);
+ }
+
+ _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 || padding.c || border.c)) {
+ contentElementCSS[_strHeight] = _strAuto;
+ }
+ else if (heightAutoChanged || paddingAbsoluteChanged) {
+ contentElementCSS[_strHeight] = _strHundredPercent;
+ }
+ if (widthAuto && (widthAutoChanged || paddingAbsoluteChanged || boxSizingChanged || padding.c || border.c || cssDirectionChanged)) {
+ contentElementCSS[_strWidth] = _strAuto;
+ contentGlueElementCSS[_strMaxMinus + _strWidth] = _strHundredPercent; //IE Fix
+ }
+ else if (widthAutoChanged || paddingAbsoluteChanged) {
+ contentElementCSS[_strWidth] = _strHundredPercent;
+ contentElementCSS[_strFloat] = _strEmpty;
+ contentGlueElementCSS[_strMaxMinus + _strWidth] = _strEmpty; //IE Fix
+ }
+ if (widthAuto) {
+ //textareaDynOrigSize.w || _strAuto :: doesnt works because applied margin will shift width
+ contentGlueElementCSS[_strWidth] = _strAuto;
+
+ contentElementCSS[_strWidth] = VENDORS._cssPropertyValue(_strWidth, 'max-content intrinsic') || _strAuto;
+ contentElementCSS[_strFloat] = isRTLRight;
+ }
+ else {
+ contentGlueElementCSS[_strWidth] = _strEmpty;
+ }
+ if (heightAuto) {
+ //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 || 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 hostAbsoluteRectSize = {
+ w: hostSize.w - _marginX - _borderX - (_isBorderBox ? 0 : _paddingX),
+ h: hostSize.h - _marginY - _borderY - (_isBorderBox ? 0 : _paddingY)
+ };
+ 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, hostAbsoluteRectSize.w),
+ h: MATH.max((heightAuto ? contentSize.h : scrollSize.h) + paddingAbsoluteY, hostAbsoluteRectSize.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 viewportSize = _viewportSize[wh] - borderSize - marginSize - (_isBorderBox ? 0 : 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] = hostAbsoluteRectSize[wh] - 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) && (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) {
+ addRemoveClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible, !ignoreOverlayScrollbarHiding)
+ }
+ 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 refreshScrollbarsVisibility = function (showX, showY) {
+ showY = showY === undefined ? showX : showY;
+ refreshScrollbarAppearance(true, showX, canScroll.x)
+ refreshScrollbarAppearance(false, showY, canScroll.y)
+ };
+
+ //manage class name which indicates scrollable overflow
+ addRemoveClass(_hostElement, _classNameHostOverflow, hideOverflow.x || hideOverflow.y);
+ addRemoveClass(_hostElement, _classNameHostOverflowX, hideOverflow.x);
+ addRemoveClass(_hostElement, _classNameHostOverflowY, hideOverflow.y);
+
+ //add or remove rtl class name for styling purposes except when its body, then the scrollbar stays
+ if (cssDirectionChanged && !_isBody) {
+ addRemoveClass(_hostElement, _classNameHostRTL, _isRTL);
+ }
+
+ //manage the resize feature (CSS3 resize "polyfill" for this plugin)
+ if (_isBody)
+ addClass(_hostElement, _classNameHostResizeDisabled);
+ if (resizeChanged) {
+ addRemoveClass(_hostElement, _classNameHostResizeDisabled, _resizeNone);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResize, !_resizeNone);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeB, _resizeBoth);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeH, _resizeHorizontal);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeV, _resizeVertical);
+ }
+
+ //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) {
+ refreshScrollbarsVisibility(false);
+ }
+ }
+ }
+ else if (scrollbarsVisibilityAuto) {
+ refreshScrollbarsVisibility(canScroll.x, canScroll.y);
+ }
+ else if (scrollbarsVisibilityVisible) {
+ refreshScrollbarsVisibility(true);
+ }
+ else if (scrollbarsVisibilityHidden) {
+ refreshScrollbarsVisibility(false);
+ }
+ }
+
+ //manage the scrollbars auto hide feature (auto hide them after specific actions)
+ if (scrollbarsAutoHideChanged || ignoreOverlayScrollbarHidingChanged) {
+ setupHostMouseTouchEvents(!_scrollbarsAutoHideLeave && !_scrollbarsAutoHideMove);
+ refreshScrollbarsAutoHide(_scrollbarsAutoHideNever, !_scrollbarsAutoHideNever);
+ }
+
+ //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:
+ dispatchCallback('onDirectionChanged', {
+ isRTL: _isRTL,
+ dir: cssDirection
+ }, cssDirectionChanged);
+ dispatchCallback('onHostSizeChanged', {
+ width: _hostSizeCache.w,
+ height: _hostSizeCache.h
+ }, hostSizeChanged);
+ dispatchCallback('onContentSizeChanged', {
+ width: _contentScrollSizeCache.w,
+ height: _contentScrollSizeCache.h
+ }, contentSizeChanged);
+ dispatchCallback('onOverflowChanged', {
+ x: hasOverflow.x,
+ y: hasOverflow.y,
+ xScrollable: hideOverflow.xs,
+ yScrollable: hideOverflow.ys,
+ clipped: hideOverflow.x || hideOverflow.y
+ }, hasOverflow.c || hideOverflow.c);
+ dispatchCallback('onOverflowAmountChanged', {
+ x: overflowAmount.x,
+ y: overflowAmount.y
+ }, overflowAmount.c);
+ }
+
+ //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;
+ }
+
+ if (_initialized && changedOptions.updateOnLoad) {
+ updateElementsOnLoad();
+ }
+
+ //freezeResizeObserver(_sizeObserverElement, false);
+ //freezeResizeObserver(_sizeAutoObserverElement, false);
+
+ dispatchCallback('onUpdated', { forced: force });
+ }
+
+ /**
+ * Updates the found elements of which the load event shall be handled.
+ */
+ function updateElementsOnLoad() {
+ if (!_isTextarea) {
+ eachUpdateOnLoad(function (i, updateOnLoadSelector) {
+ _contentElement.find(updateOnLoadSelector).each(function (i, el) {
+ // if element doesn't have a updateOnLoadCallback applied
+ if (COMPATIBILITY.inA(el, _updateOnLoadElms) < 0) {
+ _updateOnLoadElms.push(el);
+ FRAMEWORK(el)
+ .off(_updateOnLoadEventName, updateOnLoadCallback)
+ .on(_updateOnLoadEventName, updateOnLoadCallback);
+ }
+ });
+ });
+ }
+ }
+
+ //==== 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.
+ */
+ /**
+ * 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,
+ _classNameHostElementForeign,
+ _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);
+
+ //add this class to workaround class changing issues with UI frameworks especially Vue
+ if (_domExists)
+ addClass(_hostElement, _classNameHostElementForeign);
+
+ //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 (COMPATIBILITY.isA(adoptAttrs) && _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 strClickEvent = 'click';
+ 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 stopClickEventPropagation(event) {
+ COMPATIBILITY.stpP(event);
+ }
+ 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);
+ COMPATIBILITY.rAF()(function() {
+ setupResponsiveEventListener(_documentElement, strClickEvent, stopClickEventPropagation, true, { _capture: 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]);
+ COMPATIBILITY.rAF()(function() {
+ setupResponsiveEventListener(_documentElement, strClickEvent, stopClickEventPropagation, false, { _capture: true });
+ });
+
+
+ if (_msieVersion || !_documentMixed)
+ COMPATIBILITY.prvD(event);
+ COMPATIBILITY.stpP(event);
+ }
+ function onTrackMouseTouchDown(event) {
+ if (onMouseTouchDownContinue(event)) {
+ var handleToViewportRatio = scrollbarVars._info._handleLength / Math.round(MATH.min(1, _viewportSize[scrollbarVars._w_h] / _contentScrollSizeCache[scrollbarVars._w_h]) * scrollbarVars._info._trackLength);
+ var scrollDistance = MATH.round(_viewportSize[scrollbarVars._w_h] * handleToViewportRatio);
+ var scrollBaseDuration = 270 * handleToViewportRatio;
+ var scrollFirstIterationDelay = 400 * handleToViewportRatio;
+ 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 = scrollBaseDuration * scrollDurationFactor;
+ var timeoutDelay = isFirstIteration ? MATH.max(scrollFirstIterationDelay, 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, _strMouseEnter, _strMouseLeave],
+ [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 scrollbarHiddenClassName = isHorizontal ? _classNameHostScrollbarHorizontalHidden : _classNameHostScrollbarVerticalHidden;
+ var scrollbarElement = isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement;
+
+ addRemoveClass(_hostElement, scrollbarHiddenClassName, !shallBeVisible);
+ addRemoveClass(scrollbarElement, _classNameScrollbarUnusable, !canScroll);
+ }
+
+ /**
+ * 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, _viewportSize[scrollbarVars._w_h] / _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.
+ * @param dependent Boolean which decides whether the callback shall be fired, undefined is like a "true" value.
+ */
+ function dispatchCallback(name, args, dependent) {
+ if (dependent === false)
+ return;
+ 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) {
+ prefix = prefix || _strEmpty;
+ values = 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];
+ }
+
+ /**
+ * Gets the "top, right, bottom, left" CSS properties of the CSS property with the given prefix from the host element.
+ * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix)
+ * @param suffix The suffix of the "top, right, bottom, left" css properties. (example: 'border-' is a valid prefix with '-width' is a valid suffix)
+ * @param zeroX True if the x axis shall be 0.
+ * @param zeroY True if the y axis shall be 0.
+ * @returns {{}} The object which contains the numbers of the read CSS properties.
+ */
+ function getTopRightBottomLeftHost(prefix, suffix, zeroX, zeroY) {
+ suffix = suffix || _strEmpty;
+ prefix = prefix || _strEmpty;
+ return {
+ t: zeroY ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strTop + suffix)),
+ r: zeroX ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strRight + suffix)),
+ b: zeroY ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strBottom + suffix)),
+ l: zeroX ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strLeft + suffix))
+ };
+ }
+
+ /**
+ * 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(', ');
+ }
+
+ /**
+ * Generates a Regular Expression which matches with a string which starts with 'os-host'.
+ * @param {boolean} withCurrClassNameOption The Regular Expression also matches if the string is the current ClassName option (multiple values splitted by space possible).
+ * @param {boolean} withOldClassNameOption The Regular Expression also matches if the string is the old ClassName option (multiple values splitted by space possible).
+ */
+ function createHostClassNameRegExp(withCurrClassNameOption, withOldClassNameOption) {
+ var i;
+ var split;
+ var appendix;
+ var appendClasses = function (classes, condition) {
+ appendix = '';
+ if (condition && typeof classes == TYPES.s) {
+ split = classes.split(_strSpace);
+ for (i = 0; i < split[LEXICON.l]; i++)
+ appendix += '|' + split[i] + '$';
+ // split[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') for escaping regex characters
+ }
+ return appendix;
+ };
+
+ return new RegExp(
+ '(^' + _classNameHostElement + '([-_].+|)$)' +
+ appendClasses(_classNameCache, withCurrClassNameOption) +
+ appendClasses(_oldClassName, withOldClassNameOption), 'g');
+ }
+
+ /**
+ * 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 '<div ' + (classesOrAttrs ? type(classesOrAttrs) == TYPES.s ?
+ 'class="' + classesOrAttrs + '"' :
+ (function () {
+ var key;
+ var attrs = _strEmpty;
+ if (FRAMEWORK.isPlainObject(classesOrAttrs)) {
+ for (key in classesOrAttrs)
+ attrs += (key === 'c' ? 'class' : key) + '="' + classesOrAttrs[key] + '" ';
+ }
+ return attrs;
+ })() :
+ _strEmpty) +
+ '>' +
+ (content || _strEmpty) +
+ '</div>';
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Runs a action for each selector inside the updateOnLoad option.
+ * @param {Function} action The action for each updateOnLoad selector, the arguments the function takes is the index and the value (the selector).
+ */
+ function eachUpdateOnLoad(action) {
+ var updateOnLoad = _currentPreparedOptions.updateOnLoad;
+ updateOnLoad = type(updateOnLoad) == TYPES.s ? updateOnLoad.split(_strSpace) : updateOnLoad;
+
+ if (COMPATIBILITY.isA(updateOnLoad) && !_destroyed) {
+ each(updateOnLoad, action);
+ }
+ }
+
+
+ //==== 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);
+ }
+
+ /**
+ * Adds or removes the given classes dependent on the boolean value. True for add, false for remove.
+ */
+ function addRemoveClass(el, classes, doAdd) {
+ return doAdd ? addClass(el, classes) : removeClass(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 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 });
+ }
+
+ updateElementsOnLoad();
+
+ 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 < _updateOnLoadElms[LEXICON.l]; i++)
+ FRAMEWORK(_updateOnLoadElms[i]).off(_updateOnLoadEventName, updateOnLoadCallback);
+ _updateOnLoadElms = 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 (COMPATIBILITY.isA(coordinates))
+ 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, 0) //'<' = 0%
+ [strReplace](/max/g, (normalizeShortcuts ? '-' : _strEmpty) + _strHundredPercent) //'max' = 100%
+ [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 (COMPATIBILITY.isA(easing) || 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)
+ *
+ * <div class="os-host">
+ * <div class="os-resize-observer-host"></div>
+ * <div class="os-padding">
+ * <div class="os-viewport">
+ * <div class="os-content"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-horizontal ">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-vertical">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar-corner"></div>
+ * </div>
+ *
+ * =====================================================================================
+ *
+ * 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)
+ *
+ * <div class="os-host-textarea">
+ * <div class="os-resize-observer-host"></div>
+ * <div class="os-padding os-text-inherit">
+ * <div class="os-viewport os-text-inherit">
+ * <div class="os-content os-text-inherit">
+ * <div class="os-textarea-cover"></div>
+ * <textarea class="os-textarea os-text-inherit"></textarea>
+ * </div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-horizontal ">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-vertical">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar-corner"></div>
+ * </div>
+ */
+ _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 <div>, 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/src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.min.js b/src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.min.js
new file mode 100644
index 0000000..a2e1a12
--- /dev/null
+++ b/src/main/resources/static/plugins/overlayScrollbars/js/OverlayScrollbars.min.js
@@ -0,0 +1,13 @@
+/*!
+ * OverlayScrollbars
+ * https://github.com/KingSora/OverlayScrollbars
+ *
+ * Version: 1.13.0
+ *
+ * Copyright KingSora | Rene Haas.
+ * https://github.com/KingSora
+ *
+ * Released under the MIT license.
+ * Date: 02.08.2020
+ */
+!function(n,t){"function"==typeof define&&define.amd?define(function(){return t(n,n.document,undefined)}):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(n,n.document,undefined):t(n,n.document,undefined)}("undefined"!=typeof window?window:this,function(vi,hi,di){"use strict";var o,l,a,u,pi="object",bi="function",mi="array",gi="string",wi="boolean",yi="number",f="undefined",n="null",xi={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"},_i=(o={},l={},{e:a=["-webkit-","-moz-","-o-","-ms-"],u:u=["WebKit","Moz","O","MS"],v:function(n){var t=l[n];if(l[xi.hOP](n))return t;for(var r,e,i,o=c(n),u=hi.createElement("div")[xi.s],f=0;f<a.length;f++)for(i=a[f].replace(/-/g,""),r=[n,a[f]+n,i+o,c(i)+o],e=0;e<r[xi.l];e++)if(u[r[e]]!==di){t=r[e];break}return l[n]=t},d:function(n,t,r){var e=n+" "+t,i=l[e];if(l[xi.hOP](e))return i;for(var o,u=hi.createElement("div")[xi.s],f=t.split(" "),a=r||"",c=0,s=-1;c<f[xi.l];c++)for(;s<_i.e[xi.l];s++)if(o=s<0?f[c]:_i.e[s]+f[c],u.cssText=n+":"+o+a,u[xi.l]){i=o;break}return l[e]=i},m:function(n,t,r){var e=0,i=o[n];if(!o[xi.hOP](n)){for(i=vi[n];e<u[xi.l];e++)i=i||vi[(t?u[e]:u[e].toLowerCase())+c(n)];o[n]=i}return i||r}});function c(n){return n.charAt(0).toUpperCase()+n.slice(1)}var Oi={wW:r(t,0,!0),wH:r(t,0),mO:r(_i.m,0,"MutationObserver",!0),rO:r(_i.m,0,"ResizeObserver",!0),rAF:r(_i.m,0,"requestAnimationFrame",!1,function(n){return vi.setTimeout(n,1e3/60)}),cAF:r(_i.m,0,"cancelAnimationFrame",!1,function(n){return vi.clearTimeout(n)}),now:function(){return Date.now&&Date.now()||(new Date).getTime()},stpP:function(n){n.stopPropagation?n.stopPropagation():n.cancelBubble=!0},prvD:function(n){n.preventDefault&&n.cancelable?n.preventDefault():n.returnValue=!1},page:function(n){var t=((n=n.originalEvent||n).target||n.srcElement||hi).ownerDocument||hi,r=t.documentElement,e=t.body;if(n.touches===di)return!n.pageX&&n.clientX&&null!=n.clientX?{x:n.clientX+(r&&r.scrollLeft||e&&e.scrollLeft||0)-(r&&r.clientLeft||e&&e.clientLeft||0),y:n.clientY+(r&&r.scrollTop||e&&e.scrollTop||0)-(r&&r.clientTop||e&&e.clientTop||0)}:{x:n.pageX,y:n.pageY};var i=n.touches[0];return{x:i.pageX,y:i.pageY}},mBtn:function(n){var t=n.button;return n.which||t===di?n.which:1&t?1:2&t?3:4&t?2:0},inA:function(n,t){for(var r=0;r<t[xi.l];r++)try{if(t[r]===n)return r}catch(e){}return-1},isA:function(n){var t=Array.isArray;return t?t(n):this.type(n)==mi},type:function(n){return n===di||null===n?n+"":Object[xi.p].toString.call(n).replace(/^\[object (.+)\]$/,"$1").toLowerCase()},bind:r};function t(n){return n?vi.innerWidth||hi.documentElement[xi.cW]||hi.body[xi.cW]:vi.innerHeight||hi.documentElement[xi.cH]||hi.body[xi.cH]}function r(n,t){if(typeof n!=bi)throw"Can't bind function!";var r=xi.p,e=Array[r].slice.call(arguments,2),i=function(){},o=function(){return n.apply(this instanceof i?this:t,e.concat(Array[r].slice.call(arguments)))};return n[r]&&(i[r]=n[r]),o[r]=new i,o}var s,v,h,k,I,T,d,p,Si=Math,zi=vi.jQuery,A=(s={p:Si.PI,c:Si.cos,s:Si.sin,w:Si.pow,t:Si.sqrt,n:Si.asin,a:Si.abs,o:1.70158},{swing:function(n,t,r,e,i){return.5-s.c(n*s.p)/2},linear:function(n,t,r,e,i){return n},easeInQuad:function(n,t,r,e,i){return e*(t/=i)*t+r},easeOutQuad:function(n,t,r,e,i){return-e*(t/=i)*(t-2)+r},easeInOutQuad:function(n,t,r,e,i){return(t/=i/2)<1?e/2*t*t+r:-e/2*(--t*(t-2)-1)+r},easeInCubic:function(n,t,r,e,i){return e*(t/=i)*t*t+r},easeOutCubic:function(n,t,r,e,i){return e*((t=t/i-1)*t*t+1)+r},easeInOutCubic:function(n,t,r,e,i){return(t/=i/2)<1?e/2*t*t*t+r:e/2*((t-=2)*t*t+2)+r},easeInQuart:function(n,t,r,e,i){return e*(t/=i)*t*t*t+r},easeOutQuart:function(n,t,r,e,i){return-e*((t=t/i-1)*t*t*t-1)+r},easeInOutQuart:function(n,t,r,e,i){return(t/=i/2)<1?e/2*t*t*t*t+r:-e/2*((t-=2)*t*t*t-2)+r},easeInQuint:function(n,t,r,e,i){return e*(t/=i)*t*t*t*t+r},easeOutQuint:function(n,t,r,e,i){return e*((t=t/i-1)*t*t*t*t+1)+r},easeInOutQuint:function(n,t,r,e,i){return(t/=i/2)<1?e/2*t*t*t*t*t+r:e/2*((t-=2)*t*t*t*t+2)+r},easeInSine:function(n,t,r,e,i){return-e*s.c(t/i*(s.p/2))+e+r},easeOutSine:function(n,t,r,e,i){return e*s.s(t/i*(s.p/2))+r},easeInOutSine:function(n,t,r,e,i){return-e/2*(s.c(s.p*t/i)-1)+r},easeInExpo:function(n,t,r,e,i){return 0==t?r:e*s.w(2,10*(t/i-1))+r},easeOutExpo:function(n,t,r,e,i){return t==i?r+e:e*(1-s.w(2,-10*t/i))+r},easeInOutExpo:function(n,t,r,e,i){return 0==t?r:t==i?r+e:(t/=i/2)<1?e/2*s.w(2,10*(t-1))+r:e/2*(2-s.w(2,-10*--t))+r},easeInCirc:function(n,t,r,e,i){return-e*(s.t(1-(t/=i)*t)-1)+r},easeOutCirc:function(n,t,r,e,i){return e*s.t(1-(t=t/i-1)*t)+r},easeInOutCirc:function(n,t,r,e,i){return(t/=i/2)<1?-e/2*(s.t(1-t*t)-1)+r:e/2*(s.t(1-(t-=2)*t)+1)+r},easeInElastic:function(n,t,r,e,i){var o=s.o,u=0,f=e;return 0==t?r:1==(t/=i)?r+e:(u=u||.3*i,o=f<s.a(e)?(f=e,u/4):u/(2*s.p)*s.n(e/f),-(f*s.w(2,10*--t)*s.s((t*i-o)*(2*s.p)/u))+r)},easeOutElastic:function(n,t,r,e,i){var o=s.o,u=0,f=e;return 0==t?r:1==(t/=i)?r+e:(u=u||.3*i,o=f<s.a(e)?(f=e,u/4):u/(2*s.p)*s.n(e/f),f*s.w(2,-10*t)*s.s((t*i-o)*(2*s.p)/u)+e+r)},easeInOutElastic:function(n,t,r,e,i){var o=s.o,u=0,f=e;return 0==t?r:2==(t/=i/2)?r+e:(u=u||i*(.3*1.5),o=f<s.a(e)?(f=e,u/4):u/(2*s.p)*s.n(e/f),t<1?f*s.w(2,10*--t)*s.s((t*i-o)*(2*s.p)/u)*-.5+r:f*s.w(2,-10*--t)*s.s((t*i-o)*(2*s.p)/u)*.5+e+r)},easeInBack:function(n,t,r,e,i,o){return e*(t/=i)*t*(((o=o||s.o)+1)*t-o)+r},easeOutBack:function(n,t,r,e,i,o){return e*((t=t/i-1)*t*(((o=o||s.o)+1)*t+o)+1)+r},easeInOutBack:function(n,t,r,e,i,o){return o=o||s.o,(t/=i/2)<1?e/2*(t*t*((1+(o*=1.525))*t-o))+r:e/2*((t-=2)*t*((1+(o*=1.525))*t+o)+2)+r},easeInBounce:function(n,t,r,e,i){return e-this.easeOutBounce(n,i-t,0,e,i)+r},easeOutBounce:function(n,t,r,e,i){var o=7.5625;return(t/=i)<1/2.75?e*(o*t*t)+r:t<2/2.75?e*(o*(t-=1.5/2.75)*t+.75)+r:t<2.5/2.75?e*(o*(t-=2.25/2.75)*t+.9375)+r:e*(o*(t-=2.625/2.75)*t+.984375)+r},easeInOutBounce:function(n,t,r,e,i){return t<i/2?.5*this.easeInBounce(n,2*t,0,e,i)+r:.5*this.easeOutBounce(n,2*t-i,0,e,i)+.5*e+r}}),Ci=(v=/[^\x20\t\r\n\f]+/g,h=" ",k="scrollLeft",I="scrollTop",T=[],d=Oi.type,p={animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},M[xi.p]={on:function(t,r){var e,i=(t=(t||"").match(v)||[""])[xi.l],o=0;return this.each(function(){e=this;try{if(e.addEventListener)for(;o<i;o++)e.addEventListener(t[o],r);else if(e.detachEvent)for(;o<i;o++)e.attachEvent("on"+t[o],r)}catch(n){}})},off:function(t,r){var e,i=(t=(t||"").match(v)||[""])[xi.l],o=0;return this.each(function(){e=this;try{if(e.removeEventListener)for(;o<i;o++)e.removeEventListener(t[o],r);else if(e.detachEvent)for(;o<i;o++)e.detachEvent("on"+t[o],r)}catch(n){}})},one:function(n,i){return n=(n||"").match(v)||[""],this.each(function(){var e=M(this);M.each(n,function(n,t){var r=function(n){i.call(this,n),e.off(t,r)};e.on(t,r)})})},trigger:function(n){var t,r;return this.each(function(){t=this,hi.createEvent?((r=hi.createEvent("HTMLEvents")).initEvent(n,!0,!1),t.dispatchEvent(r)):t.fireEvent("on"+n)})},append:function(n){return this.each(function(){i(this,"beforeend",n)})},prepend:function(n){return this.each(function(){i(this,"afterbegin",n)})},before:function(n){return this.each(function(){i(this,"beforebegin",n)})},after:function(n){return this.each(function(){i(this,"afterend",n)})},remove:function(){return this.each(function(){var n=this.parentNode;null!=n&&n.removeChild(this)})},unwrap:function(){var n,t,r,e=[];for(this.each(function(){-1===H(r=this.parentNode,e)&&e.push(r)}),n=0;n<e[xi.l];n++){for(t=e[n],r=t.parentNode;t.firstChild;)r.insertBefore(t.firstChild,t);r.removeChild(t)}return this},wrapAll:function(n){for(var t,r=this,e=M(n)[0],i=e,o=r[0].parentNode,u=r[0].previousSibling;0<i.childNodes[xi.l];)i=i.childNodes[0];for(t=0;r[xi.l]-t;i.firstChild===r[0]&&t++)i.appendChild(r[t]);var f=u?u.nextSibling:o.firstChild;return o.insertBefore(e,f),this},wrapInner:function(r){return this.each(function(){var n=M(this),t=n.contents();t[xi.l]?t.wrapAll(r):n.append(r)})},wrap:function(n){return this.each(function(){M(this).wrapAll(n)})},css:function(n,t){var r,e,i,o=vi.getComputedStyle;return d(n)==gi?t===di?(r=this[0],i=o?o(r,null):r.currentStyle[n],o?null!=i?i.getPropertyValue(n):r[xi.s][n]:i):this.each(function(){y(this,n,t)}):this.each(function(){for(e in n)y(this,e,n[e])})},hasClass:function(n){for(var t,r,e=0,i=h+n+h;t=this[e++];){if((r=t.classList)&&r.contains(n))return!0;if(1===t.nodeType&&-1<(h+g(t.className+"")+h).indexOf(i))return!0}return!1},addClass:function(n){var t,r,e,i,o,u,f,a,c=0,s=0;if(n)for(t=n.match(v)||[];r=this[c++];)if(a=r.classList,f===di&&(f=a!==di),f)for(;o=t[s++];)a.add(o);else if(i=r.className+"",e=1===r.nodeType&&h+g(i)+h){for(;o=t[s++];)e.indexOf(h+o+h)<0&&(e+=o+h);i!==(u=g(e))&&(r.className=u)}return this},removeClass:function(n){var t,r,e,i,o,u,f,a,c=0,s=0;if(n)for(t=n.match(v)||[];r=this[c++];)if(a=r.classList,f===di&&(f=a!==di),f)for(;o=t[s++];)a.remove(o);else if(i=r.className+"",e=1===r.nodeType&&h+g(i)+h){for(;o=t[s++];)for(;-1<e.indexOf(h+o+h);)e=e.replace(h+o+h,h);i!==(u=g(e))&&(r.className=u)}return this},hide:function(){return this.each(function(){this[xi.s].display="none"})},show:function(){return this.each(function(){this[xi.s].display="block"})},attr:function(n,t){for(var r,e=0;r=this[e++];){if(t===di)return r.getAttribute(n);r.setAttribute(n,t)}return this},removeAttr:function(n){return this.each(function(){this.removeAttribute(n)})},offset:function(){var n=this[0][xi.bCR](),t=vi.pageXOffset||hi.documentElement[k],r=vi.pageYOffset||hi.documentElement[I];return{top:n.top+r,left:n.left+t}},position:function(){var n=this[0];return{top:n.offsetTop,left:n.offsetLeft}},scrollLeft:function(n){for(var t,r=0;t=this[r++];){if(n===di)return t[k];t[k]=n}return this},scrollTop:function(n){for(var t,r=0;t=this[r++];){if(n===di)return t[I];t[I]=n}return this},val:function(n){var t=this[0];return n?(t.value=n,this):t.value},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(n){return M(this[0<=n?n:this[xi.l]+n])},find:function(t){var r,e=[];return this.each(function(){var n=this.querySelectorAll(t);for(r=0;r<n[xi.l];r++)e.push(n[r])}),M(e)},children:function(n){var t,r,e,i=[];return this.each(function(){for(r=this.children,e=0;e<r[xi.l];e++)t=r[e],(!n||t.matches&&t.matches(n)||w(t,n))&&i.push(t)}),M(i)},parent:function(n){var t,r=[];return this.each(function(){t=this.parentNode,n&&!M(t).is(n)||r.push(t)}),M(r)},is:function(n){var t,r;for(r=0;r<this[xi.l];r++){if(t=this[r],":visible"===n)return _(t);if(":hidden"===n)return!_(t);if(t.matches&&t.matches(n)||w(t,n))return!0}return!1},contents:function(){var n,t,r=[];return this.each(function(){for(n=this.childNodes,t=0;t<n[xi.l];t++)r.push(n[t])}),M(r)},each:function(n){return e(this,n)},animate:function(n,t,r,e){return this.each(function(){x(this,n,t,r,e)})},stop:function(n,t){return this.each(function(){!function f(n,t,r){for(var e,i,o,u=0;u<T[xi.l];u++)if((e=T[u]).el===n){if(0<e.q[xi.l]){if((i=e.q[0]).stop=!0,Oi.cAF()(i.frame),e.q.splice(0,1),r)for(o in i.props)W(n,o,i.props[o]);t?e.q=[]:N(e,!1)}break}}(this,n,t)})}},b(M,{extend:b,inArray:H,isEmptyObject:L,isPlainObject:R,each:e}),M);function b(){var n,t,r,e,i,o,u=arguments[0]||{},f=1,a=arguments[xi.l],c=!1;for(d(u)==wi&&(c=u,u=arguments[1]||{},f=2),d(u)!=pi&&!d(u)==bi&&(u={}),a===f&&(u=M,--f);f<a;f++)if(null!=(i=arguments[f]))for(e in i)n=u[e],u!==(r=i[e])&&(c&&r&&(R(r)||(t=Oi.isA(r)))?(o=t?(t=!1,n&&Oi.isA(n)?n:[]):n&&R(n)?n:{},u[e]=b(c,o,r)):r!==di&&(u[e]=r));return u}function H(n,t,r){for(var e=r||0;e<t[xi.l];e++)if(t[e]===n)return e;return-1}function E(n){return d(n)==bi}function L(n){for(var t in n)return!1;return!0}function R(n){if(!n||d(n)!=pi)return!1;var t,r=xi.p,e=Object[r].hasOwnProperty,i=e.call(n,"constructor"),o=n.constructor&&n.constructor[r]&&e.call(n.constructor[r],"isPrototypeOf");if(n.constructor&&!i&&!o)return!1;for(t in n);return d(t)==f||e.call(n,t)}function e(n,t){var r=0;if(m(n))for(;r<n[xi.l]&&!1!==t.call(n[r],r,n[r]);r++);else for(r in n)if(!1===t.call(n[r],r,n[r]))break;return n}function m(n){var t=!!n&&[xi.l]in n&&n[xi.l],r=d(n);return!E(r)&&(r==mi||0===t||d(t)==yi&&0<t&&t-1 in n)}function g(n){return(n.match(v)||[]).join(h)}function w(n,t){for(var r=(n.parentNode||hi).querySelectorAll(t)||[],e=r[xi.l];e--;)if(r[e]==n)return 1}function i(n,t,r){if(Oi.isA(r))for(var e=0;e<r[xi.l];e++)i(n,t,r[e]);else d(r)==gi?n.insertAdjacentHTML(t,r):n.insertAdjacentElement(t,r.nodeType?r:r[0])}function y(n,t,r){try{n[xi.s][t]!==di&&(n[xi.s][t]=function e(n,t){p[n.toLowerCase()]||d(t)!=yi||(t+="px");return t}(t,r))}catch(i){}}function N(n,t){var r,e;!1!==t&&n.q.splice(0,1),0<n.q[xi.l]?(e=n.q[0],x(n.el,e.props,e.duration,e.easing,e.complete,!0)):-1<(r=H(n,T))&&T.splice(r,1)}function W(n,t,r){t===k||t===I?n[t]=r:y(n,t,r)}function x(n,t,r,e,i,o){var u,f,a,c,s,l,v=R(r),h={},d={},p=0;for(l=v?(e=r.easing,r.start,a=r.progress,c=r.step,s=r.specialEasing,i=r.complete,r.duration):r,s=s||{},l=l||400,e=e||"swing",o=o||!1;p<T[xi.l];p++)if(T[p].el===n){f=T[p];break}for(u in f||(f={el:n,q:[]},T.push(f)),t)h[u]=u===k||u===I?n[u]:M(n).css(u);for(u in h)h[u]!==t[u]&&t[u]!==di&&(d[u]=t[u]);if(L(d))o&&N(f);else{var b,m,g,w,y,x,_,O,S,z=o?0:H(C,f.q),C={props:d,duration:v?r:l,easing:e,complete:i};if(-1===z&&(z=f.q[xi.l],f.q.push(C)),0===z)if(0<l)_=Oi.now(),O=function(){for(u in b=Oi.now(),S=b-_,m=C.stop||l<=S,g=1-(Si.max(0,_+l-b)/l||0),d)w=parseFloat(h[u]),y=parseFloat(d[u]),x=(y-w)*A[s[u]||e](g,g*l,0,1,l)+w,W(n,u,x),E(c)&&c(x,{elem:n,prop:u,start:w,now:x,end:y,pos:g,options:{easing:e,speacialEasing:s,duration:l,complete:i,step:c},startTime:_});E(a)&&a({},g,Si.max(0,l-S)),m?(N(f),E(i)&&i()):C.frame=Oi.rAF()(O)},C.frame=Oi.rAF()(O);else{for(u in d)W(n,u,d[u]);N(f)}}}function _(n){return!!(n[xi.oW]||n[xi.oH]||n.getClientRects()[xi.l])}function M(n){if(0===arguments[xi.l])return this;var t,r,e=new M,i=n,o=0;if(d(n)==gi)for(i=[],t="<"===n.charAt(0)?((r=hi.createElement("div")).innerHTML=n,r.children):hi.querySelectorAll(n);o<t[xi.l];o++)i.push(t[o]);if(i){for(d(i)==gi||m(i)&&i!==vi&&i!==i.self||(i=[i]),o=0;o<i[xi.l];o++)e[o]=i[o];e[xi.l]=i[xi.l]}return e}var O,S,ki,z,C,D,F,P,j,B,Q,U,V,$,Ii,Ti=(O=[],S="__overlayScrollbars__",function(n,t){var r=arguments[xi.l];if(r<1)return O;if(t)n[S]=t,O.push(n);else{var e=Oi.inA(n,O);if(-1<e){if(!(1<r))return O[e][S];delete n[S],O.splice(e,1)}}}),q=($=[],D=Oi.type,U={className:["os-theme-dark",[n,gi]],resize:["none","n:none b:both h:horizontal v:vertical"],sizeAutoCapable:P=[!0,wi],clipAlways:P,normalizeRTL:P,paddingAbsolute:j=[!(F=[wi,yi,gi,mi,pi,bi,n]),wi],autoUpdate:[null,[n,wi]],autoUpdateInterval:[33,yi],updateOnLoad:[["img"],[gi,mi,n]],nativeScrollbarsOverlaid:{showNativeScrollbars:j,initialize:P},overflowBehavior:{x:["scroll",Q="v-h:visible-hidden v-s:visible-scroll s:scroll h:hidden"],y:["scroll",Q]},scrollbars:{visibility:["auto","v:visible h:hidden a:auto"],autoHide:["never","n:never s:scroll l:leave m:move"],autoHideDelay:[800,yi],dragScrolling:P,clickScrolling:j,touchSupport:P,snapHandle:j},textarea:{dynWidth:j,dynHeight:j,inheritedAttrs:[["style","class"],[gi,mi,n]]},callbacks:{onInitialized:B=[null,[n,bi]],onInitializationWithdrawn:B,onDestroyed:B,onScrollStart:B,onScroll:B,onScrollStop:B,onOverflowChanged:B,onOverflowAmountChanged:B,onDirectionChanged:B,onContentSizeChanged:B,onHostSizeChanged:B,onUpdated:B}},Ii={g:(V=function(i){var o=function(n){var t,r,e;for(t in n)n[xi.hOP](t)&&(r=n[t],(e=D(r))==mi?n[t]=r[i?1:0]:e==pi&&(n[t]=o(r)));return n};return o(Ci.extend(!0,{},U))})(),_:V(!0),O:function(n,t,I,r){var e={},i={},o=Ci.extend(!0,{},n),T=Ci.inArray,A=Ci.isEmptyObject,H=function(n,t,r,e,i,o){for(var u in t)if(t[xi.hOP](u)&&n[xi.hOP](u)){var f,a,c,s,l,v,h,d,p=!1,b=!1,m=t[u],g=D(m),w=g==pi,y=Oi.isA(m)?m:[m],x=r[u],_=n[u],O=D(_),S=o?o+".":"",z='The option "'+S+u+"\" wasn't set, because",C=[],k=[];if(x=x===di?{}:x,w&&O==pi)e[u]={},i[u]={},H(_,m,x,e[u],i[u],S+u),Ci.each([n,e,i],function(n,t){A(t[u])&&delete t[u]});else if(!w){for(v=0;v<y[xi.l];v++)if(l=y[v],c=(g=D(l))==gi&&-1===T(l,F))for(C.push(gi),f=l.split(" "),k=k.concat(f),h=0;h<f[xi.l];h++){for(s=(a=f[h].split(":"))[0],d=0;d<a[xi.l];d++)if(_===a[d]){p=!0;break}if(p)break}else if(C.push(l),O===l){p=!0;break}p?((b=_!==x)&&(e[u]=_),(c?T(x,a)<0:b)&&(i[u]=c?s:_)):I&&console.warn(z+" it doesn't accept the type [ "+O.toUpperCase()+' ] with the value of "'+_+'".\r\nAccepted types are: [ '+C.join(", ").toUpperCase()+" ]."+(0<k[length]?"\r\nValid strings are: [ "+k.join(", ").split(":").join(", ")+" ].":"")),delete n[u]}}};return H(o,t,r||{},e,i),!A(o)&&I&&console.warn("The following options are discarded due to invalidity:\r\n"+vi.JSON.stringify(o,null,2)),{S:e,z:i}}},(ki=vi.OverlayScrollbars=function(n,r,e){if(0===arguments[xi.l])return this;var i,t,o=[],u=Ci.isPlainObject(r);return n?(n=n[xi.l]!=di?n:[n[0]||n],X(),0<n[xi.l]&&(u?Ci.each(n,function(n,t){(i=t)!==di&&o.push(K(i,r,e,z,C))}):Ci.each(n,function(n,t){i=Ti(t),("!"===r&&ki.valid(i)||Oi.type(r)==bi&&r(t,i)||r===di)&&o.push(i)}),t=1===o[xi.l]?o[0]:o),t):u||!r?t:o}).globals=function(){X();var n=Ci.extend(!0,{},z);return delete n.msie,n},ki.defaultOptions=function(n){X();var t=z.defaultOptions;if(n===di)return Ci.extend(!0,{},t);z.defaultOptions=Ci.extend(!0,{},t,Ii.O(n,Ii._,!0,t).S)},ki.valid=function(n){return n instanceof ki&&!n.getState().destroyed},ki.extension=function(n,t,r){var e=Oi.type(n)==gi,i=arguments[xi.l],o=0;if(i<1||!e)return Ci.extend(!0,{length:$[xi.l]},$);if(e)if(Oi.type(t)==bi)$.push({name:n,extensionFactory:t,defaultOptions:r});else for(;o<$[xi.l];o++)if($[o].name===n){if(!(1<i))return Ci.extend(!0,{},$[o]);$.splice(o,1)}},ki);function X(){z=z||new Y(Ii.g),C=C||new G(z)}function Y(n){var _=this,i="overflow",O=Ci("body"),S=Ci('<div id="os-dummy-scrollbar-size"><div></div></div>'),o=S[0],e=Ci(S.children("div").eq(0));O.append(S),S.hide().show();var t,r,u,f,a,c,s,l,v,h=z(o),d={x:0===h.x,y:0===h.y},p=(r=vi.navigator.userAgent,f="substring",a=r[u="indexOf"]("MSIE "),c=r[u]("Trident/"),s=r[u]("Edge/"),l=r[u]("rv:"),v=parseInt,0<a?t=v(r[f](a+5,r[u](".",a)),10):0<c?t=v(r[f](l+3,r[u](".",l)),10):0<s&&(t=v(r[f](s+5,r[u](".",s)),10)),t);function z(n){return{x:n[xi.oH]-n[xi.cH],y:n[xi.oW]-n[xi.cW]}}Ci.extend(_,{defaultOptions:n,msie:p,autoUpdateLoop:!1,autoUpdateRecommended:!Oi.mO(),nativeScrollbarSize:h,nativeScrollbarIsOverlaid:d,nativeScrollbarStyling:function(){var n=!1;S.addClass("os-viewport-native-scrollbars-invisible");try{n="none"===S.css("scrollbar-width")&&(9<p||!p)||"none"===vi.getComputedStyle(o,"::-webkit-scrollbar").getPropertyValue("display")}catch(t){}return n}(),overlayScrollbarDummySize:{x:30,y:30},cssCalc:_i.d("width","calc","(1px)")||null,restrictedMeasuring:function(){S.css(i,"hidden");var n=o[xi.sW],t=o[xi.sH];S.css(i,"visible");var r=o[xi.sW],e=o[xi.sH];return n-r!=0||t-e!=0}(),rtlScrollBehavior:function(){S.css({"overflow-y":"hidden","overflow-x":"scroll",direction:"rtl"}).scrollLeft(0);var n=S.offset(),t=e.offset();S.scrollLeft(-999);var r=e.offset();return{i:n.left===t.left,n:t.left!==r.left}}(),supportTransform:!!_i.v("transform"),supportTransition:!!_i.v("transition"),supportPassiveEvents:function(){var n=!1;try{vi.addEventListener("test",null,Object.defineProperty({},"passive",{get:function(){n=!0}}))}catch(t){}return n}(),supportResizeObserver:!!Oi.rO(),supportMutationObserver:!!Oi.mO()}),S.removeAttr(xi.s).remove(),function(){if(!d.x||!d.y){var m=Si.abs,g=Oi.wW(),w=Oi.wH(),y=x();Ci(vi).on("resize",function(){if(0<Ti().length){var n=Oi.wW(),t=Oi.wH(),r=n-g,e=t-w;if(0==r&&0==e)return;var i,o=Si.round(n/(g/100)),u=Si.round(t/(w/100)),f=m(r),a=m(e),c=m(o),s=m(u),l=x(),v=2<f&&2<a,h=!function b(n,t){var r=m(n),e=m(t);return r!==e&&r+1!==e&&r-1!==e}(c,s),d=v&&h&&(l!==y&&0<y),p=_.nativeScrollbarSize;d&&(O.append(S),i=_.nativeScrollbarSize=z(S[0]),S.remove(),p.x===i.x&&p.y===i.y||Ci.each(Ti(),function(){Ti(this)&&Ti(this).update("zoom")})),g=n,w=t,y=l}})}function x(){var n=vi.screen.deviceXDPI||0,t=vi.screen.logicalXDPI||1;return vi.devicePixelRatio||n/t}}()}function G(r){var c,e=Ci.inArray,s=Oi.now,l="autoUpdate",v=xi.l,h=[],d=[],p=!1,b=33,m=s(),g=function(){if(0<h[v]&&p){c=Oi.rAF()(function(){g()});var n,t,r,e,i,o,u=s(),f=u-m;if(b<f){m=u-f%b,n=33;for(var a=0;a<h[v];a++)(t=h[a])!==di&&(e=(r=t.options())[l],i=Si.max(1,r.autoUpdateInterval),o=s(),(!0===e||null===e)&&o-d[a]>i&&(t.update("auto"),d[a]=new Date(o+=i)),n=Si.max(1,Si.min(n,i)));b=n}}else b=33};this.add=function(n){-1===e(n,h)&&(h.push(n),d.push(s()),0<h[v]&&!p&&(p=!0,r.autoUpdateLoop=p,g()))},this.remove=function(n){var t=e(n,h);-1<t&&(d.splice(t,1),h.splice(t,1),0===h[v]&&p&&(p=!1,r.autoUpdateLoop=p,c!==di&&(Oi.cAF()(c),c=-1)))}}function K(r,n,t,xt,_t){var cn=Oi.type,sn=Ci.inArray,h=Ci.each,Ot=new ki,e=Ci[xi.p];if(ht(r)){if(Ti(r)){var i=Ti(r);return i.options(n),i}var St,zt,Ct,kt,D,It,Tt,At,F,ln,w,T,d,Ht,Et,Lt,Rt,y,p,Nt,Wt,Mt,Dt,Ft,Pt,jt,Bt,Qt,Ut,o,u,Vt,$t,qt,f,P,c,j,Xt,Yt,Gt,Kt,Jt,Zt,nr,tr,rr,er,ir,a,s,l,v,b,m,x,A,or,ur,fr,H,ar,cr,sr,lr,vr,hr,dr,pr,br,mr,gr,wr,yr,xr,_r,E,Or,Sr,zr,Cr,kr,Ir,Tr,Ar,g,_,Hr,Er,Lr,Rr,Nr,Wr,Mr,Dr,Fr,Pr,jr,Br,Qr,Ur,O,S,z,C,Vr,$r,k,I,qr,Xr,Yr,Gr,Kr,B,Q,Jr,Zr,ne,te,re={},vn={},hn={},ee={},ie={},L="-hidden",oe="margin-",ue="padding-",fe="border-",ae="top",ce="right",se="bottom",le="left",ve="min-",he="max-",de="width",pe="height",be="float",me="",ge="auto",dn="sync",we="scroll",ye="100%",pn="x",bn="y",R=".",xe=" ",N="scrollbar",W="-horizontal",M="-vertical",_e=we+"Left",Oe=we+"Top",U="mousedown touchstart",V="mouseup touchend touchcancel",$="mousemove touchmove",q="mouseenter",X="mouseleave",Y="keydown",G="keyup",K="selectstart",J="transitionend webkitTransitionEnd oTransitionEnd",Z="__overlayScrollbarsRO__",nn="os-",tn="os-html",rn="os-host",en=rn+"-foreign",on=rn+"-textarea",un=rn+"-"+N+W+L,fn=rn+"-"+N+M+L,an=rn+"-transition",Se=rn+"-rtl",ze=rn+"-resize-disabled",Ce=rn+"-scrolling",ke=rn+"-overflow",Ie=(ke=rn+"-overflow")+"-x",Te=ke+"-y",mn="os-textarea",gn=mn+"-cover",wn="os-padding",yn="os-viewport",Ae=yn+"-native-scrollbars-invisible",xn=yn+"-native-scrollbars-overlaid",_n="os-content",He="os-content-arrange",Ee="os-content-glue",Le="os-size-auto-observer",On="os-resize-observer",Sn="os-resize-observer-item",zn=Sn+"-final",Cn="os-text-inherit",kn=nn+N,In=kn+"-track",Tn=In+"-off",An=kn+"-handle",Hn=An+"-off",En=kn+"-unusable",Ln=kn+"-"+ge+L,Rn=kn+"-corner",Re=Rn+"-resize",Ne=Re+"-both",We=Re+W,Me=Re+M,Nn=kn+W,Wn=kn+M,Mn="os-dragging",De="os-theme-none",Dn=[Ae,xn,Tn,Hn,En,Ln,Re,Ne,We,Me,Mn].join(xe),Fn=[],Pn=[xi.ti],jn={},Fe={},Pe=42,Bn="load",Qn=[],Un={},Vn=["wrap","cols","rows"],$n=[xi.i,xi.c,xi.s,"open"].concat(Pn),qn=[];return Ot.sleep=function(){Ut=!0},Ot.update=function(n){var t,r,e,i,o;if(!Et)return cn(n)==gi?n===ge?(t=function u(){if(!Ut&&!Vr){var r,e,i,o=[],n=[{C:Yt,k:$n.concat(":visible")},{C:Lt?Xt:di,k:Vn}];return h(n,function(n,t){(r=t.C)&&h(t.k,function(n,t){e=":"===t.charAt(0)?r.is(t):r.attr(t),i=Un[t],fi(e,i)&&o.push(t),Un[t]=e})}),it(o),0<o[xi.l]}}(),r=function a(){if(Ut)return!1;var n,t,r,e,i=oi(),o=Lt&&br&&!Fr?Xt.val().length:0,u=!Vr&&br&&!Lt,f={};return u&&(n=nr.css(be),f[be]=Qt?ce:le,f[de]=ge,nr.css(f)),e={w:i[xi.sW]+o,h:i[xi.sH]+o},u&&(f[be]=n,f[de]=ye,nr.css(f)),t=Ve(),r=fi(e,g),g=e,r||t}(),(e=t||r)&&qe({I:r,T:Ht?di:Vt})):n===dn?Vr?(i=z(O.takeRecords()),o=C(S.takeRecords())):i=Ot.update(ge):"zoom"===n&&qe({A:!0,I:!0}):(n=Ut||n,Ut=!1,Ot.update(dn)&&!n||qe({H:n})),Xe(),e||i||o},Ot.options=function(n,t){var r,e={};if(Ci.isEmptyObject(n)||!Ci.isPlainObject(n)){if(cn(n)!=gi)return u;if(!(1<arguments.length))return bt(u,n);!function a(n,t,r){for(var e=t.split(R),i=e.length,o=0,u={},f=u;o<i;o++)u=u[e[o]]=o+1<i?{}:r;Ci.extend(n,f,!0)}(e,n,t),r=ot(e)}else r=ot(n);Ci.isEmptyObject(r)||qe({T:r})},Ot.destroy=function(){if(!Et){for(var n in _t.remove(Ot),Qe(),je(Kt),je(Gt),jn)Ot.removeExt(n);for(;0<qn[xi.l];)qn.pop()();Ue(!0),rr&&gt(rr),tr&&gt(tr),Wt&&gt(Gt),at(!0),st(!0),ut(!0);for(var t=0;t<Qn[xi.l];t++)Ci(Qn[t]).off(Bn,rt);Qn=di,Ut=Et=!0,Ti(r,0),ti("onDestroyed")}},Ot.scroll=function(n,t,r,e){if(0===arguments.length||n===di){var i=Wr&&Qt&&Ct.i,o=Wr&&Qt&&Ct.n,u=vn.L,f=vn.R,a=vn.N;return f=i?1-f:f,u=i?a-u:u,a*=o?-1:1,{position:{x:u*=o?-1:1,y:hn.L},ratio:{x:f,y:hn.R},max:{x:a,y:hn.N},handleOffset:{x:vn.W,y:hn.W},handleLength:{x:vn.M,y:hn.M},handleLengthRatio:{x:vn.D,y:hn.D},trackLength:{x:vn.F,y:hn.F},snappedHandleOffset:{x:vn.P,y:hn.P},isRTL:Qt,isRTLNormalized:Wr}}Ot.update(dn);var c,s,l,v,h,g,w,d,p,y=Wr,b=[pn,le,"l"],m=[bn,ae,"t"],x=["+=","-=","*=","/="],_=cn(t)==pi,O=_?t.complete:e,S={},z={},C="begin",k="nearest",I="never",T="ifneeded",A=xi.l,H=[pn,bn,"xy","yx"],E=[C,"end","center",k],L=["always",I,T],R=n[xi.hOP]("el"),N=R?n.el:n,W=!!(N instanceof Ci||zi)&&N instanceof zi,M=!W&&ht(N),D=function(){s&&Je(!0),l&&Je(!1)},F=cn(O)!=bi?di:function(){D(),O()};function P(n,t){for(c=0;c<t[A];c++)if(n===t[c])return 1}function j(n,t){var r=n?b:m;if(t=cn(t)==gi||cn(t)==yi?[t,t]:t,Oi.isA(t))return n?t[0]:t[1];if(cn(t)==pi)for(c=0;c<r[A];c++)if(r[c]in t)return t[r[c]]}function B(n,t){var r,e,i,o,u=cn(t)==gi,f=n?vn:hn,a=f.L,c=f.N,s=Qt&&n,l=s&&Ct.n&&!y,v="replace",h=eval;if((e=u?(2<t[A]&&(o=t.substr(0,2),-1<sn(o,x)&&(r=o)),t=(t=r?t.substr(2):t)[v](/min/g,0)[v](/</g,0)[v](/max/g,(l?"-":me)+ye)[v](/>/g,(l?"-":me)+ye)[v](/px/g,me)[v](/%/g," * "+c*(s&&Ct.n?-1:1)/100)[v](/vw/g," * "+ee.w)[v](/vh/g," * "+ee.h),ii(isNaN(t)?ii(h(t),!0).toFixed():t)):t)!==di&&!isNaN(e)&&cn(e)==yi){var d=y&&s,p=a*(d&&Ct.n?-1:1),b=d&&Ct.i,m=d&&Ct.n;switch(p=b?c-p:p,r){case"+=":i=p+e;break;case"-=":i=p-e;break;case"*=":i=p*e;break;case"/=":i=p/e;break;default:i=e}i=b?c-i:i,i*=m?-1:1,i=s&&Ct.n?Si.min(0,Si.max(c,i)):Si.max(0,Si.min(c,i))}return i===a?di:i}function Q(n,t,r,e){var i,o,u=[r,r],f=cn(n);if(f==t)n=[n,n];else if(f==mi){if(2<(i=n[A])||i<1)n=u;else for(1===i&&(n[1]=r),c=0;c<i;c++)if(o=n[c],cn(o)!=t||!P(o,e)){n=u;break}}else n=f==pi?[n[pn]||r,n[bn]||r]:u;return{x:n[0],y:n[1]}}function U(n){var t,r,e=[],i=[ae,ce,se,le];for(c=0;c<n[A]&&c!==i[A];c++)t=n[c],(r=cn(t))==wi?e.push(t?ii(p.css(oe+i[c])):0):e.push(r==yi?t:0);return e}if(W||M){var V,$=R?n.margin:0,q=R?n.axis:0,X=R?n.scroll:0,Y=R?n.block:0,G=[0,0,0,0],K=cn($);if(0<(p=W?N:Ci(N))[A]){$=K==yi||K==wi?U([$,$,$,$]):K==mi?2===(V=$[A])?U([$[0],$[1],$[0],$[1]]):4<=V?U($):G:K==pi?U([$[ae],$[ce],$[se],$[le]]):G,h=P(q,H)?q:"xy",g=Q(X,gi,"always",L),w=Q(Y,gi,C,E),d=$;var J=vn.L,Z=hn.L,nn=Jt.offset(),tn=p.offset(),rn={x:g.x==I||h==bn,y:g.y==I||h==pn};tn[ae]-=d[0],tn[le]-=d[3];var en={x:Si.round(tn[le]-nn[le]+J),y:Si.round(tn[ae]-nn[ae]+Z)};if(Qt&&(Ct.n||Ct.i||(en.x=Si.round(nn[le]-tn[le]+J)),Ct.n&&y&&(en.x*=-1),Ct.i&&y&&(en.x=Si.round(nn[le]-tn[le]+(vn.N-J)))),w.x!=C||w.y!=C||g.x==T||g.y==T||Qt){var on=p[0],un=ln?on[xi.bCR]():{width:on[xi.oW],height:on[xi.oH]},fn={w:un[de]+d[3]+d[1],h:un[pe]+d[0]+d[2]},an=function(n){var t=ni(n),r=t.j,e=t.B,i=t.Q,o=w[i]==(n&&Qt?C:"end"),u="center"==w[i],f=w[i]==k,a=g[i]==I,c=g[i]==T,s=ee[r],l=nn[e],v=fn[r],h=tn[e],d=u?2:1,p=h+v/2,b=l+s/2,m=v<=s&&l<=h&&h+v<=l+s;a?rn[i]=!0:rn[i]||((f||c)&&(rn[i]=c&&m,o=v<s?b<p:p<b),en[i]-=o||u?(s/d-v/d)*(n&&Qt&&y?-1:1):0)};an(!0),an(!1)}rn.y&&delete en.y,rn.x&&delete en.x,n=en}}S[_e]=B(!0,j(!0,n)),S[Oe]=B(!1,j(!1,n)),s=S[_e]!==di,l=S[Oe]!==di,(s||l)&&(0<t||_)?_?(t.complete=F,Zt.animate(S,t)):(v={duration:t,complete:F},Oi.isA(r)||Ci.isPlainObject(r)?(z[_e]=r[0]||r.x,z[Oe]=r[1]||r.y,v.specialEasing=z):v.easing=r,Zt.animate(S,v)):(s&&Zt[_e](S[_e]),l&&Zt[Oe](S[Oe]),D())},Ot.scrollStop=function(n,t,r){return Zt.stop(n,t,r),Ot},Ot.getElements=function(n){var t={target:or,host:ur,padding:ar,viewport:cr,content:sr,scrollbarHorizontal:{scrollbar:a[0],track:s[0],handle:l[0]},scrollbarVertical:{scrollbar:v[0],track:b[0],handle:m[0]},scrollbarCorner:ir[0]};return cn(n)==gi?bt(t,n):t},Ot.getState=function(n){function t(n){if(!Ci.isPlainObject(n))return n;var r=ai({},n),t=function(n,t){r[xi.hOP](n)&&(r[t]=r[n],delete r[n])};return t("w",de),t("h",pe),delete r.c,r}var r={destroyed:!!t(Et),sleeping:!!t(Ut),autoUpdate:t(!Vr),widthAuto:t(br),heightAuto:t(mr),padding:t(wr),overflowAmount:t(kr),hideOverflow:t(pr),hasOverflow:t(dr),contentScrollSize:t(vr),viewportSize:t(ee),hostSize:t(lr),documentMixed:t(y)};return cn(n)==gi?bt(r,n):r},Ot.ext=function(n){var t,r="added removed on contract".split(" "),e=0;if(cn(n)==gi){if(jn[xi.hOP](n))for(t=ai({},jn[n]);e<r.length;e++)delete t[r[e]]}else for(e in t={},jn)t[e]=ai({},Ot.ext(e));return t},Ot.addExt=function(n,t){var r,e,i,o,u=ki.extension(n),f=!0;if(u){if(jn[xi.hOP](n))return Ot.ext(n);if((r=u.extensionFactory.call(Ot,ai({},u.defaultOptions),Ci,Oi))&&(i=r.contract,cn(i)==bi&&(o=i(vi),f=cn(o)==wi?o:f),f))return e=(jn[n]=r).added,cn(e)==bi&&e(t),Ot.ext(n)}else console.warn('A extension with the name "'+n+"\" isn't registered.")},Ot.removeExt=function(n){var t,r=jn[n];return!!r&&(delete jn[n],t=r.removed,cn(t)==bi&&t(),!0)},ki.valid(function yt(n,t,r){var e,i;return o=xt.defaultOptions,It=xt.nativeScrollbarStyling,At=ai({},xt.nativeScrollbarSize),St=ai({},xt.nativeScrollbarIsOverlaid),zt=ai({},xt.overlayScrollbarDummySize),Ct=ai({},xt.rtlScrollBehavior),ot(ai({},o,t)),Tt=xt.cssCalc,D=xt.msie,kt=xt.autoUpdateRecommended,F=xt.supportTransition,ln=xt.supportTransform,w=xt.supportPassiveEvents,T=xt.supportResizeObserver,d=xt.supportMutationObserver,xt.restrictedMeasuring,P=Ci(n.ownerDocument),A=P[0],f=Ci(A.defaultView||A.parentWindow),x=f[0],c=wt(P,"html"),j=wt(c,"body"),Xt=Ci(n),or=Xt[0],Lt=Xt.is("textarea"),Rt=Xt.is("body"),y=A!==hi,p=Lt?Xt.hasClass(mn)&&Xt.parent().hasClass(_n):Xt.hasClass(rn)&&Xt.children(R+wn)[xi.l],St.x&&St.y&&!Vt.nativeScrollbarsOverlaid.initialize?(ti("onInitializationWithdrawn"),p&&(ut(!0),at(!0),st(!0)),Ut=Et=!0):(Rt&&((e={}).l=Si.max(Xt[_e](),c[_e](),f[_e]()),e.t=Si.max(Xt[Oe](),c[Oe](),f[Oe]()),i=function(){Zt.removeAttr(xi.ti),Xn(Zt,U,i,!0,!0)}),ut(),at(),st(),ft(),ct(!0),ct(!1),function s(){var r,t=x.top!==x,e={},i={},o={};function u(n){if(a(n)){var t=c(n),r={};(ne||Zr)&&(r[de]=i.w+(t.x-e.x)*o.x),(te||Zr)&&(r[pe]=i.h+(t.y-e.y)*o.y),Yt.css(r),Oi.stpP(n)}else f(n)}function f(n){var t=n!==di;Xn(P,[K,$,V],[tt,u,f],!0),si(j,Mn),ir.releaseCapture&&ir.releaseCapture(),t&&(r&&Be(),Ot.update(ge)),r=!1}function a(n){var t=(n.originalEvent||n).touches!==di;return!Ut&&!Et&&(1===Oi.mBtn(n)||t)}function c(n){return D&&t?{x:n.screenX,y:n.screenY}:Oi.page(n)}Yn(ir,U,function(n){a(n)&&!Jr&&(Vr&&(r=!0,Qe()),e=c(n),i.w=ur[xi.oW]-(Nt?0:Mt),i.h=ur[xi.oH]-(Nt?0:Dt),o=vt(),Xn(P,[K,$,V],[tt,u,f]),ci(j,Mn),ir.setCapture&&ir.setCapture(),Oi.prvD(n),Oi.stpP(n))})}(),Gn(),je(Kt,Kn),Rt&&(Zt[_e](e.l)[Oe](e.t),hi.activeElement==n&&cr.focus&&(Zt.attr(xi.ti,"-1"),cr.focus(),Xn(Zt,U,i,!1,!0))),Ot.update(ge),Ht=!0,ti("onInitialized"),h(Fn,function(n,t){ti(t.n,t.a)}),Fn=[],cn(r)==gi&&(r=[r]),Oi.isA(r)?h(r,function(n,t){Ot.addExt(t)}):Ci.isPlainObject(r)&&h(r,function(n,t){Ot.addExt(n,t)}),setTimeout(function(){F&&!Et&&ci(Yt,an)},333)),Ot}(r,n,t))&&Ti(r,Ot),Ot}function Xn(n,t,r,e,i){var o=Oi.isA(t)&&Oi.isA(r),u=e?"removeEventListener":"addEventListener",f=e?"off":"on",a=!o&&t.split(xe),c=0,s=Ci.isPlainObject(i),l=w&&(s?i.U:i)||!1,v=s&&(i.V||!1),h=w?{passive:l,capture:v}:v;if(o)for(;c<t[xi.l];c++)Xn(n,t[c],r[c],e,i);else for(;c<a[xi.l];c++)w?n[0][u](a[c],r,h):n[f](a[c],r)}function Yn(n,t,r,e){Xn(n,t,r,!1,e),qn.push(Oi.bind(Xn,0,n,t,r,!0,e))}function je(n,t){if(n){var r=Oi.rO(),e="animationstart mozAnimationStart webkitAnimationStart MSAnimationStart",i="childNodes",o=3333333,u=function(){n[Oe](o)[_e](Qt?Ct.n?-o:Ct.i?0:o:o),t()};if(t){if(T)((k=n.addClass("observed").append(ui(On)).contents()[0])[Z]=new r(u)).observe(k);else if(9<D||!kt){n.prepend(ui(On,ui({c:Sn,dir:"ltr"},ui(Sn,ui(zn))+ui(Sn,ui({c:zn,style:"width: 200%; height: 200%"})))));var f,a,c,s,l=n[0][i][0][i][0],v=Ci(l[i][1]),h=Ci(l[i][0]),d=Ci(h[0][i][0]),p=l[xi.oW],b=l[xi.oH],m=xt.nativeScrollbarSize,g=function(){h[_e](o)[Oe](o),v[_e](o)[Oe](o)},w=function(){a=0,f&&(p=c,b=s,u())},y=function(n){return c=l[xi.oW],s=l[xi.oH],f=c!=p||s!=b,n&&f&&!a?(Oi.cAF()(a),a=Oi.rAF()(w)):n||w(),g(),n&&(Oi.prvD(n),Oi.stpP(n)),!1},x={},_={};ri(_,me,[-2*(m.y+1),-2*m.x,-2*m.y,-2*(m.x+1)]),Ci(l).css(_),h.on(we,y),v.on(we,y),n.on(e,function(){y(!1)}),x[de]=o,x[pe]=o,d.css(x),g()}else{var O=A.attachEvent,S=D!==di;if(O)n.prepend(ui(On)),wt(n,R+On)[0].attachEvent("onresize",u);else{var z=A.createElement(pi);z.setAttribute(xi.ti,"-1"),z.setAttribute(xi.c,On),z.onload=function(){var n=this.contentDocument.defaultView;n.addEventListener("resize",u),n.document.documentElement.style.display="none"},z.type="text/html",S&&n.prepend(z),z.data="about:blank",S||n.prepend(z),n.on(e,u)}}if(n[0]===H){var C=function(){var n=Yt.css("direction"),t={},r=0,e=!1;return n!==E&&(r="ltr"===n?(t[le]=0,t[ce]=ge,o):(t[le]=ge,t[ce]=0,Ct.n?-o:Ct.i?0:o),Kt.children().eq(0).css(t),Kt[_e](r)[Oe](o),E=n,e=!0),e};C(),Yn(n,we,function(n){return C()&&qe(),Oi.prvD(n),Oi.stpP(n),!1})}}else if(T){var k,I=(k=n.contents()[0])[Z];I&&(I.disconnect(),delete k[Z])}else gt(n.children(R+On).eq(0))}}function Gn(){if(d){var o,u,f,a,c,s,r,e,i,l,n=Oi.mO(),v=Oi.now();C=function(n){var t=!1;return Ht&&!Ut&&(h(n,function(){return!(t=function o(n){var t=n.attributeName,r=n.target,e=n.type,i="closest";if(r===sr)return null===t;if("attributes"===e&&(t===xi.c||t===xi.s)&&!Lt){if(t===xi.c&&Ci(r).hasClass(rn))return et(n.oldValue,r.className);if(typeof r[i]!=bi)return!0;if(null!==r[i](R+On)||null!==r[i](R+kn)||null!==r[i](R+Rn))return!1}return!0}(this))}),t&&(e=Oi.now(),i=mr||br,l=function(){Et||(v=e,Lt&&$e(),i?qe():Ot.update(ge))},clearTimeout(r),11<e-v||!i?l():r=setTimeout(l,11))),t},O=new n(z=function(n){var t,r=!1,e=!1,i=[];return Ht&&!Ut&&(h(n,function(){o=(t=this).target,u=t.attributeName,f=u===xi.c,a=t.oldValue,c=o.className,p&&f&&!e&&-1<a.indexOf(en)&&c.indexOf(en)<0&&(s=lt(!0),ur.className=c.split(xe).concat(a.split(xe).filter(function(n){return n.match(s)})).join(xe),r=e=!0),r=r||(f?et(a,c):u!==xi.s||a!==o[xi.s].cssText),i.push(u)}),it(i),r&&Ot.update(e||ge)),r}),S=new n(C)}}function Be(){d&&!Vr&&(O.observe(ur,{attributes:!0,attributeOldValue:!0,attributeFilter:$n}),S.observe(Lt?or:sr,{attributes:!0,attributeOldValue:!0,subtree:!Lt,childList:!Lt,characterData:!Lt,attributeFilter:Lt?Vn:$n}),Vr=!0)}function Qe(){d&&Vr&&(O.disconnect(),S.disconnect(),Vr=!1)}function Kn(){if(!Ut){var n,t={w:H[xi.sW],h:H[xi.sH]};n=fi(t,_),_=t,n&&qe({A:!0})}}function Jn(){Kr&&Ge(!0)}function Zn(){Kr&&!j.hasClass(Mn)&&Ge(!1)}function nt(){Gr&&(Ge(!0),clearTimeout(I),I=setTimeout(function(){Gr&&!Et&&Ge(!1)},100))}function tt(n){return Oi.prvD(n),!1}function rt(n){var r=Ci(n.target);mt(function(n,t){r.is(t)&&qe({I:!0})})}function Ue(n){n||Ue(!0),Xn(Yt,$.split(xe)[0],nt,!Gr||n,!0),Xn(Yt,[q,X],[Jn,Zn],!Kr||n,!0),Ht||n||Yt.one("mouseover",Jn)}function Ve(){var n={};return Rt&&tr&&(n.w=ii(tr.css(ve+de)),n.h=ii(tr.css(ve+pe)),n.c=fi(n,Ur),n.f=!0),!!(Ur=n).c}function et(n,t){var r,e,i=typeof t==gi?t.split(xe):[],o=function f(n,t){var r,e,i=[],o=[];for(r=0;r<n.length;r++)i[n[r]]=!0;for(r=0;r<t.length;r++)i[t[r]]?delete i[t[r]]:i[t[r]]=!0;for(e in i)o.push(e);return o}(typeof n==gi?n.split(xe):[],i),u=sn(De,o);if(-1<u&&o.splice(u,1),0<o[xi.l])for(e=lt(!0,!0),r=0;r<o.length;r++)if(!o[r].match(e))return!0;return!1}function it(n){h(n=n||Pn,function(n,t){if(-1<Oi.inA(t,Pn)){var r=Xt.attr(t);cn(r)==gi?Zt.attr(t,r):Zt.removeAttr(t)}})}function $e(){if(!Ut){var n,t,r,e,i=!Fr,o=ee.w,u=ee.h,f={},a=br||i;return f[ve+de]=me,f[ve+pe]=me,f[de]=ge,Xt.css(f),n=or[xi.oW],t=a?Si.max(n,or[xi.sW]-1):1,f[de]=br?ge:ye,f[ve+de]=ye,f[pe]=ge,Xt.css(f),r=or[xi.oH],e=Si.max(r,or[xi.sH]-1),f[de]=t,f[pe]=e,er.css(f),f[ve+de]=o,f[ve+pe]=u,Xt.css(f),{$:n,X:r,Y:t,G:e}}}function qe(n){clearTimeout(qt),n=n||{},Fe.A|=n.A,Fe.I|=n.I,Fe.H|=n.H;var t,r=Oi.now(),e=!!Fe.A,i=!!Fe.I,o=!!Fe.H,u=n.T,f=0<Pe&&Ht&&!Et&&!o&&!u&&r-$t<Pe&&!mr&&!br;if(f&&(qt=setTimeout(qe,Pe)),!(Et||f||Ut&&!u||Ht&&!o&&(t=Yt.is(":hidden"))||"inline"===Yt.css("display"))){$t=r,Fe={},!It||St.x&&St.y?At=ai({},xt.nativeScrollbarSize):(At.x=0,At.y=0),ie={x:3*(At.x+(St.x?0:3)),y:3*(At.y+(St.y?0:3))},u=u||{};var a=function(){return fi.apply(this,[].slice.call(arguments).concat([o]))},c={x:Zt[_e](),y:Zt[Oe]()},s=Vt.scrollbars,l=Vt.textarea,v=s.visibility,h=a(v,Hr),d=s.autoHide,p=a(d,Er),b=s.clickScrolling,m=a(b,Lr),g=s.dragScrolling,w=a(g,Rr),y=Vt.className,x=a(y,Mr),_=Vt.resize,O=a(_,Nr)&&!Rt,S=Vt.paddingAbsolute,z=a(S,Or),C=Vt.clipAlways,k=a(C,Sr),I=Vt.sizeAutoCapable&&!Rt,T=a(I,Ar),A=Vt.nativeScrollbarsOverlaid.showNativeScrollbars,H=a(A,Ir),E=Vt.autoUpdate,L=a(E,Tr),R=Vt.overflowBehavior,N=a(R,Cr,o),W=l.dynWidth,M=a(Qr,W),D=l.dynHeight,F=a(Br,D);if(Xr="n"===d,Yr="s"===d,Gr="m"===d,Kr="l"===d,qr=s.autoHideDelay,Dr=Mr,Jr="n"===_,Zr="b"===_,ne="h"===_,te="v"===_,Wr=Vt.normalizeRTL,A=A&&St.x&&St.y,Hr=v,Er=d,Lr=b,Rr=g,Mr=y,Nr=_,Or=S,Sr=C,Ar=I,Ir=A,Tr=E,Cr=ai({},R),Qr=W,Br=D,dr=dr||{x:!1,y:!1},x&&(si(Yt,Dr+xe+De),ci(Yt,y!==di&&null!==y&&0<y.length?y:De)),L&&(!0===E||null===E&&kt?(Qe(),_t.add(Ot)):(_t.remove(Ot),Be())),T)if(I)if(rr?rr.show():(rr=Ci(ui(Ee)),Jt.before(rr)),Wt)Gt.show();else{Gt=Ci(ui(Le)),fr=Gt[0],rr.before(Gt);var P={w:-1,h:-1};je(Gt,function(){var n={w:fr[xi.oW],h:fr[xi.oH]};fi(n,P)&&(Ht&&mr&&0<n.h||br&&0<n.w||Ht&&!mr&&0===n.h||!br&&0===n.w)&&qe(),P=n}),Wt=!0,null!==Tt&&Gt.css(pe,Tt+"(100% + 1px)")}else Wt&&Gt.hide(),rr&&rr.hide();o&&(Kt.find("*").trigger(we),Wt&&Gt.find("*").trigger(we)),t=t===di?Yt.is(":hidden"):t;var j,B=!!Lt&&"off"!==Xt.attr("wrap"),Q=a(B,Fr),U=Yt.css("direction"),V=a(U,_r),$=Yt.css("box-sizing"),q=a($,gr),X=ei(ue);try{j=Wt?fr[xi.bCR]():null}catch(wt){return}Nt="border-box"===$;var Y=(Qt="rtl"===U)?le:ce,G=Qt?ce:le,K=!1,J=!(!Wt||"none"===Yt.css(be))&&(0===Si.round(j.right-j.left)&&(!!S||0<ur[xi.cW]-Mt));if(I&&!J){var Z=ur[xi.oW],nn=rr.css(de);rr.css(de,ge);var tn=ur[xi.oW];rr.css(de,nn),(K=Z!==tn)||(rr.css(de,Z+1),tn=ur[xi.oW],rr.css(de,nn),K=Z!==tn)}var rn=(J||K)&&I&&!t,en=a(rn,br),on=!rn&&br,un=!(!Wt||!I||t)&&0===Si.round(j.bottom-j.top),fn=a(un,mr),an=!un&&mr,cn=ei(fe,"-"+de,!(rn&&Nt||!Nt),!(un&&Nt||!Nt)),sn=ei(oe),ln={},vn={},hn=function(){return{w:ur[xi.cW],h:ur[xi.cH]}},dn=function(){return{w:ar[xi.oW]+Si.max(0,sr[xi.cW]-sr[xi.sW]),h:ar[xi.oH]+Si.max(0,sr[xi.cH]-sr[xi.sH])}},pn=Mt=X.l+X.r,bn=Dt=X.t+X.b;if(pn*=S?1:0,bn*=S?1:0,X.c=a(X,wr),Ft=cn.l+cn.r,Pt=cn.t+cn.b,cn.c=a(cn,yr),jt=sn.l+sn.r,Bt=sn.t+sn.b,sn.c=a(sn,xr),Fr=B,_r=U,gr=$,br=rn,mr=un,wr=X,yr=cn,xr=sn,V&&Wt&&Gt.css(be,G),X.c||V||z||en||fn||q||T){var mn={},gn={},wn=[X.t,X.r,X.b,X.l];ri(vn,oe,[-X.t,-X.r,-X.b,-X.l]),S?(ri(mn,me,wn),ri(Lt?gn:ln,ue)):(ri(mn,me),ri(Lt?gn:ln,ue,wn)),Jt.css(mn),Xt.css(gn)}ee=dn();var yn=!!Lt&&$e(),xn=Lt&&a(yn,jr),_n=Lt&&yn?{w:W?yn.Y:yn.$,h:D?yn.G:yn.X}:{};if(jr=yn,un&&(fn||z||q||X.c||cn.c)?ln[pe]=ge:(fn||z)&&(ln[pe]=ye),rn&&(en||z||q||X.c||cn.c||V)?(ln[de]=ge,vn[he+de]=ye):(en||z)&&(ln[de]=ye,ln[be]=me,vn[he+de]=me),rn?(vn[de]=ge,ln[de]=_i.d(de,"max-content intrinsic")||ge,ln[be]=G):vn[de]=me,vn[pe]=un?_n.h||sr[xi.cH]:me,I&&rr.css(vn),nr.css(ln),ln={},vn={},e||i||xn||V||q||z||en||rn||fn||un||H||N||k||O||h||p||w||m||M||F||Q){var On="overflow",Sn=On+"-x",zn=On+"-y";if(!It){var Cn={},kn=dr.y&&pr.ys&&!A?St.y?Zt.css(Y):-At.y:0,In=dr.x&&pr.xs&&!A?St.x?Zt.css(se):-At.x:0;ri(Cn,me),Zt.css(Cn)}var Tn=oi(),An={w:_n.w||Tn[xi.cW],h:_n.h||Tn[xi.cH]},Hn=Tn[xi.sW],En=Tn[xi.sH];It||(Cn[se]=an?me:In,Cn[Y]=on?me:kn,Zt.css(Cn)),ee=dn();var Ln=hn(),Rn={w:Ln.w-jt-Ft-(Nt?0:Mt),h:Ln.h-Bt-Pt-(Nt?0:Dt)},Nn={w:Si.max((rn?An.w:Hn)+pn,Rn.w),h:Si.max((un?An.h:En)+bn,Rn.h)};if(Nn.c=a(Nn,zr),zr=Nn,I){(Nn.c||un||rn)&&(vn[de]=Nn.w,vn[pe]=Nn.h,Lt||(An={w:Tn[xi.cW],h:Tn[xi.cH]}));var Wn={},Mn=function(n){var t=ni(n),r=t.j,e=t.K,i=n?rn:un,o=n?Ft:Pt,u=n?Mt:Dt,f=n?jt:Bt,a=ee[r]-o-f-(Nt?0:u);i&&(i||!cn.c)||(vn[e]=Rn[r]-1),!(i&&An[r]<a)||n&&Lt&&B||(Lt&&(Wn[e]=ii(er.css(e))-1),--vn[e]),0<An[r]&&(vn[e]=Si.max(1,vn[e]))};Mn(!0),Mn(!1),Lt&&er.css(Wn),rr.css(vn)}rn&&(ln[de]=ye),!rn||Nt||Vr||(ln[be]="none"),nr.css(ln),ln={};var Dn={w:Tn[xi.sW],h:Tn[xi.sH]};Dn.c=i=a(Dn,vr),vr=Dn,ee=dn(),e=a(Ln=hn(),lr),lr=Ln;var Fn=Lt&&(0===ee.w||0===ee.h),Pn=kr,jn={},Bn={},Qn={},Un={},Vn={},$n={},qn={},Xn=ar[xi.bCR](),Yn=function(n){var t=ni(n),r=ni(!n).Q,e=t.Q,i=t.j,o=t.K,u=we+t.J+"Max",f=Xn[o]?Si.abs(Xn[o]-ee[i]):0,a=Pn&&0<Pn[e]&&0===cr[u];jn[e]="v-s"===R[e],Bn[e]="v-h"===R[e],Qn[e]="s"===R[e],Un[e]=Si.max(0,Si.round(100*(Dn[i]-ee[i]))/100),Un[e]*=Fn||a&&0<f&&f<1?0:1,Vn[e]=0<Un[e],$n[e]=jn[e]||Bn[e]?Vn[r]&&!jn[r]&&!Bn[r]:Vn[e],$n[e+"s"]=!!$n[e]&&(Qn[e]||jn[e]),qn[e]=Vn[e]&&$n[e+"s"]};if(Yn(!0),Yn(!1),Un.c=a(Un,kr),kr=Un,Vn.c=a(Vn,dr),dr=Vn,$n.c=a($n,pr),pr=$n,St.x||St.y){var Gn,Kn={},Jn={},Zn=o;(Vn.x||Vn.y)&&(Jn.w=St.y&&Vn.y?Dn.w+zt.y:me,Jn.h=St.x&&Vn.x?Dn.h+zt.x:me,Zn=a(Jn,hr),hr=Jn),(Vn.c||$n.c||Dn.c||V||en||fn||rn||un||H)&&(ln[oe+G]=ln[fe+G]=me,Gn=function(n){var t=ni(n),r=ni(!n),e=t.Q,i=n?se:Y,o=n?un:rn;St[e]&&Vn[e]&&$n[e+"s"]?(ln[oe+i]=!o||A?me:zt[e],ln[fe+i]=n&&o||A?me:zt[e]+"px solid transparent"):(Jn[r.j]=ln[oe+i]=ln[fe+i]=me,Zn=!0)},It?li(Zt,Ae,!A):(Gn(!0),Gn(!1))),A&&(Jn.w=Jn.h=me,Zn=!0),Zn&&!It&&(Kn[de]=$n.y?Jn.w:me,Kn[pe]=$n.x?Jn.h:me,tr||(tr=Ci(ui(He)),Zt.prepend(tr)),tr.css(Kn)),nr.css(ln)}var nt,tt={};mn={};if((e||Vn.c||$n.c||Dn.c||N||q||H||V||k||fn)&&(tt[G]=me,(nt=function(n){var t=ni(n),r=ni(!n),e=t.Q,i=t.Z,o=n?se:Y,u=function(){tt[o]=me,re[r.j]=0};Vn[e]&&$n[e+"s"]?(tt[On+i]=we,A||It?u():(tt[o]=-(St[e]?zt[e]:At[e]),re[r.j]=St[e]?zt[r.Q]:0)):(tt[On+i]=me,u())})(!0),nt(!1),!It&&(ee.h<ie.x||ee.w<ie.y)&&(Vn.x&&$n.x&&!St.x||Vn.y&&$n.y&&!St.y)?(tt[ue+ae]=ie.x,tt[oe+ae]=-ie.x,tt[ue+G]=ie.y,tt[oe+G]=-ie.y):tt[ue+ae]=tt[oe+ae]=tt[ue+G]=tt[oe+G]=me,tt[ue+Y]=tt[oe+Y]=me,Vn.x&&$n.x||Vn.y&&$n.y||Fn?Lt&&Fn&&(mn[Sn]=mn[zn]="hidden"):(!C||Bn.x||jn.x||Bn.y||jn.y)&&(Lt&&(mn[Sn]=mn[zn]=me),tt[Sn]=tt[zn]="visible"),Jt.css(mn),Zt.css(tt),tt={},(Vn.c||q||en||fn)&&(!St.x||!St.y))){var rt=sr[xi.s];rt.webkitTransform="scale(1)",rt.display="run-in",sr[xi.oH],rt.display=me,rt.webkitTransform=me}if(ln={},V||en||fn)if(Qt&&rn){var et=nr.css(be),it=Si.round(nr.css(be,me).css(le,me).position().left);nr.css(be,et),it!==Si.round(nr.position().left)&&(ln[le]=it)}else ln[le]=me;if(nr.css(ln),Lt&&i){var ot=function yt(){var n=or.selectionStart;if(n===di)return;var t,r,e=Xt.val(),i=e[xi.l],o=e.split("\n"),u=o[xi.l],f=e.substr(0,n).split("\n"),a=0,c=0,s=f[xi.l],l=f[f[xi.l]-1][xi.l];for(r=0;r<o[xi.l];r++)t=o[r][xi.l],c<t&&(a=r+1,c=t);return{nn:s,tn:l,rn:u,en:c,"in":a,un:n,an:i}}();if(ot){var ut=Pr===di||ot.rn!==Pr.rn,ft=ot.nn,at=ot.tn,ct=ot["in"],st=ot.rn,lt=ot.en,vt=ot.un,ht=ot.an<=vt&&$r,dt={x:B||at!==lt||ft!==ct?-1:kr.x,y:(B?ht||ut&&Pn&&c.y===Pn.y:(ht||ut)&&ft===st)?kr.y:-1};c.x=-1<dt.x?Qt&&Wr&&Ct.i?0:dt.x:c.x,c.y=-1<dt.y?dt.y:c.y}Pr=ot}Qt&&Ct.i&&St.y&&Vn.x&&Wr&&(c.x+=re.w||0),rn&&Yt[_e](0),un&&Yt[Oe](0),Zt[_e](c.x)[Oe](c.y);var pt="v"===v,bt="h"===v,mt="a"===v,gt=function(n,t){t=t===di?n:t,Ye(!0,n,qn.x),Ye(!1,t,qn.y)};li(Yt,ke,$n.x||$n.y),li(Yt,Ie,$n.x),li(Yt,Te,$n.y),V&&!Rt&&li(Yt,Se,Qt),Rt&&ci(Yt,ze),O&&(li(Yt,ze,Jr),li(ir,Re,!Jr),li(ir,Ne,Zr),li(ir,We,ne),li(ir,Me,te)),(h||N||$n.c||Vn.c||H)&&(A?H&&(si(Yt,Ce),A&&gt(!1)):mt?gt(qn.x,qn.y):pt?gt(!0):bt&&gt(!1)),(p||H)&&(Ue(!Kr&&!Gr),Ge(Xr,!Xr)),(e||Un.c||fn||en||O||q||z||H||V)&&(Ke(!0),Je(!0),Ke(!1),Je(!1)),m&&Ze(!0,b),w&&Ze(!1,g),ti("onDirectionChanged",{isRTL:Qt,dir:U},V),ti("onHostSizeChanged",{width:lr.w,height:lr.h},e),ti("onContentSizeChanged",{width:vr.w,height:vr.h},i),ti("onOverflowChanged",{x:Vn.x,y:Vn.y,xScrollable:$n.xs,yScrollable:$n.ys,clipped:$n.x||$n.y},Vn.c||$n.c),ti("onOverflowAmountChanged",{x:Un.x,y:Un.y},Un.c)}Rt&&Ur&&(dr.c||Ur.c)&&(Ur.f||Ve(),St.y&&dr.x&&nr.css(ve+de,Ur.w+zt.y),St.x&&dr.y&&nr.css(ve+pe,Ur.h+zt.x),Ur.c=!1),Ht&&u.updateOnLoad&&Xe(),ti("onUpdated",{forced:o})}}function Xe(){Lt||mt(function(n,t){nr.find(t).each(function(n,t){Oi.inA(t,Qn)<0&&(Qn.push(t),Ci(t).off(Bn,rt).on(Bn,rt))})})}function ot(n){var t=Ii.O(n,Ii._,!0,u);return u=ai({},u,t.S),Vt=ai({},Vt,t.z),t.z}function ut(e){var n="parent",t=mn+xe+Cn,r=Lt?xe+Cn:me,i=Vt.textarea.inheritedAttrs,o={},u=function(){var r=e?Xt:Yt;h(o,function(n,t){cn(t)==gi&&(n==xi.c?r.addClass(t):r.attr(n,t))})},f=[rn,en,on,ze,Se,un,fn,an,Ce,ke,Ie,Te,De,mn,Cn,Mr].join(xe),a={};Yt=Yt||(Lt?p?Xt[n]()[n]()[n]()[n]():Ci(ui(on)):Xt),nr=nr||pt(_n+r),Zt=Zt||pt(yn+r),Jt=Jt||pt(wn+r),Kt=Kt||pt("os-resize-observer-host"),er=er||(Lt?pt(gn):di),p&&ci(Yt,en),e&&si(Yt,f),i=cn(i)==gi?i.split(xe):i,Oi.isA(i)&&Lt&&h(i,function(n,t){cn(t)==gi&&(o[t]=e?Yt.attr(t):Xt.attr(t))}),e?(p&&Ht?(Kt.children().remove(),h([Jt,Zt,nr,er],function(n,t){t&&si(t.removeAttr(xi.s),Dn)}),ci(Yt,Lt?on:rn)):(gt(Kt),nr.contents().unwrap().unwrap().unwrap(),Lt&&(Xt.unwrap(),gt(Yt),gt(er),u())),Lt&&Xt.removeAttr(xi.s),Rt&&si(c,tn)):(Lt&&(Vt.sizeAutoCapable||(a[de]=Xt.css(de),a[pe]=Xt.css(pe)),p||Xt.addClass(Cn).wrap(Yt),Yt=Xt[n]().css(a)),p||(ci(Xt,Lt?t:rn),Yt.wrapInner(nr).wrapInner(Zt).wrapInner(Jt).prepend(Kt),nr=wt(Yt,R+_n),Zt=wt(Yt,R+yn),Jt=wt(Yt,R+wn),Lt&&(nr.prepend(er),u())),It&&ci(Zt,Ae),St.x&&St.y&&ci(Zt,xn),Rt&&ci(c,tn),H=Kt[0],ur=Yt[0],ar=Jt[0],cr=Zt[0],sr=nr[0],it())}function ft(){var r,t,e=[112,113,114,115,116,117,118,119,120,121,123,33,34,37,38,39,40,16,17,18,19,20,144],i=[],n="focus";function o(n){$e(),Ot.update(ge),n&&kt&&clearInterval(r)}Lt?(9<D||!kt?Yn(Xt,"input",o):Yn(Xt,[Y,G],[function u(n){var t=n.keyCode;sn(t,e)<0&&(i[xi.l]||(o(),r=setInterval(o,1e3/60)),sn(t,i)<0&&i.push(t))},function f(n){var t=n.keyCode,r=sn(t,i);sn(t,e)<0&&(-1<r&&i.splice(r,1),i[xi.l]||o(!0))}]),Yn(Xt,[we,"drop",n,n+"out"],[function a(n){return Xt[_e](Ct.i&&Wr?9999999:0),Xt[Oe](0),Oi.prvD(n),Oi.stpP(n),!1},function c(n){setTimeout(function(){Et||o()},50)},function s(){$r=!0,ci(Yt,n)},function l(){$r=!1,i=[],si(Yt,n),o(!0)}])):Yn(nr,J,function v(n){!0!==Tr&&function l(n){if(!Ht)return 1;var t="flex-grow",r="flex-shrink",e="flex-basis",i=[de,ve+de,he+de,oe+le,oe+ce,le,ce,"font-weight","word-spacing",t,r,e],o=[ue+le,ue+ce,fe+le+de,fe+ce+de],u=[pe,ve+pe,he+pe,oe+ae,oe+se,ae,se,"line-height",t,r,e],f=[ue+ae,ue+se,fe+ae+de,fe+se+de],a="s"===Cr.x||"v-s"===Cr.x,c=!1,s=function(n,t){for(var r=0;r<n[xi.l];r++)if(n[r]===t)return!0;return!1};return("s"===Cr.y||"v-s"===Cr.y)&&((c=s(u,n))||Nt||(c=s(f,n))),a&&!c&&((c=s(i,n))||Nt||(c=s(o,n))),c}((n=n.originalEvent||n).propertyName)&&Ot.update(ge)}),Yn(Zt,we,function h(n){Ut||(t!==di?clearTimeout(t):((Yr||Gr)&&Ge(!0),dt()||ci(Yt,Ce),ti("onScrollStart",n)),Q||(Je(!0),Je(!1)),ti("onScroll",n),t=setTimeout(function(){Et||(clearTimeout(t),t=di,(Yr||Gr)&&Ge(!1),dt()||si(Yt,Ce),ti("onScrollStop",n))},175))},!0)}function at(i){var n,t,o=function(n){var t=pt(kn+xe+(n?Nn:Wn),!0),r=pt(In,t),e=pt(An,t);return p||i||(t.append(r),r.append(e)),{cn:t,sn:r,ln:e}};function r(n){var t=ni(n),r=t.cn,e=t.sn,i=t.ln;p&&Ht?h([r,e,i],function(n,t){si(t.removeAttr(xi.s),Dn)}):gt(r||o(n).cn)}i?(r(!0),r()):(n=o(!0),t=o(),a=n.cn,s=n.sn,l=n.ln,v=t.cn,b=t.sn,m=t.ln,p||(Jt.after(v),Jt.after(a)))}function ct(S){var z,i,C,k,e=ni(S),I=e.vn,t=x.top!==x,T=e.Q,r=e.Z,A=we+e.J,o="active",u="snapHandle",f="click",H=1,a=[16,17];function c(n){return D&&t?n["screen"+r]:Oi.page(n)[T]}function s(n){return Vt.scrollbars[n]}function l(){H=.5}function v(){H=1}function h(n){Oi.stpP(n)}function E(n){-1<sn(n.keyCode,a)&&l()}function L(n){-1<sn(n.keyCode,a)&&v()}function R(n){var t=(n.originalEvent||n).touches!==di;return!(Ut||Et||dt()||!Rr||t&&!s("touchSupport"))&&(1===Oi.mBtn(n)||t)}function d(n){if(R(n)){var t=I.F,r=I.M,e=I.N*((c(n)-C)*k/(t-r));e=isFinite(e)?e:0,Qt&&S&&!Ct.i&&(e*=-1),Zt[A](Si.round(i+e)),Q&&Je(S,i+e),w||Oi.prvD(n)}else N(n)}function N(n){if(n=n||n.originalEvent,Xn(P,[$,V,Y,G,K],[d,N,E,L,tt],!0),Oi.rAF()(function(){Xn(P,f,h,!0,{V:!0})}),Q&&Je(S,!0),Q=!1,si(j,Mn),si(e.ln,o),si(e.sn,o),si(e.cn,o),k=1,v(),z!==(C=i=di)&&(Ot.scrollStop(),clearTimeout(z),z=di),n){var t=ur[xi.bCR]();n.clientX>=t.left&&n.clientX<=t.right&&n.clientY>=t.top&&n.clientY<=t.bottom||Zn(),(Yr||Gr)&&Ge(!1)}}function W(n){i=Zt[A](),i=isNaN(i)?0:i,(Qt&&S&&!Ct.n||!Qt)&&(i=i<0?0:i),k=vt()[T],C=c(n),Q=!s(u),ci(j,Mn),ci(e.ln,o),ci(e.cn,o),Xn(P,[$,V,K],[d,N,tt]),Oi.rAF()(function(){Xn(P,f,h,!1,{V:!0})}),!D&&y||Oi.prvD(n),Oi.stpP(n)}Yn(e.ln,U,function p(n){R(n)&&W(n)}),Yn(e.sn,[U,q,X],[function M(n){if(R(n)){var h,t=e.vn.M/Math.round(Si.min(1,ee[e.j]/vr[e.j])*e.vn.F),d=Si.round(ee[e.j]*t),p=270*t,b=400*t,m=e.sn.offset()[e.B],r=n.ctrlKey,g=n.shiftKey,w=g&&r,y=!0,x=function(n){Q&&Je(S,n)},_=function(){x(),W(n)},O=function(){if(!Et){var n=(C-m)*k,t=I.W,r=I.F,e=I.M,i=I.N,o=I.L,u=p*H,f=y?Si.max(b,u):u,a=i*((n-e/2)/(r-e)),c=Qt&&S&&(!Ct.i&&!Ct.n||Wr),s=c?t<n:n<t,l={},v={easing:"linear",step:function(n){Q&&(Zt[A](n),Je(S,n))}};a=isFinite(a)?a:0,a=Qt&&S&&!Ct.i?i-a:a,g?(Zt[A](a),w?(a=Zt[A](),Zt[A](o),a=c&&Ct.i?i-a:a,a=c&&Ct.n?-a:a,l[T]=a,Ot.scroll(l,ai(v,{duration:130,complete:_}))):_()):(h=y?s:h,(c?h?n<=t+e:t<=n:h?t<=n:n<=t+e)?(clearTimeout(z),Ot.scrollStop(),z=di,x(!0)):(z=setTimeout(O,f),l[T]=(h?"-=":"+=")+d,Ot.scroll(l,ai(v,{duration:u}))),y=!1)}};r&&l(),k=vt()[T],C=Oi.page(n)[T],Q=!s(u),ci(j,Mn),ci(e.sn,o),ci(e.cn,o),Xn(P,[V,Y,G,K],[N,E,L,tt]),O(),Oi.prvD(n),Oi.stpP(n)}},function b(n){B=!0,(Yr||Gr)&&Ge(!0)},function m(n){B=!1,(Yr||Gr)&&Ge(!1)}]),Yn(e.cn,U,function g(n){Oi.stpP(n)}),F&&Yn(e.cn,J,function(n){n.target===e.cn[0]&&(Ke(S),Je(S))})}function Ye(n,t,r){var e=n?a:v;li(Yt,n?un:fn,!t),li(e,En,!r)}function Ge(n,t){if(clearTimeout(k),n)si(a,Ln),si(v,Ln);else{var r,e=function(){B||Et||(!(r=l.hasClass("active")||m.hasClass("active"))&&(Yr||Gr||Kr)&&ci(a,Ln),!r&&(Yr||Gr||Kr)&&ci(v,Ln))};0<qr&&!0!==t?k=setTimeout(e,qr):e()}}function Ke(n){var t={},r=ni(n),e=r.vn,i=Si.min(1,ee[r.j]/vr[r.j]);t[r.K]=Si.floor(100*i*1e6)/1e6+"%",dt()||r.ln.css(t),e.M=r.ln[0]["offset"+r.hn],e.D=i}function Je(n,t){var r,e,i=cn(t)==wi,o=Qt&&n,u=ni(n),f=u.vn,a="translate(",c=_i.v("transform"),s=_i.v("transition"),l=n?Zt[_e]():Zt[Oe](),v=t===di||i?l:t,h=f.M,d=u.sn[0]["offset"+u.hn],p=d-h,b={},m=(cr[we+u.hn]-cr["client"+u.hn])*(Ct.n&&o?-1:1),g=function(n){return isNaN(n/m)?0:Si.max(0,Si.min(1,n/m))},w=function(n){var t=p*n;return t=isNaN(t)?0:t,t=o&&!Ct.i?d-h-t:t,t=Si.max(0,t)},y=g(l),x=w(g(v)),_=w(y);f.N=m,f.L=l,f.R=y,ln?(r=o?-(d-h-x):x,e=n?a+r+"px, 0)":a+"0, "+r+"px)",b[c]=e,F&&(b[s]=i&&1<Si.abs(x-f.W)?function O(n){var t=_i.v("transition"),r=n.css(t);if(r)return r;for(var e,i,o,u="\\s*(([^,(]+(\\(.+?\\))?)+)[\\s,]*",f=new RegExp(u),a=new RegExp("^("+u+")+$"),c="property duration timing-function delay".split(" "),s=[],l=0,v=function(n){if(e=[],!n.match(a))return n;for(;n.match(f);)e.push(RegExp.$1),n=n.replace(f,me);return e};l<c[xi.l];l++)for(i=v(n.css(t+"-"+c[l])),o=0;o<i[xi.l];o++)s[o]=(s[o]?s[o]+xe:me)+i[o];return s.join(", ")}(u.ln)+", "+(c+xe+250)+"ms":me)):b[u.B]=x,dt()||(u.ln.css(b),ln&&F&&i&&u.ln.one(J,function(){Et||u.ln.css(s,me)})),f.W=x,f.P=_,f.F=d}function Ze(n,t){var r=t?"removeClass":"addClass",e=n?b:m,i=n?Tn:Hn;(n?s:l)[r](i),e[r](i)}function ni(n){return{K:n?de:pe,hn:n?"Width":"Height",B:n?le:ae,J:n?"Left":"Top",Q:n?pn:bn,Z:n?"X":"Y",j:n?"w":"h",dn:n?"l":"t",sn:n?s:b,ln:n?l:m,cn:n?a:v,vn:n?vn:hn}}function st(n){ir=ir||pt(Rn,!0),n?p&&Ht?si(ir.removeAttr(xi.s),Dn):gt(ir):p||Yt.append(ir)}function ti(n,t,r){if(!1!==r)if(Ht){var e,i=Vt.callbacks[n],o=n;"on"===o.substr(0,2)&&(o=o.substr(2,1).toLowerCase()+o.substr(3)),cn(i)==bi&&i.call(Ot,t),h(jn,function(){cn((e=this).on)==bi&&e.on(o,t)})}else Et||Fn.push({n:n,a:t})}function ri(n,t,r){r=r||[me,me,me,me],n[(t=t||me)+ae]=r[0],n[t+ce]=r[1],n[t+se]=r[2],n[t+le]=r[3]}function ei(n,t,r,e){return t=t||me,n=n||me,{t:e?0:ii(Yt.css(n+ae+t)),r:r?0:ii(Yt.css(n+ce+t)),b:e?0:ii(Yt.css(n+se+t)),l:r?0:ii(Yt.css(n+le+t))}}function lt(n,t){var r,e,i,o=function(n,t){if(i="",t&&typeof n==gi)for(e=n.split(xe),r=0;r<e[xi.l];r++)i+="|"+e[r]+"$";return i};return new RegExp("(^"+rn+"([-_].+|)$)"+o(Mr,n)+o(Dr,t),"g")}function vt(){var n=ar[xi.bCR]();return{x:ln&&1/(Si.round(n.width)/ar[xi.oW])||1,y:ln&&1/(Si.round(n.height)/ar[xi.oH])||1}}function ht(n){var t="ownerDocument",r="HTMLElement",e=n&&n[t]&&n[t].parentWindow||vi;return typeof e[r]==pi?n instanceof e[r]:n&&typeof n==pi&&null!==n&&1===n.nodeType&&typeof n.nodeName==gi}function ii(n,t){var r=t?parseFloat(n):parseInt(n,10);return isNaN(r)?0:r}function dt(){return Ir&&St.x&&St.y}function oi(){return Lt?er[0]:sr}function ui(r,n){return"<div "+(r?cn(r)==gi?'class="'+r+'"':function(){var n,t=me;if(Ci.isPlainObject(r))for(n in r)t+=("c"===n?"class":n)+'="'+r[n]+'" ';return t}():me)+">"+(n||me)+"</div>"}function pt(n,t){var r=cn(t)==wi,e=!r&&t||Yt;return p&&!e[xi.l]?null:p?e[r?"children":"find"](R+n.replace(/\s/g,R)).eq(0):Ci(ui(n))}function bt(n,t){for(var r,e=t.split(R),i=0;i<e.length;i++){if(!n[xi.hOP](e[i]))return;r=n[e[i]],i<e.length&&cn(r)==pi&&(n=r)}return r}function mt(n){var t=Vt.updateOnLoad;t=cn(t)==gi?t.split(xe):t,Oi.isA(t)&&!Et&&h(t,n)}function fi(n,t,r){if(r)return r;if(cn(n)!=pi||cn(t)!=pi)return n!==t;for(var e in n)if("c"!==e){if(!n[xi.hOP](e)||!t[xi.hOP](e))return!0;if(fi(n[e],t[e]))return!0}return!1}function ai(){return Ci.extend.apply(this,[!0].concat([].slice.call(arguments)))}function ci(n,t){return e.addClass.call(n,t)}function si(n,t){return e.removeClass.call(n,t)}function li(n,t,r){return(r?ci:si)(n,t)}function gt(n){return e.remove.call(n)}function wt(n,t){return e.find.call(n,t).eq(0)}}return zi&&zi.fn&&(zi.fn.overlayScrollbars=function(n,t){return zi.isPlainObject(n)?(zi.each(this,function(){q(this,n,t)}),this):q(this,n)}),q}); \ No newline at end of file
diff --git a/src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js b/src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js
new file mode 100644
index 0000000..e08835b
--- /dev/null
+++ b/src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.js
@@ -0,0 +1,5578 @@
+/*!
+ * OverlayScrollbars
+ * https://github.com/KingSora/OverlayScrollbars
+ *
+ * Version: 1.13.0
+ *
+ * Copyright KingSora | Rene Haas.
+ * https://github.com/KingSora
+ *
+ * Released under the MIT license.
+ * Date: 02.08.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;
+ },
+ _cssPropertyValue: function (property, values, suffix) {
+ var name = property + ' ' + values;
+ var result = cssCache[name];
+
+ if (cssCache[LEXICON.hOP](name))
+ return result;
+
+ var dummyStyle = document.createElement('div')[LEXICON.s];
+ var possbleValues = values.split(' ');
+ var preparedSuffix = suffix || '';
+ var i = 0;
+ var v = -1;
+ var prop;
+
+ for (; i < possbleValues[LEXICON.l]; i++) {
+ for (; v < VENDORS._cssPrefixes[LEXICON.l]; v++) {
+ prop = v < 0 ? possbleValues[i] : VENDORS._cssPrefixes[v] + possbleValues[i];
+ dummyStyle.cssText = property + ':' + prop + preparedSuffix;
+ if (dummyStyle[LEXICON.l]) {
+ result = prop;
+ 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 updateOnLoadTemplate = [['img'], [TYPES.s, TYPES.a, TYPES.z]];
+ 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
+ updateOnLoad: updateOnLoadTemplate, //string || array || null
+ 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 = !COMPATIBILITY.isA(templateValue) ? [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('<div id="os-dummy-scrollbar-size"><div></div></div>');
+ 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: VENDORS._cssPropertyValue('width', 'calc', '(1px)') || 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'),
+ supportTransition: !!VENDORS._cssProperty('transition'),
+ 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 _strMouseEnter = 'mouseenter';
+ var _strMouseLeave = '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 _classNameHostElementForeign = _classNameHostElement + '-foreign';
+ 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 _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 _updateOnLoadEventName = 'load';
+ var _updateOnLoadElms = [];
+
+ //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 _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 _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.
+ * @param passiveOrOptions The options for the event.
+ */
+ function setupResponsiveEventListener(element, eventNames, listener, remove, passiveOrOptions) {
+ var collected = COMPATIBILITY.isA(eventNames) && COMPATIBILITY.isA(listener);
+ var method = remove ? 'removeEventListener' : 'addEventListener';
+ var onOff = remove ? 'off' : 'on';
+ var events = collected ? false : eventNames.split(_strSpace)
+ var i = 0;
+
+ var passiveOrOptionsIsObj = FRAMEWORK.isPlainObject(passiveOrOptions);
+ var passive = (_supportPassiveEvents && (passiveOrOptionsIsObj ? (passiveOrOptions._passive) : passiveOrOptions)) || false;
+ var capture = passiveOrOptionsIsObj && (passiveOrOptions._capture || false);
+ var nativeParam = _supportPassiveEvents ? {
+ passive: passive,
+ capture: capture,
+ } : capture;
+
+ if (collected) {
+ for (; i < eventNames[LEXICON.l]; i++)
+ setupResponsiveEventListener(element, eventNames[i], listener[i], remove, passiveOrOptions);
+ }
+ else {
+ for (; i < events[LEXICON.l]; i++) {
+ if(_supportPassiveEvents) {
+ element[0][method](events[i], listener, nativeParam);
+ }
+ 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 mutationIsClass;
+ var oldMutationVal;
+ var newClassVal;
+ var hostClassNameRegex;
+ var contentTimeout;
+ var now;
+ var sizeAuto;
+ var action;
+
+ _mutationObserverHostCallback = function (mutations) {
+
+ var doUpdate = false;
+ var doUpdateForce = false;
+ var mutation;
+ var mutatedAttrs = [];
+
+ if (_initialized && !_sleeping) {
+ each(mutations, function () {
+ mutation = this;
+ mutationTarget = mutation.target;
+ mutationAttrName = mutation.attributeName;
+ mutationIsClass = mutationAttrName === LEXICON.c;
+ oldMutationVal = mutation.oldValue;
+ newClassVal = mutationTarget.className;
+
+ if (_domExists && mutationIsClass && !doUpdateForce) {
+ // if old class value contains _classNameHostElementForeign and new class value doesn't
+ if (oldMutationVal.indexOf(_classNameHostElementForeign) > -1 && newClassVal.indexOf(_classNameHostElementForeign) < 0) {
+ hostClassNameRegex = createHostClassNameRegExp(true);
+ _hostElementNative.className = newClassVal.split(_strSpace).concat(oldMutationVal.split(_strSpace).filter(function (name) {
+ return name.match(hostClassNameRegex);
+ })).join(_strSpace);
+ doUpdate = doUpdateForce = true;
+ }
+ }
+
+ if (!doUpdate) {
+ doUpdate = mutationIsClass
+ ? hostClassNamesChanged(oldMutationVal, newClassVal)
+ : mutationAttrName === LEXICON.s
+ ? oldMutationVal !== mutationTarget[LEXICON.s].cssText
+ : true;
+ }
+
+ mutatedAttrs.push(mutationAttrName);
+ });
+
+ updateViewportAttrsFromTarget(mutatedAttrs);
+
+ if (doUpdate)
+ _base.update(doUpdateForce || _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 element has loaded.
+ */
+ function updateOnLoadCallback(event) {
+ var elm = FRAMEWORK(event.target);
+
+ eachUpdateOnLoad(function (i, updateOnLoadSelector) {
+ if (elm.is(updateOnLoadSelector)) {
+ 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) {
+ if (!destroy)
+ setupHostMouseTouchEvents(true);
+
+ setupResponsiveEventListener(_hostElement,
+ _strMouseTouchMoveEvent.split(_strSpace)[0],
+ hostOnMouseMove,
+ (!_scrollbarsAutoHideMove || destroy), true);
+ setupResponsiveEventListener(_hostElement,
+ [_strMouseEnter, _strMouseLeave],
+ [hostOnMouseEnter, hostOnMouseLeave],
+ (!_scrollbarsAutoHideLeave || 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 oldClassNames The old ClassName string or array.
+ * @param newClassNames The new ClassName string or array.
+ * @returns {boolean} True if the class names has really changed, false otherwise.
+ */
+ function hostClassNamesChanged(oldClassNames, newClassNames) {
+ var currClasses = typeof newClassNames == TYPES.s ? newClassNames.split(_strSpace) : [];
+ var oldClasses = typeof oldClassNames == TYPES.s ? oldClassNames.split(_strSpace) : [];
+ var diff = getArrayDifferences(oldClasses, currClasses);
+
+ // remove none theme from diff list to prevent update
+ var idx = inArray(_classNameThemeNone, diff);
+ var i;
+ var regex;
+
+ if (idx > -1)
+ diff.splice(idx, 1);
+
+ if (diff[LEXICON.l] > 0) {
+ regex = createHostClassNameRegExp(true, true);
+ for (i = 0; i < diff.length; i++) {
+ if (!diff[i].match(regex)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 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.className);
+
+ //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 || (autoUpdate === null && _autoUpdateRecommended)) {
+ disconnectMutationObservers();
+ autoUpdateLoop.add(_base);
+ }
+ else {
+ autoUpdateLoop.remove(_base);
+ connectMutationObservers();
+ }
+ }
+
+ //activate or deactivate size auto capability
+ if (sizeAutoCapableChanged) {
+ if (sizeAutoCapable) {
+ if (_contentGlueElement) {
+ _contentGlueElement.show();
+ }
+ else {
+ _contentGlueElement = FRAMEWORK(generateDiv(_classNameContentGlueElement));
+ _paddingElement.before(_contentGlueElement);
+ }
+ 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;
+
+ //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 = getTopRightBottomLeftHost(_strPaddingMinus);
+
+ //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 updateBorderX = (widthAuto && _isBorderBox) || !_isBorderBox;
+ var updateBorderY = (heightAuto && _isBorderBox) || !_isBorderBox;
+ var border = getTopRightBottomLeftHost(_strBorderMinus, '-' + _strWidth, !updateBorderX, !updateBorderY)
+
+ //detect margin:
+ var margin = getTopRightBottomLeftHost(_strMarginMinus);
+
+ //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);
+
+ //refresh cache
+ _textareaAutoWrappingCache = textareaAutoWrapping;
+ _cssDirectionCache = cssDirection;
+ _cssBoxSizingCache = boxSizing;
+ _widthAutoCache = widthAuto;
+ _heightAutoCache = heightAuto;
+ _cssPaddingCache = padding;
+ _cssBorderCache = border;
+ _cssMarginCache = margin;
+
+ //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 = {};
+ var paddingValues = [padding.t, padding.r, padding.b, padding.l];
+
+ setTopRightBottomLeft(contentGlueElementCSS, _strMarginMinus, [-padding.t, -padding.r, -padding.b, -padding.l]);
+ if (paddingAbsolute) {
+ setTopRightBottomLeft(paddingElementCSS, _strEmpty, paddingValues);
+ setTopRightBottomLeft(_isTextarea ? textareaCSS : contentElementCSS, _strPaddingMinus);
+ }
+ else {
+ setTopRightBottomLeft(paddingElementCSS, _strEmpty);
+ setTopRightBottomLeft(_isTextarea ? textareaCSS : contentElementCSS, _strPaddingMinus, paddingValues);
+ }
+
+ _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 || padding.c || border.c)) {
+ contentElementCSS[_strHeight] = _strAuto;
+ }
+ else if (heightAutoChanged || paddingAbsoluteChanged) {
+ contentElementCSS[_strHeight] = _strHundredPercent;
+ }
+ if (widthAuto && (widthAutoChanged || paddingAbsoluteChanged || boxSizingChanged || padding.c || border.c || cssDirectionChanged)) {
+ contentElementCSS[_strWidth] = _strAuto;
+ contentGlueElementCSS[_strMaxMinus + _strWidth] = _strHundredPercent; //IE Fix
+ }
+ else if (widthAutoChanged || paddingAbsoluteChanged) {
+ contentElementCSS[_strWidth] = _strHundredPercent;
+ contentElementCSS[_strFloat] = _strEmpty;
+ contentGlueElementCSS[_strMaxMinus + _strWidth] = _strEmpty; //IE Fix
+ }
+ if (widthAuto) {
+ //textareaDynOrigSize.w || _strAuto :: doesnt works because applied margin will shift width
+ contentGlueElementCSS[_strWidth] = _strAuto;
+
+ contentElementCSS[_strWidth] = VENDORS._cssPropertyValue(_strWidth, 'max-content intrinsic') || _strAuto;
+ contentElementCSS[_strFloat] = isRTLRight;
+ }
+ else {
+ contentGlueElementCSS[_strWidth] = _strEmpty;
+ }
+ if (heightAuto) {
+ //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 || 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 hostAbsoluteRectSize = {
+ w: hostSize.w - _marginX - _borderX - (_isBorderBox ? 0 : _paddingX),
+ h: hostSize.h - _marginY - _borderY - (_isBorderBox ? 0 : _paddingY)
+ };
+ 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, hostAbsoluteRectSize.w),
+ h: MATH.max((heightAuto ? contentSize.h : scrollSize.h) + paddingAbsoluteY, hostAbsoluteRectSize.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 viewportSize = _viewportSize[wh] - borderSize - marginSize - (_isBorderBox ? 0 : 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] = hostAbsoluteRectSize[wh] - 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) && (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) {
+ addRemoveClass(_viewportElement, _classNameViewportNativeScrollbarsInvisible, !ignoreOverlayScrollbarHiding)
+ }
+ 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 refreshScrollbarsVisibility = function (showX, showY) {
+ showY = showY === undefined ? showX : showY;
+ refreshScrollbarAppearance(true, showX, canScroll.x)
+ refreshScrollbarAppearance(false, showY, canScroll.y)
+ };
+
+ //manage class name which indicates scrollable overflow
+ addRemoveClass(_hostElement, _classNameHostOverflow, hideOverflow.x || hideOverflow.y);
+ addRemoveClass(_hostElement, _classNameHostOverflowX, hideOverflow.x);
+ addRemoveClass(_hostElement, _classNameHostOverflowY, hideOverflow.y);
+
+ //add or remove rtl class name for styling purposes except when its body, then the scrollbar stays
+ if (cssDirectionChanged && !_isBody) {
+ addRemoveClass(_hostElement, _classNameHostRTL, _isRTL);
+ }
+
+ //manage the resize feature (CSS3 resize "polyfill" for this plugin)
+ if (_isBody)
+ addClass(_hostElement, _classNameHostResizeDisabled);
+ if (resizeChanged) {
+ addRemoveClass(_hostElement, _classNameHostResizeDisabled, _resizeNone);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResize, !_resizeNone);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeB, _resizeBoth);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeH, _resizeHorizontal);
+ addRemoveClass(_scrollbarCornerElement, _classNameScrollbarCornerResizeV, _resizeVertical);
+ }
+
+ //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) {
+ refreshScrollbarsVisibility(false);
+ }
+ }
+ }
+ else if (scrollbarsVisibilityAuto) {
+ refreshScrollbarsVisibility(canScroll.x, canScroll.y);
+ }
+ else if (scrollbarsVisibilityVisible) {
+ refreshScrollbarsVisibility(true);
+ }
+ else if (scrollbarsVisibilityHidden) {
+ refreshScrollbarsVisibility(false);
+ }
+ }
+
+ //manage the scrollbars auto hide feature (auto hide them after specific actions)
+ if (scrollbarsAutoHideChanged || ignoreOverlayScrollbarHidingChanged) {
+ setupHostMouseTouchEvents(!_scrollbarsAutoHideLeave && !_scrollbarsAutoHideMove);
+ refreshScrollbarsAutoHide(_scrollbarsAutoHideNever, !_scrollbarsAutoHideNever);
+ }
+
+ //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:
+ dispatchCallback('onDirectionChanged', {
+ isRTL: _isRTL,
+ dir: cssDirection
+ }, cssDirectionChanged);
+ dispatchCallback('onHostSizeChanged', {
+ width: _hostSizeCache.w,
+ height: _hostSizeCache.h
+ }, hostSizeChanged);
+ dispatchCallback('onContentSizeChanged', {
+ width: _contentScrollSizeCache.w,
+ height: _contentScrollSizeCache.h
+ }, contentSizeChanged);
+ dispatchCallback('onOverflowChanged', {
+ x: hasOverflow.x,
+ y: hasOverflow.y,
+ xScrollable: hideOverflow.xs,
+ yScrollable: hideOverflow.ys,
+ clipped: hideOverflow.x || hideOverflow.y
+ }, hasOverflow.c || hideOverflow.c);
+ dispatchCallback('onOverflowAmountChanged', {
+ x: overflowAmount.x,
+ y: overflowAmount.y
+ }, overflowAmount.c);
+ }
+
+ //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;
+ }
+
+ if (_initialized && changedOptions.updateOnLoad) {
+ updateElementsOnLoad();
+ }
+
+ //freezeResizeObserver(_sizeObserverElement, false);
+ //freezeResizeObserver(_sizeAutoObserverElement, false);
+
+ dispatchCallback('onUpdated', { forced: force });
+ }
+
+ /**
+ * Updates the found elements of which the load event shall be handled.
+ */
+ function updateElementsOnLoad() {
+ if (!_isTextarea) {
+ eachUpdateOnLoad(function (i, updateOnLoadSelector) {
+ _contentElement.find(updateOnLoadSelector).each(function (i, el) {
+ // if element doesn't have a updateOnLoadCallback applied
+ if (COMPATIBILITY.inA(el, _updateOnLoadElms) < 0) {
+ _updateOnLoadElms.push(el);
+ FRAMEWORK(el)
+ .off(_updateOnLoadEventName, updateOnLoadCallback)
+ .on(_updateOnLoadEventName, updateOnLoadCallback);
+ }
+ });
+ });
+ }
+ }
+
+ //==== 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.
+ */
+ /**
+ * 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,
+ _classNameHostElementForeign,
+ _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);
+
+ //add this class to workaround class changing issues with UI frameworks especially Vue
+ if (_domExists)
+ addClass(_hostElement, _classNameHostElementForeign);
+
+ //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 (COMPATIBILITY.isA(adoptAttrs) && _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 strClickEvent = 'click';
+ 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 stopClickEventPropagation(event) {
+ COMPATIBILITY.stpP(event);
+ }
+ 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);
+ COMPATIBILITY.rAF()(function() {
+ setupResponsiveEventListener(_documentElement, strClickEvent, stopClickEventPropagation, true, { _capture: 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]);
+ COMPATIBILITY.rAF()(function() {
+ setupResponsiveEventListener(_documentElement, strClickEvent, stopClickEventPropagation, false, { _capture: true });
+ });
+
+
+ if (_msieVersion || !_documentMixed)
+ COMPATIBILITY.prvD(event);
+ COMPATIBILITY.stpP(event);
+ }
+ function onTrackMouseTouchDown(event) {
+ if (onMouseTouchDownContinue(event)) {
+ var handleToViewportRatio = scrollbarVars._info._handleLength / Math.round(MATH.min(1, _viewportSize[scrollbarVars._w_h] / _contentScrollSizeCache[scrollbarVars._w_h]) * scrollbarVars._info._trackLength);
+ var scrollDistance = MATH.round(_viewportSize[scrollbarVars._w_h] * handleToViewportRatio);
+ var scrollBaseDuration = 270 * handleToViewportRatio;
+ var scrollFirstIterationDelay = 400 * handleToViewportRatio;
+ 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 = scrollBaseDuration * scrollDurationFactor;
+ var timeoutDelay = isFirstIteration ? MATH.max(scrollFirstIterationDelay, 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, _strMouseEnter, _strMouseLeave],
+ [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 scrollbarHiddenClassName = isHorizontal ? _classNameHostScrollbarHorizontalHidden : _classNameHostScrollbarVerticalHidden;
+ var scrollbarElement = isHorizontal ? _scrollbarHorizontalElement : _scrollbarVerticalElement;
+
+ addRemoveClass(_hostElement, scrollbarHiddenClassName, !shallBeVisible);
+ addRemoveClass(scrollbarElement, _classNameScrollbarUnusable, !canScroll);
+ }
+
+ /**
+ * 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, _viewportSize[scrollbarVars._w_h] / _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.
+ * @param dependent Boolean which decides whether the callback shall be fired, undefined is like a "true" value.
+ */
+ function dispatchCallback(name, args, dependent) {
+ if (dependent === false)
+ return;
+ 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) {
+ prefix = prefix || _strEmpty;
+ values = 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];
+ }
+
+ /**
+ * Gets the "top, right, bottom, left" CSS properties of the CSS property with the given prefix from the host element.
+ * @param prefix The prefix of the "top, right, bottom, left" css properties. (example: 'padding-' is a valid prefix)
+ * @param suffix The suffix of the "top, right, bottom, left" css properties. (example: 'border-' is a valid prefix with '-width' is a valid suffix)
+ * @param zeroX True if the x axis shall be 0.
+ * @param zeroY True if the y axis shall be 0.
+ * @returns {{}} The object which contains the numbers of the read CSS properties.
+ */
+ function getTopRightBottomLeftHost(prefix, suffix, zeroX, zeroY) {
+ suffix = suffix || _strEmpty;
+ prefix = prefix || _strEmpty;
+ return {
+ t: zeroY ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strTop + suffix)),
+ r: zeroX ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strRight + suffix)),
+ b: zeroY ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strBottom + suffix)),
+ l: zeroX ? 0 : parseToZeroOrNumber(_hostElement.css(prefix + _strLeft + suffix))
+ };
+ }
+
+ /**
+ * 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(', ');
+ }
+
+ /**
+ * Generates a Regular Expression which matches with a string which starts with 'os-host'.
+ * @param {boolean} withCurrClassNameOption The Regular Expression also matches if the string is the current ClassName option (multiple values splitted by space possible).
+ * @param {boolean} withOldClassNameOption The Regular Expression also matches if the string is the old ClassName option (multiple values splitted by space possible).
+ */
+ function createHostClassNameRegExp(withCurrClassNameOption, withOldClassNameOption) {
+ var i;
+ var split;
+ var appendix;
+ var appendClasses = function (classes, condition) {
+ appendix = '';
+ if (condition && typeof classes == TYPES.s) {
+ split = classes.split(_strSpace);
+ for (i = 0; i < split[LEXICON.l]; i++)
+ appendix += '|' + split[i] + '$';
+ // split[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') for escaping regex characters
+ }
+ return appendix;
+ };
+
+ return new RegExp(
+ '(^' + _classNameHostElement + '([-_].+|)$)' +
+ appendClasses(_classNameCache, withCurrClassNameOption) +
+ appendClasses(_oldClassName, withOldClassNameOption), 'g');
+ }
+
+ /**
+ * 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 '<div ' + (classesOrAttrs ? type(classesOrAttrs) == TYPES.s ?
+ 'class="' + classesOrAttrs + '"' :
+ (function () {
+ var key;
+ var attrs = _strEmpty;
+ if (FRAMEWORK.isPlainObject(classesOrAttrs)) {
+ for (key in classesOrAttrs)
+ attrs += (key === 'c' ? 'class' : key) + '="' + classesOrAttrs[key] + '" ';
+ }
+ return attrs;
+ })() :
+ _strEmpty) +
+ '>' +
+ (content || _strEmpty) +
+ '</div>';
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Runs a action for each selector inside the updateOnLoad option.
+ * @param {Function} action The action for each updateOnLoad selector, the arguments the function takes is the index and the value (the selector).
+ */
+ function eachUpdateOnLoad(action) {
+ var updateOnLoad = _currentPreparedOptions.updateOnLoad;
+ updateOnLoad = type(updateOnLoad) == TYPES.s ? updateOnLoad.split(_strSpace) : updateOnLoad;
+
+ if (COMPATIBILITY.isA(updateOnLoad) && !_destroyed) {
+ each(updateOnLoad, action);
+ }
+ }
+
+
+ //==== 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);
+ }
+
+ /**
+ * Adds or removes the given classes dependent on the boolean value. True for add, false for remove.
+ */
+ function addRemoveClass(el, classes, doAdd) {
+ return doAdd ? addClass(el, classes) : removeClass(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 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 });
+ }
+
+ updateElementsOnLoad();
+
+ 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 < _updateOnLoadElms[LEXICON.l]; i++)
+ FRAMEWORK(_updateOnLoadElms[i]).off(_updateOnLoadEventName, updateOnLoadCallback);
+ _updateOnLoadElms = 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 (COMPATIBILITY.isA(coordinates))
+ 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, 0) //'<' = 0%
+ [strReplace](/max/g, (normalizeShortcuts ? '-' : _strEmpty) + _strHundredPercent) //'max' = 100%
+ [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 (COMPATIBILITY.isA(easing) || 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)
+ *
+ * <div class="os-host">
+ * <div class="os-resize-observer-host"></div>
+ * <div class="os-padding">
+ * <div class="os-viewport">
+ * <div class="os-content"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-horizontal ">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-vertical">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar-corner"></div>
+ * </div>
+ *
+ * =====================================================================================
+ *
+ * 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)
+ *
+ * <div class="os-host-textarea">
+ * <div class="os-resize-observer-host"></div>
+ * <div class="os-padding os-text-inherit">
+ * <div class="os-viewport os-text-inherit">
+ * <div class="os-content os-text-inherit">
+ * <div class="os-textarea-cover"></div>
+ * <textarea class="os-textarea os-text-inherit"></textarea>
+ * </div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-horizontal ">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar os-scrollbar-vertical">
+ * <div class="os-scrollbar-track">
+ * <div class="os-scrollbar-handle"></div>
+ * </div>
+ * </div>
+ * <div class="os-scrollbar-corner"></div>
+ * </div>
+ */
+ _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 <div>, 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/src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js b/src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js
new file mode 100644
index 0000000..3654b72
--- /dev/null
+++ b/src/main/resources/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js
@@ -0,0 +1,13 @@
+/*!
+ * OverlayScrollbars
+ * https://github.com/KingSora/OverlayScrollbars
+ *
+ * Version: 1.13.0
+ *
+ * Copyright KingSora | Rene Haas.
+ * https://github.com/KingSora
+ *
+ * Released under the MIT license.
+ * Date: 02.08.2020
+ */
+!function(t,r){"function"==typeof define&&define.amd?define(["jquery"],function(n){return r(t,t.document,undefined,n)}):"object"==typeof module&&"object"==typeof module.exports?module.exports=r(t,t.document,undefined,require("jquery")):r(t,t.document,undefined,t.jQuery)}("undefined"!=typeof window?window:this,function(vi,di,hi,n){"use strict";var o,l,f,a,pi="object",bi="function",yi="array",mi="string",gi="boolean",wi="number",t="null",xi={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"},_i=(o={},l={},{e:f=["-webkit-","-moz-","-o-","-ms-"],o:a=["WebKit","Moz","O","MS"],u:function(n){var t=l[n];if(l[xi.hOP](n))return t;for(var r,e,i,o=c(n),a=di.createElement("div")[xi.s],u=0;u<f.length;u++)for(i=f[u].replace(/-/g,""),r=[n,f[u]+n,i+o,c(i)+o],e=0;e<r[xi.l];e++)if(a[r[e]]!==hi){t=r[e];break}return l[n]=t},v:function(n,t,r){var e=n+" "+t,i=l[e];if(l[xi.hOP](e))return i;for(var o,a=di.createElement("div")[xi.s],u=t.split(" "),f=r||"",c=0,s=-1;c<u[xi.l];c++)for(;s<_i.e[xi.l];s++)if(o=s<0?u[c]:_i.e[s]+u[c],a.cssText=n+":"+o+f,a[xi.l]){i=o;break}return l[e]=i},d:function(n,t,r){var e=0,i=o[n];if(!o[xi.hOP](n)){for(i=vi[n];e<a[xi.l];e++)i=i||vi[(t?a[e]:a[e].toLowerCase())+c(n)];o[n]=i}return i||r}});function c(n){return n.charAt(0).toUpperCase()+n.slice(1)}var Si={wW:e(r,0,!0),wH:e(r,0),mO:e(_i.d,0,"MutationObserver",!0),rO:e(_i.d,0,"ResizeObserver",!0),rAF:e(_i.d,0,"requestAnimationFrame",!1,function(n){return vi.setTimeout(n,1e3/60)}),cAF:e(_i.d,0,"cancelAnimationFrame",!1,function(n){return vi.clearTimeout(n)}),now:function(){return Date.now&&Date.now()||(new Date).getTime()},stpP:function(n){n.stopPropagation?n.stopPropagation():n.cancelBubble=!0},prvD:function(n){n.preventDefault&&n.cancelable?n.preventDefault():n.returnValue=!1},page:function(n){var t=((n=n.originalEvent||n).target||n.srcElement||di).ownerDocument||di,r=t.documentElement,e=t.body;if(n.touches===hi)return!n.pageX&&n.clientX&&null!=n.clientX?{x:n.clientX+(r&&r.scrollLeft||e&&e.scrollLeft||0)-(r&&r.clientLeft||e&&e.clientLeft||0),y:n.clientY+(r&&r.scrollTop||e&&e.scrollTop||0)-(r&&r.clientTop||e&&e.clientTop||0)}:{x:n.pageX,y:n.pageY};var i=n.touches[0];return{x:i.pageX,y:i.pageY}},mBtn:function(n){var t=n.button;return n.which||t===hi?n.which:1&t?1:2&t?3:4&t?2:0},inA:function(n,t){for(var r=0;r<t[xi.l];r++)try{if(t[r]===n)return r}catch(e){}return-1},isA:function(n){var t=Array.isArray;return t?t(n):this.type(n)==yi},type:function(n){return n===hi||null===n?n+"":Object[xi.p].toString.call(n).replace(/^\[object (.+)\]$/,"$1").toLowerCase()},bind:e};function r(n){return n?vi.innerWidth||di.documentElement[xi.cW]||di.body[xi.cW]:vi.innerHeight||di.documentElement[xi.cH]||di.body[xi.cH]}function e(n,t){if(typeof n!=bi)throw"Can't bind function!";var r=xi.p,e=Array[r].slice.call(arguments,2),i=function(){},o=function(){return n.apply(this instanceof i?this:t,e.concat(Array[r].slice.call(arguments)))};return n[r]&&(i[r]=n[r]),o[r]=new i,o}var i,u,zi,s,v,L,N,d,h,p,b,y,m,g,Ti,Oi=Math,ki=n,Ci=(n.easing,n),Ai=(i=[],u="__overlayScrollbars__",function(n,t){var r=arguments[xi.l];if(r<1)return i;if(t)n[u]=t,i.push(n);else{var e=Si.inA(n,i);if(-1<e){if(!(1<r))return i[e][u];delete n[u],i.splice(e,1)}}}),w=(g=[],L=Si.type,y={className:["os-theme-dark",[t,mi]],resize:["none","n:none b:both h:horizontal v:vertical"],sizeAutoCapable:d=[!0,gi],clipAlways:d,normalizeRTL:d,paddingAbsolute:h=[!(N=[gi,wi,mi,yi,pi,bi,t]),gi],autoUpdate:[null,[t,gi]],autoUpdateInterval:[33,wi],updateOnLoad:[["img"],[mi,yi,t]],nativeScrollbarsOverlaid:{showNativeScrollbars:h,initialize:d},overflowBehavior:{x:["scroll",b="v-h:visible-hidden v-s:visible-scroll s:scroll h:hidden"],y:["scroll",b]},scrollbars:{visibility:["auto","v:visible h:hidden a:auto"],autoHide:["never","n:never s:scroll l:leave m:move"],autoHideDelay:[800,wi],dragScrolling:d,clickScrolling:h,touchSupport:d,snapHandle:h},textarea:{dynWidth:h,dynHeight:h,inheritedAttrs:[["style","class"],[mi,yi,t]]},callbacks:{onInitialized:p=[null,[t,bi]],onInitializationWithdrawn:p,onDestroyed:p,onScrollStart:p,onScroll:p,onScrollStop:p,onOverflowChanged:p,onOverflowAmountChanged:p,onDirectionChanged:p,onContentSizeChanged:p,onHostSizeChanged:p,onUpdated:p}},Ti={m:(m=function(i){var o=function(n){var t,r,e;for(t in n)n[xi.hOP](t)&&(r=n[t],(e=L(r))==yi?n[t]=r[i?1:0]:e==pi&&(n[t]=o(r)));return n};return o(Ci.extend(!0,{},y))})(),g:m(!0),_:function(n,t,C,r){var e={},i={},o=Ci.extend(!0,{},n),A=Ci.inArray,H=Ci.isEmptyObject,R=function(n,t,r,e,i,o){for(var a in t)if(t[xi.hOP](a)&&n[xi.hOP](a)){var u,f,c,s,l,v,d,h,p=!1,b=!1,y=t[a],m=L(y),g=m==pi,w=Si.isA(y)?y:[y],x=r[a],_=n[a],S=L(_),z=o?o+".":"",T='The option "'+z+a+"\" wasn't set, because",O=[],k=[];if(x=x===hi?{}:x,g&&S==pi)e[a]={},i[a]={},R(_,y,x,e[a],i[a],z+a),Ci.each([n,e,i],function(n,t){H(t[a])&&delete t[a]});else if(!g){for(v=0;v<w[xi.l];v++)if(l=w[v],c=(m=L(l))==mi&&-1===A(l,N))for(O.push(mi),u=l.split(" "),k=k.concat(u),d=0;d<u[xi.l];d++){for(s=(f=u[d].split(":"))[0],h=0;h<f[xi.l];h++)if(_===f[h]){p=!0;break}if(p)break}else if(O.push(l),S===l){p=!0;break}p?((b=_!==x)&&(e[a]=_),(c?A(x,f)<0:b)&&(i[a]=c?s:_)):C&&console.warn(T+" it doesn't accept the type [ "+S.toUpperCase()+' ] with the value of "'+_+'".\r\nAccepted types are: [ '+O.join(", ").toUpperCase()+" ]."+(0<k[length]?"\r\nValid strings are: [ "+k.join(", ").split(":").join(", ")+" ].":"")),delete n[a]}}};return R(o,t,r||{},e,i),!H(o)&&C&&console.warn("The following options are discarded due to invalidity:\r\n"+vi.JSON.stringify(o,null,2)),{S:e,z:i}}},(zi=vi.OverlayScrollbars=function(n,r,e){if(0===arguments[xi.l])return this;var i,t,o=[],a=Ci.isPlainObject(r);return n?(n=n[xi.l]!=hi?n:[n[0]||n],x(),0<n[xi.l]&&(a?Ci.each(n,function(n,t){(i=t)!==hi&&o.push(z(i,r,e,s,v))}):Ci.each(n,function(n,t){i=Ai(t),("!"===r&&zi.valid(i)||Si.type(r)==bi&&r(t,i)||r===hi)&&o.push(i)}),t=1===o[xi.l]?o[0]:o),t):a||!r?t:o}).globals=function(){x();var n=Ci.extend(!0,{},s);return delete n.msie,n},zi.defaultOptions=function(n){x();var t=s.defaultOptions;if(n===hi)return Ci.extend(!0,{},t);s.defaultOptions=Ci.extend(!0,{},t,Ti._(n,Ti.g,!0,t).S)},zi.valid=function(n){return n instanceof zi&&!n.getState().destroyed},zi.extension=function(n,t,r){var e=Si.type(n)==mi,i=arguments[xi.l],o=0;if(i<1||!e)return Ci.extend(!0,{length:g[xi.l]},g);if(e)if(Si.type(t)==bi)g.push({name:n,extensionFactory:t,defaultOptions:r});else for(;o<g[xi.l];o++)if(g[o].name===n){if(!(1<i))return Ci.extend(!0,{},g[o]);g.splice(o,1)}},zi);function x(){s=s||new _(Ti.m),v=v||new S(s)}function _(n){var _=this,i="overflow",S=Ci("body"),z=Ci('<div id="os-dummy-scrollbar-size"><div></div></div>'),o=z[0],e=Ci(z.children("div").eq(0));S.append(z),z.hide().show();var t,r,a,u,f,c,s,l,v,d=T(o),h={x:0===d.x,y:0===d.y},p=(r=vi.navigator.userAgent,u="substring",f=r[a="indexOf"]("MSIE "),c=r[a]("Trident/"),s=r[a]("Edge/"),l=r[a]("rv:"),v=parseInt,0<f?t=v(r[u](f+5,r[a](".",f)),10):0<c?t=v(r[u](l+3,r[a](".",l)),10):0<s&&(t=v(r[u](s+5,r[a](".",s)),10)),t);function T(n){return{x:n[xi.oH]-n[xi.cH],y:n[xi.oW]-n[xi.cW]}}Ci.extend(_,{defaultOptions:n,msie:p,autoUpdateLoop:!1,autoUpdateRecommended:!Si.mO(),nativeScrollbarSize:d,nativeScrollbarIsOverlaid:h,nativeScrollbarStyling:function(){var n=!1;z.addClass("os-viewport-native-scrollbars-invisible");try{n="none"===z.css("scrollbar-width")&&(9<p||!p)||"none"===vi.getComputedStyle(o,"::-webkit-scrollbar").getPropertyValue("display")}catch(t){}return n}(),overlayScrollbarDummySize:{x:30,y:30},cssCalc:_i.v("width","calc","(1px)")||null,restrictedMeasuring:function(){z.css(i,"hidden");var n=o[xi.sW],t=o[xi.sH];z.css(i,"visible");var r=o[xi.sW],e=o[xi.sH];return n-r!=0||t-e!=0}(),rtlScrollBehavior:function(){z.css({"overflow-y":"hidden","overflow-x":"scroll",direction:"rtl"}).scrollLeft(0);var n=z.offset(),t=e.offset();z.scrollLeft(-999);var r=e.offset();return{i:n.left===t.left,n:t.left!==r.left}}(),supportTransform:!!_i.u("transform"),supportTransition:!!_i.u("transition"),supportPassiveEvents:function(){var n=!1;try{vi.addEventListener("test",null,Object.defineProperty({},"passive",{get:function(){n=!0}}))}catch(t){}return n}(),supportResizeObserver:!!Si.rO(),supportMutationObserver:!!Si.mO()}),z.removeAttr(xi.s).remove(),function(){if(!h.x||!h.y){var y=Oi.abs,m=Si.wW(),g=Si.wH(),w=x();Ci(vi).on("resize",function(){if(0<Ai().length){var n=Si.wW(),t=Si.wH(),r=n-m,e=t-g;if(0==r&&0==e)return;var i,o=Oi.round(n/(m/100)),a=Oi.round(t/(g/100)),u=y(r),f=y(e),c=y(o),s=y(a),l=x(),v=2<u&&2<f,d=!function b(n,t){var r=y(n),e=y(t);return r!==e&&r+1!==e&&r-1!==e}(c,s),h=v&&d&&(l!==w&&0<w),p=_.nativeScrollbarSize;h&&(S.append(z),i=_.nativeScrollbarSize=T(z[0]),z.remove(),p.x===i.x&&p.y===i.y||Ci.each(Ai(),function(){Ai(this)&&Ai(this).update("zoom")})),m=n,g=t,w=l}})}function x(){var n=vi.screen.deviceXDPI||0,t=vi.screen.logicalXDPI||1;return vi.devicePixelRatio||n/t}}()}function S(r){var c,e=Ci.inArray,s=Si.now,l="autoUpdate",v=xi.l,d=[],h=[],p=!1,b=33,y=s(),m=function(){if(0<d[v]&&p){c=Si.rAF()(function(){m()});var n,t,r,e,i,o,a=s(),u=a-y;if(b<u){y=a-u%b,n=33;for(var f=0;f<d[v];f++)(t=d[f])!==hi&&(e=(r=t.options())[l],i=Oi.max(1,r.autoUpdateInterval),o=s(),(!0===e||null===e)&&o-h[f]>i&&(t.update("auto"),h[f]=new Date(o+=i)),n=Oi.max(1,Oi.min(n,i)));b=n}}else b=33};this.add=function(n){-1===e(n,d)&&(d.push(n),h.push(s()),0<d[v]&&!p&&(p=!0,r.autoUpdateLoop=p,m()))},this.remove=function(n){var t=e(n,d);-1<t&&(h.splice(t,1),d.splice(t,1),0===d[v]&&p&&(p=!1,r.autoUpdateLoop=p,c!==hi&&(Si.cAF()(c),c=-1)))}}function z(r,n,t,xt,_t){var cn=Si.type,sn=Ci.inArray,d=Ci.each,St=new zi,e=Ci[xi.p];if(dt(r)){if(Ai(r)){var i=Ai(r);return i.options(n),i}var zt,Tt,Ot,kt,I,Ct,At,Ht,j,ln,g,A,h,Rt,Lt,Nt,Wt,w,p,Dt,Mt,Et,It,jt,Ft,Pt,Ut,Vt,$t,o,a,qt,Bt,Xt,u,F,c,P,Yt,Kt,Gt,Jt,Qt,Zt,nr,tr,rr,er,ir,f,s,l,v,b,y,x,H,or,ar,ur,R,fr,cr,sr,lr,vr,dr,hr,pr,br,yr,mr,gr,wr,xr,_r,L,Sr,zr,Tr,Or,kr,Cr,Ar,Hr,m,_,Rr,Lr,Nr,Wr,Dr,Mr,Er,Ir,jr,Fr,Pr,Ur,Vr,$r,S,z,T,O,qr,Br,k,C,Xr,Yr,Kr,Gr,Jr,U,V,Qr,Zr,ne,te,re={},vn={},dn={},ee={},ie={},N="-hidden",oe="margin-",ae="padding-",ue="border-",fe="top",ce="right",se="bottom",le="left",ve="min-",de="max-",he="width",pe="height",be="float",ye="",me="auto",hn="sync",ge="scroll",we="100%",pn="x",bn="y",W=".",xe=" ",D="scrollbar",M="-horizontal",E="-vertical",_e=ge+"Left",Se=ge+"Top",$="mousedown touchstart",q="mouseup touchend touchcancel",B="mousemove touchmove",X="mouseenter",Y="mouseleave",K="keydown",G="keyup",J="selectstart",Q="transitionend webkitTransitionEnd oTransitionEnd",Z="__overlayScrollbarsRO__",nn="os-",tn="os-html",rn="os-host",en=rn+"-foreign",on=rn+"-textarea",an=rn+"-"+D+M+N,un=rn+"-"+D+E+N,fn=rn+"-transition",ze=rn+"-rtl",Te=rn+"-resize-disabled",Oe=rn+"-scrolling",ke=rn+"-overflow",Ce=(ke=rn+"-overflow")+"-x",Ae=ke+"-y",yn="os-textarea",mn=yn+"-cover",gn="os-padding",wn="os-viewport",He=wn+"-native-scrollbars-invisible",xn=wn+"-native-scrollbars-overlaid",_n="os-content",Re="os-content-arrange",Le="os-content-glue",Ne="os-size-auto-observer",Sn="os-resize-observer",zn="os-resize-observer-item",Tn=zn+"-final",On="os-text-inherit",kn=nn+D,Cn=kn+"-track",An=Cn+"-off",Hn=kn+"-handle",Rn=Hn+"-off",Ln=kn+"-unusable",Nn=kn+"-"+me+N,Wn=kn+"-corner",We=Wn+"-resize",De=We+"-both",Me=We+M,Ee=We+E,Dn=kn+M,Mn=kn+E,En="os-dragging",Ie="os-theme-none",In=[He,xn,An,Rn,Ln,Nn,We,De,Me,Ee,En].join(xe),jn=[],Fn=[xi.ti],Pn={},je={},Fe=42,Un="load",Vn=[],$n={},qn=["wrap","cols","rows"],Bn=[xi.i,xi.c,xi.s,"open"].concat(Fn),Xn=[];return St.sleep=function(){$t=!0},St.update=function(n){var t,r,e,i,o;if(!Lt)return cn(n)==mi?n===me?(t=function a(){if(!$t&&!qr){var r,e,i,o=[],n=[{T:Kt,O:Bn.concat(":visible")},{T:Nt?Yt:hi,O:qn}];return d(n,function(n,t){(r=t.T)&&d(t.O,function(n,t){e=":"===t.charAt(0)?r.is(t):r.attr(t),i=$n[t],ui(e,i)&&o.push(t),$n[t]=e})}),it(o),0<o[xi.l]}}(),r=function f(){if($t)return!1;var n,t,r,e,i=oi(),o=Nt&&br&&!jr?Yt.val().length:0,a=!qr&&br&&!Nt,u={};return a&&(n=nr.css(be),u[be]=Vt?ce:le,u[he]=me,nr.css(u)),e={w:i[xi.sW]+o,h:i[xi.sH]+o},a&&(u[be]=n,u[he]=we,nr.css(u)),t=qe(),r=ui(e,m),m=e,r||t}(),(e=t||r)&&Xe({k:r,C:Rt?hi:qt})):n===hn?qr?(i=T(S.takeRecords()),o=O(z.takeRecords())):i=St.update(me):"zoom"===n&&Xe({A:!0,k:!0}):(n=$t||n,$t=!1,St.update(hn)&&!n||Xe({H:n})),Ye(),e||i||o},St.options=function(n,t){var r,e={};if(Ci.isEmptyObject(n)||!Ci.isPlainObject(n)){if(cn(n)!=mi)return a;if(!(1<arguments.length))return bt(a,n);!function f(n,t,r){for(var e=t.split(W),i=e.length,o=0,a={},u=a;o<i;o++)a=a[e[o]]=o+1<i?{}:r;Ci.extend(n,u,!0)}(e,n,t),r=ot(e)}else r=ot(n);Ci.isEmptyObject(r)||Xe({C:r})},St.destroy=function(){if(!Lt){for(var n in _t.remove(St),Ve(),Pe(Jt),Pe(Gt),Pn)St.removeExt(n);for(;0<Xn[xi.l];)Xn.pop()();$e(!0),rr&&mt(rr),tr&&mt(tr),Mt&&mt(Gt),ft(!0),st(!0),at(!0);for(var t=0;t<Vn[xi.l];t++)Ci(Vn[t]).off(Un,rt);Vn=hi,$t=Lt=!0,Ai(r,0),ti("onDestroyed")}},St.scroll=function(n,t,r,e){if(0===arguments.length||n===hi){var i=Mr&&Vt&&Ot.i,o=Mr&&Vt&&Ot.n,a=vn.R,u=vn.L,f=vn.N;return u=i?1-u:u,a=i?f-a:a,f*=o?-1:1,{position:{x:a*=o?-1:1,y:dn.R},ratio:{x:u,y:dn.L},max:{x:f,y:dn.N},handleOffset:{x:vn.W,y:dn.W},handleLength:{x:vn.D,y:dn.D},handleLengthRatio:{x:vn.M,y:dn.M},trackLength:{x:vn.I,y:dn.I},snappedHandleOffset:{x:vn.j,y:dn.j},isRTL:Vt,isRTLNormalized:Mr}}St.update(hn);var c,s,l,v,d,m,g,h,p,w=Mr,b=[pn,le,"l"],y=[bn,fe,"t"],x=["+=","-=","*=","/="],_=cn(t)==pi,S=_?t.complete:e,z={},T={},O="begin",k="nearest",C="never",A="ifneeded",H=xi.l,R=[pn,bn,"xy","yx"],L=[O,"end","center",k],N=["always",C,A],W=n[xi.hOP]("el"),D=W?n.el:n,M=!!(D instanceof Ci||ki)&&D instanceof ki,E=!M&&dt(D),I=function(){s&&Qe(!0),l&&Qe(!1)},j=cn(S)!=bi?hi:function(){I(),S()};function F(n,t){for(c=0;c<t[H];c++)if(n===t[c])return 1}function P(n,t){var r=n?b:y;if(t=cn(t)==mi||cn(t)==wi?[t,t]:t,Si.isA(t))return n?t[0]:t[1];if(cn(t)==pi)for(c=0;c<r[H];c++)if(r[c]in t)return t[r[c]]}function U(n,t){var r,e,i,o,a=cn(t)==mi,u=n?vn:dn,f=u.R,c=u.N,s=Vt&&n,l=s&&Ot.n&&!w,v="replace",d=eval;if((e=a?(2<t[H]&&(o=t.substr(0,2),-1<sn(o,x)&&(r=o)),t=(t=r?t.substr(2):t)[v](/min/g,0)[v](/</g,0)[v](/max/g,(l?"-":ye)+we)[v](/>/g,(l?"-":ye)+we)[v](/px/g,ye)[v](/%/g," * "+c*(s&&Ot.n?-1:1)/100)[v](/vw/g," * "+ee.w)[v](/vh/g," * "+ee.h),ii(isNaN(t)?ii(d(t),!0).toFixed():t)):t)!==hi&&!isNaN(e)&&cn(e)==wi){var h=w&&s,p=f*(h&&Ot.n?-1:1),b=h&&Ot.i,y=h&&Ot.n;switch(p=b?c-p:p,r){case"+=":i=p+e;break;case"-=":i=p-e;break;case"*=":i=p*e;break;case"/=":i=p/e;break;default:i=e}i=b?c-i:i,i*=y?-1:1,i=s&&Ot.n?Oi.min(0,Oi.max(c,i)):Oi.max(0,Oi.min(c,i))}return i===f?hi:i}function V(n,t,r,e){var i,o,a=[r,r],u=cn(n);if(u==t)n=[n,n];else if(u==yi){if(2<(i=n[H])||i<1)n=a;else for(1===i&&(n[1]=r),c=0;c<i;c++)if(o=n[c],cn(o)!=t||!F(o,e)){n=a;break}}else n=u==pi?[n[pn]||r,n[bn]||r]:a;return{x:n[0],y:n[1]}}function $(n){var t,r,e=[],i=[fe,ce,se,le];for(c=0;c<n[H]&&c!==i[H];c++)t=n[c],(r=cn(t))==gi?e.push(t?ii(p.css(oe+i[c])):0):e.push(r==wi?t:0);return e}if(M||E){var q,B=W?n.margin:0,X=W?n.axis:0,Y=W?n.scroll:0,K=W?n.block:0,G=[0,0,0,0],J=cn(B);if(0<(p=M?D:Ci(D))[H]){B=J==wi||J==gi?$([B,B,B,B]):J==yi?2===(q=B[H])?$([B[0],B[1],B[0],B[1]]):4<=q?$(B):G:J==pi?$([B[fe],B[ce],B[se],B[le]]):G,d=F(X,R)?X:"xy",m=V(Y,mi,"always",N),g=V(K,mi,O,L),h=B;var Q=vn.R,Z=dn.R,nn=Qt.offset(),tn=p.offset(),rn={x:m.x==C||d==bn,y:m.y==C||d==pn};tn[fe]-=h[0],tn[le]-=h[3];var en={x:Oi.round(tn[le]-nn[le]+Q),y:Oi.round(tn[fe]-nn[fe]+Z)};if(Vt&&(Ot.n||Ot.i||(en.x=Oi.round(nn[le]-tn[le]+Q)),Ot.n&&w&&(en.x*=-1),Ot.i&&w&&(en.x=Oi.round(nn[le]-tn[le]+(vn.N-Q)))),g.x!=O||g.y!=O||m.x==A||m.y==A||Vt){var on=p[0],an=ln?on[xi.bCR]():{width:on[xi.oW],height:on[xi.oH]},un={w:an[he]+h[3]+h[1],h:an[pe]+h[0]+h[2]},fn=function(n){var t=ni(n),r=t.F,e=t.P,i=t.U,o=g[i]==(n&&Vt?O:"end"),a="center"==g[i],u=g[i]==k,f=m[i]==C,c=m[i]==A,s=ee[r],l=nn[e],v=un[r],d=tn[e],h=a?2:1,p=d+v/2,b=l+s/2,y=v<=s&&l<=d&&d+v<=l+s;f?rn[i]=!0:rn[i]||((u||c)&&(rn[i]=c&&y,o=v<s?b<p:p<b),en[i]-=o||a?(s/h-v/h)*(n&&Vt&&w?-1:1):0)};fn(!0),fn(!1)}rn.y&&delete en.y,rn.x&&delete en.x,n=en}}z[_e]=U(!0,P(!0,n)),z[Se]=U(!1,P(!1,n)),s=z[_e]!==hi,l=z[Se]!==hi,(s||l)&&(0<t||_)?_?(t.complete=j,Zt.animate(z,t)):(v={duration:t,complete:j},Si.isA(r)||Ci.isPlainObject(r)?(T[_e]=r[0]||r.x,T[Se]=r[1]||r.y,v.specialEasing=T):v.easing=r,Zt.animate(z,v)):(s&&Zt[_e](z[_e]),l&&Zt[Se](z[Se]),I())},St.scrollStop=function(n,t,r){return Zt.stop(n,t,r),St},St.getElements=function(n){var t={target:or,host:ar,padding:fr,viewport:cr,content:sr,scrollbarHorizontal:{scrollbar:f[0],track:s[0],handle:l[0]},scrollbarVertical:{scrollbar:v[0],track:b[0],handle:y[0]},scrollbarCorner:ir[0]};return cn(n)==mi?bt(t,n):t},St.getState=function(n){function t(n){if(!Ci.isPlainObject(n))return n;var r=fi({},n),t=function(n,t){r[xi.hOP](n)&&(r[t]=r[n],delete r[n])};return t("w",he),t("h",pe),delete r.c,r}var r={destroyed:!!t(Lt),sleeping:!!t($t),autoUpdate:t(!qr),widthAuto:t(br),heightAuto:t(yr),padding:t(gr),overflowAmount:t(kr),hideOverflow:t(pr),hasOverflow:t(hr),contentScrollSize:t(vr),viewportSize:t(ee),hostSize:t(lr),documentMixed:t(w)};return cn(n)==mi?bt(r,n):r},St.ext=function(n){var t,r="added removed on contract".split(" "),e=0;if(cn(n)==mi){if(Pn[xi.hOP](n))for(t=fi({},Pn[n]);e<r.length;e++)delete t[r[e]]}else for(e in t={},Pn)t[e]=fi({},St.ext(e));return t},St.addExt=function(n,t){var r,e,i,o,a=zi.extension(n),u=!0;if(a){if(Pn[xi.hOP](n))return St.ext(n);if((r=a.extensionFactory.call(St,fi({},a.defaultOptions),Ci,Si))&&(i=r.contract,cn(i)==bi&&(o=i(vi),u=cn(o)==gi?o:u),u))return e=(Pn[n]=r).added,cn(e)==bi&&e(t),St.ext(n)}else console.warn('A extension with the name "'+n+"\" isn't registered.")},St.removeExt=function(n){var t,r=Pn[n];return!!r&&(delete Pn[n],t=r.removed,cn(t)==bi&&t(),!0)},zi.valid(function wt(n,t,r){var e,i;return o=xt.defaultOptions,Ct=xt.nativeScrollbarStyling,Ht=fi({},xt.nativeScrollbarSize),zt=fi({},xt.nativeScrollbarIsOverlaid),Tt=fi({},xt.overlayScrollbarDummySize),Ot=fi({},xt.rtlScrollBehavior),ot(fi({},o,t)),At=xt.cssCalc,I=xt.msie,kt=xt.autoUpdateRecommended,j=xt.supportTransition,ln=xt.supportTransform,g=xt.supportPassiveEvents,A=xt.supportResizeObserver,h=xt.supportMutationObserver,xt.restrictedMeasuring,F=Ci(n.ownerDocument),H=F[0],u=Ci(H.defaultView||H.parentWindow),x=u[0],c=gt(F,"html"),P=gt(c,"body"),Yt=Ci(n),or=Yt[0],Nt=Yt.is("textarea"),Wt=Yt.is("body"),w=H!==di,p=Nt?Yt.hasClass(yn)&&Yt.parent().hasClass(_n):Yt.hasClass(rn)&&Yt.children(W+gn)[xi.l],zt.x&&zt.y&&!qt.nativeScrollbarsOverlaid.initialize?(ti("onInitializationWithdrawn"),p&&(at(!0),ft(!0),st(!0)),$t=Lt=!0):(Wt&&((e={}).l=Oi.max(Yt[_e](),c[_e](),u[_e]()),e.t=Oi.max(Yt[Se](),c[Se](),u[Se]()),i=function(){Zt.removeAttr(xi.ti),Yn(Zt,$,i,!0,!0)}),at(),ft(),st(),ut(),ct(!0),ct(!1),function s(){var r,t=x.top!==x,e={},i={},o={};function a(n){if(f(n)){var t=c(n),r={};(ne||Zr)&&(r[he]=i.w+(t.x-e.x)*o.x),(te||Zr)&&(r[pe]=i.h+(t.y-e.y)*o.y),Kt.css(r),Si.stpP(n)}else u(n)}function u(n){var t=n!==hi;Yn(F,[J,B,q],[tt,a,u],!0),si(P,En),ir.releaseCapture&&ir.releaseCapture(),t&&(r&&Ue(),St.update(me)),r=!1}function f(n){var t=(n.originalEvent||n).touches!==hi;return!$t&&!Lt&&(1===Si.mBtn(n)||t)}function c(n){return I&&t?{x:n.screenX,y:n.screenY}:Si.page(n)}Kn(ir,$,function(n){f(n)&&!Qr&&(qr&&(r=!0,Ve()),e=c(n),i.w=ar[xi.oW]-(Dt?0:Et),i.h=ar[xi.oH]-(Dt?0:It),o=vt(),Yn(F,[J,B,q],[tt,a,u]),ci(P,En),ir.setCapture&&ir.setCapture(),Si.prvD(n),Si.stpP(n))})}(),Gn(),Pe(Jt,Jn),Wt&&(Zt[_e](e.l)[Se](e.t),di.activeElement==n&&cr.focus&&(Zt.attr(xi.ti,"-1"),cr.focus(),Yn(Zt,$,i,!1,!0))),St.update(me),Rt=!0,ti("onInitialized"),d(jn,function(n,t){ti(t.n,t.a)}),jn=[],cn(r)==mi&&(r=[r]),Si.isA(r)?d(r,function(n,t){St.addExt(t)}):Ci.isPlainObject(r)&&d(r,function(n,t){St.addExt(n,t)}),setTimeout(function(){j&&!Lt&&ci(Kt,fn)},333)),St}(r,n,t))&&Ai(r,St),St}function Yn(n,t,r,e,i){var o=Si.isA(t)&&Si.isA(r),a=e?"removeEventListener":"addEventListener",u=e?"off":"on",f=!o&&t.split(xe),c=0,s=Ci.isPlainObject(i),l=g&&(s?i.V:i)||!1,v=s&&(i.$||!1),d=g?{passive:l,capture:v}:v;if(o)for(;c<t[xi.l];c++)Yn(n,t[c],r[c],e,i);else for(;c<f[xi.l];c++)g?n[0][a](f[c],r,d):n[u](f[c],r)}function Kn(n,t,r,e){Yn(n,t,r,!1,e),Xn.push(Si.bind(Yn,0,n,t,r,!0,e))}function Pe(n,t){if(n){var r=Si.rO(),e="animationstart mozAnimationStart webkitAnimationStart MSAnimationStart",i="childNodes",o=3333333,a=function(){n[Se](o)[_e](Vt?Ot.n?-o:Ot.i?0:o:o),t()};if(t){if(A)((k=n.addClass("observed").append(ai(Sn)).contents()[0])[Z]=new r(a)).observe(k);else if(9<I||!kt){n.prepend(ai(Sn,ai({c:zn,dir:"ltr"},ai(zn,ai(Tn))+ai(zn,ai({c:Tn,style:"width: 200%; height: 200%"})))));var u,f,c,s,l=n[0][i][0][i][0],v=Ci(l[i][1]),d=Ci(l[i][0]),h=Ci(d[0][i][0]),p=l[xi.oW],b=l[xi.oH],y=xt.nativeScrollbarSize,m=function(){d[_e](o)[Se](o),v[_e](o)[Se](o)},g=function(){f=0,u&&(p=c,b=s,a())},w=function(n){return c=l[xi.oW],s=l[xi.oH],u=c!=p||s!=b,n&&u&&!f?(Si.cAF()(f),f=Si.rAF()(g)):n||g(),m(),n&&(Si.prvD(n),Si.stpP(n)),!1},x={},_={};ri(_,ye,[-2*(y.y+1),-2*y.x,-2*y.y,-2*(y.x+1)]),Ci(l).css(_),d.on(ge,w),v.on(ge,w),n.on(e,function(){w(!1)}),x[he]=o,x[pe]=o,h.css(x),m()}else{var S=H.attachEvent,z=I!==hi;if(S)n.prepend(ai(Sn)),gt(n,W+Sn)[0].attachEvent("onresize",a);else{var T=H.createElement(pi);T.setAttribute(xi.ti,"-1"),T.setAttribute(xi.c,Sn),T.onload=function(){var n=this.contentDocument.defaultView;n.addEventListener("resize",a),n.document.documentElement.style.display="none"},T.type="text/html",z&&n.prepend(T),T.data="about:blank",z||n.prepend(T),n.on(e,a)}}if(n[0]===R){var O=function(){var n=Kt.css("direction"),t={},r=0,e=!1;return n!==L&&(r="ltr"===n?(t[le]=0,t[ce]=me,o):(t[le]=me,t[ce]=0,Ot.n?-o:Ot.i?0:o),Jt.children().eq(0).css(t),Jt[_e](r)[Se](o),L=n,e=!0),e};O(),Kn(n,ge,function(n){return O()&&Xe(),Si.prvD(n),Si.stpP(n),!1})}}else if(A){var k,C=(k=n.contents()[0])[Z];C&&(C.disconnect(),delete k[Z])}else mt(n.children(W+Sn).eq(0))}}function Gn(){if(h){var o,a,u,f,c,s,r,e,i,l,n=Si.mO(),v=Si.now();O=function(n){var t=!1;return Rt&&!$t&&(d(n,function(){return!(t=function o(n){var t=n.attributeName,r=n.target,e=n.type,i="closest";if(r===sr)return null===t;if("attributes"===e&&(t===xi.c||t===xi.s)&&!Nt){if(t===xi.c&&Ci(r).hasClass(rn))return et(n.oldValue,r.className);if(typeof r[i]!=bi)return!0;if(null!==r[i](W+Sn)||null!==r[i](W+kn)||null!==r[i](W+Wn))return!1}return!0}(this))}),t&&(e=Si.now(),i=yr||br,l=function(){Lt||(v=e,Nt&&Be(),i?Xe():St.update(me))},clearTimeout(r),11<e-v||!i?l():r=setTimeout(l,11))),t},S=new n(T=function(n){var t,r=!1,e=!1,i=[];return Rt&&!$t&&(d(n,function(){o=(t=this).target,a=t.attributeName,u=a===xi.c,f=t.oldValue,c=o.className,p&&u&&!e&&-1<f.indexOf(en)&&c.indexOf(en)<0&&(s=lt(!0),ar.className=c.split(xe).concat(f.split(xe).filter(function(n){return n.match(s)})).join(xe),r=e=!0),r=r||(u?et(f,c):a!==xi.s||f!==o[xi.s].cssText),i.push(a)}),it(i),r&&St.update(e||me)),r}),z=new n(O)}}function Ue(){h&&!qr&&(S.observe(ar,{attributes:!0,attributeOldValue:!0,attributeFilter:Bn}),z.observe(Nt?or:sr,{attributes:!0,attributeOldValue:!0,subtree:!Nt,childList:!Nt,characterData:!Nt,attributeFilter:Nt?qn:Bn}),qr=!0)}function Ve(){h&&qr&&(S.disconnect(),z.disconnect(),qr=!1)}function Jn(){if(!$t){var n,t={w:R[xi.sW],h:R[xi.sH]};n=ui(t,_),_=t,n&&Xe({A:!0})}}function Qn(){Jr&&Ge(!0)}function Zn(){Jr&&!P.hasClass(En)&&Ge(!1)}function nt(){Gr&&(Ge(!0),clearTimeout(C),C=setTimeout(function(){Gr&&!Lt&&Ge(!1)},100))}function tt(n){return Si.prvD(n),!1}function rt(n){var r=Ci(n.target);yt(function(n,t){r.is(t)&&Xe({k:!0})})}function $e(n){n||$e(!0),Yn(Kt,B.split(xe)[0],nt,!Gr||n,!0),Yn(Kt,[X,Y],[Qn,Zn],!Jr||n,!0),Rt||n||Kt.one("mouseover",Qn)}function qe(){var n={};return Wt&&tr&&(n.w=ii(tr.css(ve+he)),n.h=ii(tr.css(ve+pe)),n.c=ui(n,$r),n.f=!0),!!($r=n).c}function et(n,t){var r,e,i=typeof t==mi?t.split(xe):[],o=function u(n,t){var r,e,i=[],o=[];for(r=0;r<n.length;r++)i[n[r]]=!0;for(r=0;r<t.length;r++)i[t[r]]?delete i[t[r]]:i[t[r]]=!0;for(e in i)o.push(e);return o}(typeof n==mi?n.split(xe):[],i),a=sn(Ie,o);if(-1<a&&o.splice(a,1),0<o[xi.l])for(e=lt(!0,!0),r=0;r<o.length;r++)if(!o[r].match(e))return!0;return!1}function it(n){d(n=n||Fn,function(n,t){if(-1<Si.inA(t,Fn)){var r=Yt.attr(t);cn(r)==mi?Zt.attr(t,r):Zt.removeAttr(t)}})}function Be(){if(!$t){var n,t,r,e,i=!jr,o=ee.w,a=ee.h,u={},f=br||i;return u[ve+he]=ye,u[ve+pe]=ye,u[he]=me,Yt.css(u),n=or[xi.oW],t=f?Oi.max(n,or[xi.sW]-1):1,u[he]=br?me:we,u[ve+he]=we,u[pe]=me,Yt.css(u),r=or[xi.oH],e=Oi.max(r,or[xi.sH]-1),u[he]=t,u[pe]=e,er.css(u),u[ve+he]=o,u[ve+pe]=a,Yt.css(u),{q:n,B:r,X:t,Y:e}}}function Xe(n){clearTimeout(Xt),n=n||{},je.A|=n.A,je.k|=n.k,je.H|=n.H;var t,r=Si.now(),e=!!je.A,i=!!je.k,o=!!je.H,a=n.C,u=0<Fe&&Rt&&!Lt&&!o&&!a&&r-Bt<Fe&&!yr&&!br;if(u&&(Xt=setTimeout(Xe,Fe)),!(Lt||u||$t&&!a||Rt&&!o&&(t=Kt.is(":hidden"))||"inline"===Kt.css("display"))){Bt=r,je={},!Ct||zt.x&&zt.y?Ht=fi({},xt.nativeScrollbarSize):(Ht.x=0,Ht.y=0),ie={x:3*(Ht.x+(zt.x?0:3)),y:3*(Ht.y+(zt.y?0:3))},a=a||{};var f=function(){return ui.apply(this,[].slice.call(arguments).concat([o]))},c={x:Zt[_e](),y:Zt[Se]()},s=qt.scrollbars,l=qt.textarea,v=s.visibility,d=f(v,Rr),h=s.autoHide,p=f(h,Lr),b=s.clickScrolling,y=f(b,Nr),m=s.dragScrolling,g=f(m,Wr),w=qt.className,x=f(w,Er),_=qt.resize,S=f(_,Dr)&&!Wt,z=qt.paddingAbsolute,T=f(z,Sr),O=qt.clipAlways,k=f(O,zr),C=qt.sizeAutoCapable&&!Wt,A=f(C,Hr),H=qt.nativeScrollbarsOverlaid.showNativeScrollbars,R=f(H,Cr),L=qt.autoUpdate,N=f(L,Ar),W=qt.overflowBehavior,D=f(W,Or,o),M=l.dynWidth,E=f(Vr,M),I=l.dynHeight,j=f(Ur,I);if(Yr="n"===h,Kr="s"===h,Gr="m"===h,Jr="l"===h,Xr=s.autoHideDelay,Ir=Er,Qr="n"===_,Zr="b"===_,ne="h"===_,te="v"===_,Mr=qt.normalizeRTL,H=H&&zt.x&&zt.y,Rr=v,Lr=h,Nr=b,Wr=m,Er=w,Dr=_,Sr=z,zr=O,Hr=C,Cr=H,Ar=L,Or=fi({},W),Vr=M,Ur=I,hr=hr||{x:!1,y:!1},x&&(si(Kt,Ir+xe+Ie),ci(Kt,w!==hi&&null!==w&&0<w.length?w:Ie)),N&&(!0===L||null===L&&kt?(Ve(),_t.add(St)):(_t.remove(St),Ue())),A)if(C)if(rr?rr.show():(rr=Ci(ai(Le)),Qt.before(rr)),Mt)Gt.show();else{Gt=Ci(ai(Ne)),ur=Gt[0],rr.before(Gt);var F={w:-1,h:-1};Pe(Gt,function(){var n={w:ur[xi.oW],h:ur[xi.oH]};ui(n,F)&&(Rt&&yr&&0<n.h||br&&0<n.w||Rt&&!yr&&0===n.h||!br&&0===n.w)&&Xe(),F=n}),Mt=!0,null!==At&&Gt.css(pe,At+"(100% + 1px)")}else Mt&&Gt.hide(),rr&&rr.hide();o&&(Jt.find("*").trigger(ge),Mt&&Gt.find("*").trigger(ge)),t=t===hi?Kt.is(":hidden"):t;var P,U=!!Nt&&"off"!==Yt.attr("wrap"),V=f(U,jr),$=Kt.css("direction"),q=f($,_r),B=Kt.css("box-sizing"),X=f(B,mr),Y=ei(ae);try{P=Mt?ur[xi.bCR]():null}catch(gt){return}Dt="border-box"===B;var K=(Vt="rtl"===$)?le:ce,G=Vt?ce:le,J=!1,Q=!(!Mt||"none"===Kt.css(be))&&(0===Oi.round(P.right-P.left)&&(!!z||0<ar[xi.cW]-Et));if(C&&!Q){var Z=ar[xi.oW],nn=rr.css(he);rr.css(he,me);var tn=ar[xi.oW];rr.css(he,nn),(J=Z!==tn)||(rr.css(he,Z+1),tn=ar[xi.oW],rr.css(he,nn),J=Z!==tn)}var rn=(Q||J)&&C&&!t,en=f(rn,br),on=!rn&&br,an=!(!Mt||!C||t)&&0===Oi.round(P.bottom-P.top),un=f(an,yr),fn=!an&&yr,cn=ei(ue,"-"+he,!(rn&&Dt||!Dt),!(an&&Dt||!Dt)),sn=ei(oe),ln={},vn={},dn=function(){return{w:ar[xi.cW],h:ar[xi.cH]}},hn=function(){return{w:fr[xi.oW]+Oi.max(0,sr[xi.cW]-sr[xi.sW]),h:fr[xi.oH]+Oi.max(0,sr[xi.cH]-sr[xi.sH])}},pn=Et=Y.l+Y.r,bn=It=Y.t+Y.b;if(pn*=z?1:0,bn*=z?1:0,Y.c=f(Y,gr),jt=cn.l+cn.r,Ft=cn.t+cn.b,cn.c=f(cn,wr),Pt=sn.l+sn.r,Ut=sn.t+sn.b,sn.c=f(sn,xr),jr=U,_r=$,mr=B,br=rn,yr=an,gr=Y,wr=cn,xr=sn,q&&Mt&&Gt.css(be,G),Y.c||q||T||en||un||X||A){var yn={},mn={},gn=[Y.t,Y.r,Y.b,Y.l];ri(vn,oe,[-Y.t,-Y.r,-Y.b,-Y.l]),z?(ri(yn,ye,gn),ri(Nt?mn:ln,ae)):(ri(yn,ye),ri(Nt?mn:ln,ae,gn)),Qt.css(yn),Yt.css(mn)}ee=hn();var wn=!!Nt&&Be(),xn=Nt&&f(wn,Pr),_n=Nt&&wn?{w:M?wn.X:wn.q,h:I?wn.Y:wn.B}:{};if(Pr=wn,an&&(un||T||X||Y.c||cn.c)?ln[pe]=me:(un||T)&&(ln[pe]=we),rn&&(en||T||X||Y.c||cn.c||q)?(ln[he]=me,vn[de+he]=we):(en||T)&&(ln[he]=we,ln[be]=ye,vn[de+he]=ye),rn?(vn[he]=me,ln[he]=_i.v(he,"max-content intrinsic")||me,ln[be]=G):vn[he]=ye,vn[pe]=an?_n.h||sr[xi.cH]:ye,C&&rr.css(vn),nr.css(ln),ln={},vn={},e||i||xn||q||X||T||en||rn||un||an||R||D||k||S||d||p||g||y||E||j||V){var Sn="overflow",zn=Sn+"-x",Tn=Sn+"-y";if(!Ct){var On={},kn=hr.y&&pr.ys&&!H?zt.y?Zt.css(K):-Ht.y:0,Cn=hr.x&&pr.xs&&!H?zt.x?Zt.css(se):-Ht.x:0;ri(On,ye),Zt.css(On)}var An=oi(),Hn={w:_n.w||An[xi.cW],h:_n.h||An[xi.cH]},Rn=An[xi.sW],Ln=An[xi.sH];Ct||(On[se]=fn?ye:Cn,On[K]=on?ye:kn,Zt.css(On)),ee=hn();var Nn=dn(),Wn={w:Nn.w-Pt-jt-(Dt?0:Et),h:Nn.h-Ut-Ft-(Dt?0:It)},Dn={w:Oi.max((rn?Hn.w:Rn)+pn,Wn.w),h:Oi.max((an?Hn.h:Ln)+bn,Wn.h)};if(Dn.c=f(Dn,Tr),Tr=Dn,C){(Dn.c||an||rn)&&(vn[he]=Dn.w,vn[pe]=Dn.h,Nt||(Hn={w:An[xi.cW],h:An[xi.cH]}));var Mn={},En=function(n){var t=ni(n),r=t.F,e=t.K,i=n?rn:an,o=n?jt:Ft,a=n?Et:It,u=n?Pt:Ut,f=ee[r]-o-u-(Dt?0:a);i&&(i||!cn.c)||(vn[e]=Wn[r]-1),!(i&&Hn[r]<f)||n&&Nt&&U||(Nt&&(Mn[e]=ii(er.css(e))-1),--vn[e]),0<Hn[r]&&(vn[e]=Oi.max(1,vn[e]))};En(!0),En(!1),Nt&&er.css(Mn),rr.css(vn)}rn&&(ln[he]=we),!rn||Dt||qr||(ln[be]="none"),nr.css(ln),ln={};var In={w:An[xi.sW],h:An[xi.sH]};In.c=i=f(In,vr),vr=In,ee=hn(),e=f(Nn=dn(),lr),lr=Nn;var jn=Nt&&(0===ee.w||0===ee.h),Fn=kr,Pn={},Un={},Vn={},$n={},qn={},Bn={},Xn={},Yn=fr[xi.bCR](),Kn=function(n){var t=ni(n),r=ni(!n).U,e=t.U,i=t.F,o=t.K,a=ge+t.G+"Max",u=Yn[o]?Oi.abs(Yn[o]-ee[i]):0,f=Fn&&0<Fn[e]&&0===cr[a];Pn[e]="v-s"===W[e],Un[e]="v-h"===W[e],Vn[e]="s"===W[e],$n[e]=Oi.max(0,Oi.round(100*(In[i]-ee[i]))/100),$n[e]*=jn||f&&0<u&&u<1?0:1,qn[e]=0<$n[e],Bn[e]=Pn[e]||Un[e]?qn[r]&&!Pn[r]&&!Un[r]:qn[e],Bn[e+"s"]=!!Bn[e]&&(Vn[e]||Pn[e]),Xn[e]=qn[e]&&Bn[e+"s"]};if(Kn(!0),Kn(!1),$n.c=f($n,kr),kr=$n,qn.c=f(qn,hr),hr=qn,Bn.c=f(Bn,pr),pr=Bn,zt.x||zt.y){var Gn,Jn={},Qn={},Zn=o;(qn.x||qn.y)&&(Qn.w=zt.y&&qn.y?In.w+Tt.y:ye,Qn.h=zt.x&&qn.x?In.h+Tt.x:ye,Zn=f(Qn,dr),dr=Qn),(qn.c||Bn.c||In.c||q||en||un||rn||an||R)&&(ln[oe+G]=ln[ue+G]=ye,Gn=function(n){var t=ni(n),r=ni(!n),e=t.U,i=n?se:K,o=n?an:rn;zt[e]&&qn[e]&&Bn[e+"s"]?(ln[oe+i]=!o||H?ye:Tt[e],ln[ue+i]=n&&o||H?ye:Tt[e]+"px solid transparent"):(Qn[r.F]=ln[oe+i]=ln[ue+i]=ye,Zn=!0)},Ct?li(Zt,He,!H):(Gn(!0),Gn(!1))),H&&(Qn.w=Qn.h=ye,Zn=!0),Zn&&!Ct&&(Jn[he]=Bn.y?Qn.w:ye,Jn[pe]=Bn.x?Qn.h:ye,tr||(tr=Ci(ai(Re)),Zt.prepend(tr)),tr.css(Jn)),nr.css(ln)}var nt,tt={};yn={};if((e||qn.c||Bn.c||In.c||D||X||R||q||k||un)&&(tt[G]=ye,(nt=function(n){var t=ni(n),r=ni(!n),e=t.U,i=t.J,o=n?se:K,a=function(){tt[o]=ye,re[r.F]=0};qn[e]&&Bn[e+"s"]?(tt[Sn+i]=ge,H||Ct?a():(tt[o]=-(zt[e]?Tt[e]:Ht[e]),re[r.F]=zt[e]?Tt[r.U]:0)):(tt[Sn+i]=ye,a())})(!0),nt(!1),!Ct&&(ee.h<ie.x||ee.w<ie.y)&&(qn.x&&Bn.x&&!zt.x||qn.y&&Bn.y&&!zt.y)?(tt[ae+fe]=ie.x,tt[oe+fe]=-ie.x,tt[ae+G]=ie.y,tt[oe+G]=-ie.y):tt[ae+fe]=tt[oe+fe]=tt[ae+G]=tt[oe+G]=ye,tt[ae+K]=tt[oe+K]=ye,qn.x&&Bn.x||qn.y&&Bn.y||jn?Nt&&jn&&(yn[zn]=yn[Tn]="hidden"):(!O||Un.x||Pn.x||Un.y||Pn.y)&&(Nt&&(yn[zn]=yn[Tn]=ye),tt[zn]=tt[Tn]="visible"),Qt.css(yn),Zt.css(tt),tt={},(qn.c||X||en||un)&&(!zt.x||!zt.y))){var rt=sr[xi.s];rt.webkitTransform="scale(1)",rt.display="run-in",sr[xi.oH],rt.display=ye,rt.webkitTransform=ye}if(ln={},q||en||un)if(Vt&&rn){var et=nr.css(be),it=Oi.round(nr.css(be,ye).css(le,ye).position().left);nr.css(be,et),it!==Oi.round(nr.position().left)&&(ln[le]=it)}else ln[le]=ye;if(nr.css(ln),Nt&&i){var ot=function wt(){var n=or.selectionStart;if(n===hi)return;var t,r,e=Yt.val(),i=e[xi.l],o=e.split("\n"),a=o[xi.l],u=e.substr(0,n).split("\n"),f=0,c=0,s=u[xi.l],l=u[u[xi.l]-1][xi.l];for(r=0;r<o[xi.l];r++)t=o[r][xi.l],c<t&&(f=r+1,c=t);return{Q:s,Z:l,nn:a,tn:c,rn:f,en:n,"in":i}}();if(ot){var at=Fr===hi||ot.nn!==Fr.nn,ut=ot.Q,ft=ot.Z,ct=ot.rn,st=ot.nn,lt=ot.tn,vt=ot.en,dt=ot["in"]<=vt&&Br,ht={x:U||ft!==lt||ut!==ct?-1:kr.x,y:(U?dt||at&&Fn&&c.y===Fn.y:(dt||at)&&ut===st)?kr.y:-1};c.x=-1<ht.x?Vt&&Mr&&Ot.i?0:ht.x:c.x,c.y=-1<ht.y?ht.y:c.y}Fr=ot}Vt&&Ot.i&&zt.y&&qn.x&&Mr&&(c.x+=re.w||0),rn&&Kt[_e](0),an&&Kt[Se](0),Zt[_e](c.x)[Se](c.y);var pt="v"===v,bt="h"===v,yt="a"===v,mt=function(n,t){t=t===hi?n:t,Ke(!0,n,Xn.x),Ke(!1,t,Xn.y)};li(Kt,ke,Bn.x||Bn.y),li(Kt,Ce,Bn.x),li(Kt,Ae,Bn.y),q&&!Wt&&li(Kt,ze,Vt),Wt&&ci(Kt,Te),S&&(li(Kt,Te,Qr),li(ir,We,!Qr),li(ir,De,Zr),li(ir,Me,ne),li(ir,Ee,te)),(d||D||Bn.c||qn.c||R)&&(H?R&&(si(Kt,Oe),H&&mt(!1)):yt?mt(Xn.x,Xn.y):pt?mt(!0):bt&&mt(!1)),(p||R)&&($e(!Jr&&!Gr),Ge(Yr,!Yr)),(e||$n.c||un||en||S||X||T||R||q)&&(Je(!0),Qe(!0),Je(!1),Qe(!1)),y&&Ze(!0,b),g&&Ze(!1,m),ti("onDirectionChanged",{isRTL:Vt,dir:$},q),ti("onHostSizeChanged",{width:lr.w,height:lr.h},e),ti("onContentSizeChanged",{width:vr.w,height:vr.h},i),ti("onOverflowChanged",{x:qn.x,y:qn.y,xScrollable:Bn.xs,yScrollable:Bn.ys,clipped:Bn.x||Bn.y},qn.c||Bn.c),ti("onOverflowAmountChanged",{x:$n.x,y:$n.y},$n.c)}Wt&&$r&&(hr.c||$r.c)&&($r.f||qe(),zt.y&&hr.x&&nr.css(ve+he,$r.w+Tt.y),zt.x&&hr.y&&nr.css(ve+pe,$r.h+Tt.x),$r.c=!1),Rt&&a.updateOnLoad&&Ye(),ti("onUpdated",{forced:o})}}function Ye(){Nt||yt(function(n,t){nr.find(t).each(function(n,t){Si.inA(t,Vn)<0&&(Vn.push(t),Ci(t).off(Un,rt).on(Un,rt))})})}function ot(n){var t=Ti._(n,Ti.g,!0,a);return a=fi({},a,t.S),qt=fi({},qt,t.z),t.z}function at(e){var n="parent",t=yn+xe+On,r=Nt?xe+On:ye,i=qt.textarea.inheritedAttrs,o={},a=function(){var r=e?Yt:Kt;d(o,function(n,t){cn(t)==mi&&(n==xi.c?r.addClass(t):r.attr(n,t))})},u=[rn,en,on,Te,ze,an,un,fn,Oe,ke,Ce,Ae,Ie,yn,On,Er].join(xe),f={};Kt=Kt||(Nt?p?Yt[n]()[n]()[n]()[n]():Ci(ai(on)):Yt),nr=nr||pt(_n+r),Zt=Zt||pt(wn+r),Qt=Qt||pt(gn+r),Jt=Jt||pt("os-resize-observer-host"),er=er||(Nt?pt(mn):hi),p&&ci(Kt,en),e&&si(Kt,u),i=cn(i)==mi?i.split(xe):i,Si.isA(i)&&Nt&&d(i,function(n,t){cn(t)==mi&&(o[t]=e?Kt.attr(t):Yt.attr(t))}),e?(p&&Rt?(Jt.children().remove(),d([Qt,Zt,nr,er],function(n,t){t&&si(t.removeAttr(xi.s),In)}),ci(Kt,Nt?on:rn)):(mt(Jt),nr.contents().unwrap().unwrap().unwrap(),Nt&&(Yt.unwrap(),mt(Kt),mt(er),a())),Nt&&Yt.removeAttr(xi.s),Wt&&si(c,tn)):(Nt&&(qt.sizeAutoCapable||(f[he]=Yt.css(he),f[pe]=Yt.css(pe)),p||Yt.addClass(On).wrap(Kt),Kt=Yt[n]().css(f)),p||(ci(Yt,Nt?t:rn),Kt.wrapInner(nr).wrapInner(Zt).wrapInner(Qt).prepend(Jt),nr=gt(Kt,W+_n),Zt=gt(Kt,W+wn),Qt=gt(Kt,W+gn),Nt&&(nr.prepend(er),a())),Ct&&ci(Zt,He),zt.x&&zt.y&&ci(Zt,xn),Wt&&ci(c,tn),R=Jt[0],ar=Kt[0],fr=Qt[0],cr=Zt[0],sr=nr[0],it())}function ut(){var r,t,e=[112,113,114,115,116,117,118,119,120,121,123,33,34,37,38,39,40,16,17,18,19,20,144],i=[],n="focus";function o(n){Be(),St.update(me),n&&kt&&clearInterval(r)}Nt?(9<I||!kt?Kn(Yt,"input",o):Kn(Yt,[K,G],[function a(n){var t=n.keyCode;sn(t,e)<0&&(i[xi.l]||(o(),r=setInterval(o,1e3/60)),sn(t,i)<0&&i.push(t))},function u(n){var t=n.keyCode,r=sn(t,i);sn(t,e)<0&&(-1<r&&i.splice(r,1),i[xi.l]||o(!0))}]),Kn(Yt,[ge,"drop",n,n+"out"],[function f(n){return Yt[_e](Ot.i&&Mr?9999999:0),Yt[Se](0),Si.prvD(n),Si.stpP(n),!1},function c(n){setTimeout(function(){Lt||o()},50)},function s(){Br=!0,ci(Kt,n)},function l(){Br=!1,i=[],si(Kt,n),o(!0)}])):Kn(nr,Q,function v(n){!0!==Ar&&function l(n){if(!Rt)return 1;var t="flex-grow",r="flex-shrink",e="flex-basis",i=[he,ve+he,de+he,oe+le,oe+ce,le,ce,"font-weight","word-spacing",t,r,e],o=[ae+le,ae+ce,ue+le+he,ue+ce+he],a=[pe,ve+pe,de+pe,oe+fe,oe+se,fe,se,"line-height",t,r,e],u=[ae+fe,ae+se,ue+fe+he,ue+se+he],f="s"===Or.x||"v-s"===Or.x,c=!1,s=function(n,t){for(var r=0;r<n[xi.l];r++)if(n[r]===t)return!0;return!1};return("s"===Or.y||"v-s"===Or.y)&&((c=s(a,n))||Dt||(c=s(u,n))),f&&!c&&((c=s(i,n))||Dt||(c=s(o,n))),c}((n=n.originalEvent||n).propertyName)&&St.update(me)}),Kn(Zt,ge,function d(n){$t||(t!==hi?clearTimeout(t):((Kr||Gr)&&Ge(!0),ht()||ci(Kt,Oe),ti("onScrollStart",n)),V||(Qe(!0),Qe(!1)),ti("onScroll",n),t=setTimeout(function(){Lt||(clearTimeout(t),t=hi,(Kr||Gr)&&Ge(!1),ht()||si(Kt,Oe),ti("onScrollStop",n))},175))},!0)}function ft(i){var n,t,o=function(n){var t=pt(kn+xe+(n?Dn:Mn),!0),r=pt(Cn,t),e=pt(Hn,t);return p||i||(t.append(r),r.append(e)),{an:t,un:r,cn:e}};function r(n){var t=ni(n),r=t.an,e=t.un,i=t.cn;p&&Rt?d([r,e,i],function(n,t){si(t.removeAttr(xi.s),In)}):mt(r||o(n).an)}i?(r(!0),r()):(n=o(!0),t=o(),f=n.an,s=n.un,l=n.cn,v=t.an,b=t.un,y=t.cn,p||(Qt.after(v),Qt.after(f)))}function ct(z){var T,i,O,k,e=ni(z),C=e.sn,t=x.top!==x,A=e.U,r=e.J,H=ge+e.G,o="active",a="snapHandle",u="click",R=1,f=[16,17];function c(n){return I&&t?n["screen"+r]:Si.page(n)[A]}function s(n){return qt.scrollbars[n]}function l(){R=.5}function v(){R=1}function d(n){Si.stpP(n)}function L(n){-1<sn(n.keyCode,f)&&l()}function N(n){-1<sn(n.keyCode,f)&&v()}function W(n){var t=(n.originalEvent||n).touches!==hi;return!($t||Lt||ht()||!Wr||t&&!s("touchSupport"))&&(1===Si.mBtn(n)||t)}function h(n){if(W(n)){var t=C.I,r=C.D,e=C.N*((c(n)-O)*k/(t-r));e=isFinite(e)?e:0,Vt&&z&&!Ot.i&&(e*=-1),Zt[H](Oi.round(i+e)),V&&Qe(z,i+e),g||Si.prvD(n)}else D(n)}function D(n){if(n=n||n.originalEvent,Yn(F,[B,q,K,G,J],[h,D,L,N,tt],!0),Si.rAF()(function(){Yn(F,u,d,!0,{$:!0})}),V&&Qe(z,!0),V=!1,si(P,En),si(e.cn,o),si(e.un,o),si(e.an,o),k=1,v(),T!==(O=i=hi)&&(St.scrollStop(),clearTimeout(T),T=hi),n){var t=ar[xi.bCR]();n.clientX>=t.left&&n.clientX<=t.right&&n.clientY>=t.top&&n.clientY<=t.bottom||Zn(),(Kr||Gr)&&Ge(!1)}}function M(n){i=Zt[H](),i=isNaN(i)?0:i,(Vt&&z&&!Ot.n||!Vt)&&(i=i<0?0:i),k=vt()[A],O=c(n),V=!s(a),ci(P,En),ci(e.cn,o),ci(e.an,o),Yn(F,[B,q,J],[h,D,tt]),Si.rAF()(function(){Yn(F,u,d,!1,{$:!0})}),!I&&w||Si.prvD(n),Si.stpP(n)}Kn(e.cn,$,function p(n){W(n)&&M(n)}),Kn(e.un,[$,X,Y],[function E(n){if(W(n)){var d,t=e.sn.D/Math.round(Oi.min(1,ee[e.F]/vr[e.F])*e.sn.I),h=Oi.round(ee[e.F]*t),p=270*t,b=400*t,y=e.un.offset()[e.P],r=n.ctrlKey,m=n.shiftKey,g=m&&r,w=!0,x=function(n){V&&Qe(z,n)},_=function(){x(),M(n)},S=function(){if(!Lt){var n=(O-y)*k,t=C.W,r=C.I,e=C.D,i=C.N,o=C.R,a=p*R,u=w?Oi.max(b,a):a,f=i*((n-e/2)/(r-e)),c=Vt&&z&&(!Ot.i&&!Ot.n||Mr),s=c?t<n:n<t,l={},v={easing:"linear",step:function(n){V&&(Zt[H](n),Qe(z,n))}};f=isFinite(f)?f:0,f=Vt&&z&&!Ot.i?i-f:f,m?(Zt[H](f),g?(f=Zt[H](),Zt[H](o),f=c&&Ot.i?i-f:f,f=c&&Ot.n?-f:f,l[A]=f,St.scroll(l,fi(v,{duration:130,complete:_}))):_()):(d=w?s:d,(c?d?n<=t+e:t<=n:d?t<=n:n<=t+e)?(clearTimeout(T),St.scrollStop(),T=hi,x(!0)):(T=setTimeout(S,u),l[A]=(d?"-=":"+=")+h,St.scroll(l,fi(v,{duration:a}))),w=!1)}};r&&l(),k=vt()[A],O=Si.page(n)[A],V=!s(a),ci(P,En),ci(e.un,o),ci(e.an,o),Yn(F,[q,K,G,J],[D,L,N,tt]),S(),Si.prvD(n),Si.stpP(n)}},function b(n){U=!0,(Kr||Gr)&&Ge(!0)},function y(n){U=!1,(Kr||Gr)&&Ge(!1)}]),Kn(e.an,$,function m(n){Si.stpP(n)}),j&&Kn(e.an,Q,function(n){n.target===e.an[0]&&(Je(z),Qe(z))})}function Ke(n,t,r){var e=n?f:v;li(Kt,n?an:un,!t),li(e,Ln,!r)}function Ge(n,t){if(clearTimeout(k),n)si(f,Nn),si(v,Nn);else{var r,e=function(){U||Lt||(!(r=l.hasClass("active")||y.hasClass("active"))&&(Kr||Gr||Jr)&&ci(f,Nn),!r&&(Kr||Gr||Jr)&&ci(v,Nn))};0<Xr&&!0!==t?k=setTimeout(e,Xr):e()}}function Je(n){var t={},r=ni(n),e=r.sn,i=Oi.min(1,ee[r.F]/vr[r.F]);t[r.K]=Oi.floor(100*i*1e6)/1e6+"%",ht()||r.cn.css(t),e.D=r.cn[0]["offset"+r.ln],e.M=i}function Qe(n,t){var r,e,i=cn(t)==gi,o=Vt&&n,a=ni(n),u=a.sn,f="translate(",c=_i.u("transform"),s=_i.u("transition"),l=n?Zt[_e]():Zt[Se](),v=t===hi||i?l:t,d=u.D,h=a.un[0]["offset"+a.ln],p=h-d,b={},y=(cr[ge+a.ln]-cr["client"+a.ln])*(Ot.n&&o?-1:1),m=function(n){return isNaN(n/y)?0:Oi.max(0,Oi.min(1,n/y))},g=function(n){var t=p*n;return t=isNaN(t)?0:t,t=o&&!Ot.i?h-d-t:t,t=Oi.max(0,t)},w=m(l),x=g(m(v)),_=g(w);u.N=y,u.R=l,u.L=w,ln?(r=o?-(h-d-x):x,e=n?f+r+"px, 0)":f+"0, "+r+"px)",b[c]=e,j&&(b[s]=i&&1<Oi.abs(x-u.W)?function S(n){var t=_i.u("transition"),r=n.css(t);if(r)return r;for(var e,i,o,a="\\s*(([^,(]+(\\(.+?\\))?)+)[\\s,]*",u=new RegExp(a),f=new RegExp("^("+a+")+$"),c="property duration timing-function delay".split(" "),s=[],l=0,v=function(n){if(e=[],!n.match(f))return n;for(;n.match(u);)e.push(RegExp.$1),n=n.replace(u,ye);return e};l<c[xi.l];l++)for(i=v(n.css(t+"-"+c[l])),o=0;o<i[xi.l];o++)s[o]=(s[o]?s[o]+xe:ye)+i[o];return s.join(", ")}(a.cn)+", "+(c+xe+250)+"ms":ye)):b[a.P]=x,ht()||(a.cn.css(b),ln&&j&&i&&a.cn.one(Q,function(){Lt||a.cn.css(s,ye)})),u.W=x,u.j=_,u.I=h}function Ze(n,t){var r=t?"removeClass":"addClass",e=n?b:y,i=n?An:Rn;(n?s:l)[r](i),e[r](i)}function ni(n){return{K:n?he:pe,ln:n?"Width":"Height",P:n?le:fe,G:n?"Left":"Top",U:n?pn:bn,J:n?"X":"Y",F:n?"w":"h",vn:n?"l":"t",un:n?s:b,cn:n?l:y,an:n?f:v,sn:n?vn:dn}}function st(n){ir=ir||pt(Wn,!0),n?p&&Rt?si(ir.removeAttr(xi.s),In):mt(ir):p||Kt.append(ir)}function ti(n,t,r){if(!1!==r)if(Rt){var e,i=qt.callbacks[n],o=n;"on"===o.substr(0,2)&&(o=o.substr(2,1).toLowerCase()+o.substr(3)),cn(i)==bi&&i.call(St,t),d(Pn,function(){cn((e=this).on)==bi&&e.on(o,t)})}else Lt||jn.push({n:n,a:t})}function ri(n,t,r){r=r||[ye,ye,ye,ye],n[(t=t||ye)+fe]=r[0],n[t+ce]=r[1],n[t+se]=r[2],n[t+le]=r[3]}function ei(n,t,r,e){return t=t||ye,n=n||ye,{t:e?0:ii(Kt.css(n+fe+t)),r:r?0:ii(Kt.css(n+ce+t)),b:e?0:ii(Kt.css(n+se+t)),l:r?0:ii(Kt.css(n+le+t))}}function lt(n,t){var r,e,i,o=function(n,t){if(i="",t&&typeof n==mi)for(e=n.split(xe),r=0;r<e[xi.l];r++)i+="|"+e[r]+"$";return i};return new RegExp("(^"+rn+"([-_].+|)$)"+o(Er,n)+o(Ir,t),"g")}function vt(){var n=fr[xi.bCR]();return{x:ln&&1/(Oi.round(n.width)/fr[xi.oW])||1,y:ln&&1/(Oi.round(n.height)/fr[xi.oH])||1}}function dt(n){var t="ownerDocument",r="HTMLElement",e=n&&n[t]&&n[t].parentWindow||vi;return typeof e[r]==pi?n instanceof e[r]:n&&typeof n==pi&&null!==n&&1===n.nodeType&&typeof n.nodeName==mi}function ii(n,t){var r=t?parseFloat(n):parseInt(n,10);return isNaN(r)?0:r}function ht(){return Cr&&zt.x&&zt.y}function oi(){return Nt?er[0]:sr}function ai(r,n){return"<div "+(r?cn(r)==mi?'class="'+r+'"':function(){var n,t=ye;if(Ci.isPlainObject(r))for(n in r)t+=("c"===n?"class":n)+'="'+r[n]+'" ';return t}():ye)+">"+(n||ye)+"</div>"}function pt(n,t){var r=cn(t)==gi,e=!r&&t||Kt;return p&&!e[xi.l]?null:p?e[r?"children":"find"](W+n.replace(/\s/g,W)).eq(0):Ci(ai(n))}function bt(n,t){for(var r,e=t.split(W),i=0;i<e.length;i++){if(!n[xi.hOP](e[i]))return;r=n[e[i]],i<e.length&&cn(r)==pi&&(n=r)}return r}function yt(n){var t=qt.updateOnLoad;t=cn(t)==mi?t.split(xe):t,Si.isA(t)&&!Lt&&d(t,n)}function ui(n,t,r){if(r)return r;if(cn(n)!=pi||cn(t)!=pi)return n!==t;for(var e in n)if("c"!==e){if(!n[xi.hOP](e)||!t[xi.hOP](e))return!0;if(ui(n[e],t[e]))return!0}return!1}function fi(){return Ci.extend.apply(this,[!0].concat([].slice.call(arguments)))}function ci(n,t){return e.addClass.call(n,t)}function si(n,t){return e.removeClass.call(n,t)}function li(n,t,r){return(r?ci:si)(n,t)}function mt(n){return e.remove.call(n)}function gt(n,t){return e.find.call(n,t).eq(0)}}return ki&&ki.fn&&(ki.fn.overlayScrollbars=function(n,t){return ki.isPlainObject(n)?(ki.each(this,function(){w(this,n,t)}),this):w(this,n)}),w}); \ No newline at end of file