lampa-main в git: клиент переживает пересоздание контейнера

- каталог lampa-main/ (yumata/lampa) смонтирован bind-mountом в /lampac/wwwroot/lampa-main (override)
- в образе 1.72.0 клиента нет, LampaCron из GitHub не докачивает (нет доступа к GitHub) -> / отдавал 500
- README/AGENT: механика обновления клиента через git
- compose: 1.72.0, cache/database как bind-mountы, секреты в init.conf
This commit is contained in:
2026-10-06 17:35:35 +03:00
parent 22053424f5
commit d03a0282f1
175 changed files with 109796 additions and 16 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10253
View File
File diff suppressed because it is too large Load Diff
+884
View File
@@ -0,0 +1,884 @@
/*!
*
* simple-keyboard v2.32.123
* https://github.com/hodgef/simple-keyboard
*
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
! function(t, e) {
"object" === typeof exports && "object" === typeof module ? module.exports = e() : "function" === typeof define && define.amd ? define("SimpleKeyboard", [], e) : "object" === typeof exports ? exports.SimpleKeyboard = e() : t.SimpleKeyboard = e()
}(this, (function() {
return function(t) {
var e = {};
function __webpack_require__(n) {
if (e[n]) return e[n].exports;
var o = e[n] = {
i: n,
l: !1,
exports: {}
};
return t[n].call(o.exports, o, o.exports, __webpack_require__), o.l = !0, o.exports
}
return __webpack_require__.m = t, __webpack_require__.c = e, __webpack_require__.d = function(t, e, n) {
__webpack_require__.o(t, e) || Object.defineProperty(t, e, {
enumerable: !0,
get: n
})
}, __webpack_require__.r = function(t) {
"undefined" !== typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {
value: "Module"
}), Object.defineProperty(t, "__esModule", {
value: !0
})
}, __webpack_require__.t = function(t, e) {
if (1 & e && (t = __webpack_require__(t)), 8 & e) return t;
if (4 & e && "object" === typeof t && t && t.__esModule) return t;
var n = Object.create(null);
if (__webpack_require__.r(n), Object.defineProperty(n, "default", {
enumerable: !0,
value: t
}), 2 & e && "string" != typeof t)
for (var o in t) __webpack_require__.d(n, o, function(e) {
return t[e]
}.bind(null, o));
return n
}, __webpack_require__.n = function(t) {
var e = t && t.__esModule ? function() {
return t.default
} : function() {
return t
};
return __webpack_require__.d(e, "a", e), e
}, __webpack_require__.o = function(t, e) {
return Object.prototype.hasOwnProperty.call(t, e)
}, __webpack_require__.p = "/", __webpack_require__(__webpack_require__.s = 0)
}([function(t, e, n) {
t.exports = n(1)
}, function(t, e, n) {
"use strict";
n.r(e);
function _createForOfIteratorHelper(t, e) {
var n;
if ("undefined" === typeof Symbol || null == t[Symbol.iterator]) {
if (Array.isArray(t) || (n = function(t, e) {
if (!t) return;
if ("string" === typeof t) return _arrayLikeToArray(t, e);
var n = Object.prototype.toString.call(t).slice(8, -1);
"Object" === n && t.constructor && (n = t.constructor.name);
if ("Map" === n || "Set" === n) return Array.from(t);
if ("Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(t, e)
}(t)) || e && t && "number" === typeof t.length) {
n && (t = n);
var o = 0,
F = function() {};
return {
s: F,
n: function() {
return o >= t.length ? {
done: !0
} : {
done: !1,
value: t[o++]
}
},
e: function(t) {
throw t
},
f: F
}
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")
}
var i, s = !0,
a = !1;
return {
s: function() {
n = t[Symbol.iterator]()
},
n: function() {
var t = n.next();
return s = t.done, t
},
e: function(t) {
a = !0, i = t
},
f: function() {
try {
s || null == n.return || n.return()
} finally {
if (a) throw i
}
}
}
}
function _arrayLikeToArray(t, e) {
(null == e || e > t.length) && (e = t.length);
for (var n = 0, o = new Array(e); n < e; n++) o[n] = t[n];
return o
}
function _typeof(t) {
return (_typeof = "function" === typeof Symbol && "symbol" === typeof Symbol.iterator ? function(t) {
return typeof t
} : function(t) {
return t && "function" === typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t
})(t)
}
function _defineProperties(t, e) {
for (var n = 0; n < e.length; n++) {
var o = e[n];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(t, o.key, o)
}
}
var o, i, s, a = function() {
function Utilities(t) {
var e = t.getOptions,
n = t.getCaretPosition,
o = t.getCaretPositionEnd,
i = t.dispatch;
! function(t, e) {
if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
}(this, Utilities), this.getOptions = e, this.getCaretPosition = n, this.getCaretPositionEnd = o, this.dispatch = i, Utilities.bindMethods(Utilities, this)
}
var t, e, n;
return t = Utilities, n = [{
key: "bindMethods",
value: function(t, e) {
var n, o = _createForOfIteratorHelper(Object.getOwnPropertyNames(t.prototype));
try {
for (o.s(); !(n = o.n()).done;) {
var i = n.value;
"constructor" === i || "bindMethods" === i || (e[i] = e[i].bind(e))
}
} catch (s) {
o.e(s)
} finally {
o.f()
}
}
}], (e = [{
key: "getButtonClass",
value: function(t) {
var e = t.includes("{") && t.includes("}") && "{//}" !== t ? "functionBtn" : "standardBtn",
n = t.replace("{", "").replace("}", ""),
o = "";
return "standardBtn" !== e && (o = " hg-button-".concat(n)), "hg-".concat(e).concat(o)
}
}, {
key: "getDefaultDiplay",
value: function() {
return {
"{bksp}": "backspace",
"{backspace}": "backspace",
"{enter}": "< enter",
"{shift}": "shift",
"{shiftleft}": "shift",
"{shiftright}": "shift",
"{alt}": "alt",
"{s}": "shift",
"{tab}": "tab",
"{lock}": "caps",
"{capslock}": "caps",
"{accept}": "Submit",
"{space}": " ",
"{//}": " ",
"{esc}": "esc",
"{escape}": "esc",
"{f1}": "f1",
"{f2}": "f2",
"{f3}": "f3",
"{f4}": "f4",
"{f5}": "f5",
"{f6}": "f6",
"{f7}": "f7",
"{f8}": "f8",
"{f9}": "f9",
"{f10}": "f10",
"{f11}": "f11",
"{f12}": "f12",
"{numpaddivide}": "/",
"{numlock}": "lock",
"{arrowup}": "\u2191",
"{arrowleft}": "\u2190",
"{arrowdown}": "\u2193",
"{arrowright}": "\u2192",
"{prtscr}": "print",
"{scrolllock}": "scroll",
"{pause}": "pause",
"{insert}": "ins",
"{home}": "home",
"{pageup}": "up",
"{delete}": "del",
"{end}": "end",
"{pagedown}": "down",
"{numpadmultiply}": "*",
"{numpadsubtract}": "-",
"{numpadadd}": "+",
"{numpadenter}": "enter",
"{period}": ".",
"{numpaddecimal}": ".",
"{numpad0}": "0",
"{numpad1}": "1",
"{numpad2}": "2",
"{numpad3}": "3",
"{numpad4}": "4",
"{numpad5}": "5",
"{numpad6}": "6",
"{numpad7}": "7",
"{numpad8}": "8",
"{numpad9}": "9"
}
}
}, {
key: "getButtonDisplayName",
value: function(t, e, n) {
return (e = n ? Object.assign({}, this.getDefaultDiplay(), e) : e || this.getDefaultDiplay())[t] || t
}
}, {
key: "getUpdatedInput",
value: function(t, e, n) {
var o = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : n,
i = arguments.length > 4 && void 0 !== arguments[4] && arguments[4],
s = this.getOptions(),
a = [n, o, i],
r = e;
return ("{bksp}" === t || "{backspace}" === t) && r.length > 0 ? r = this.removeAt.apply(this, [r].concat(a)) : "{space}" === t ? r = this.addStringAt.apply(this, [r, " "].concat(a)) : "{tab}" !== t || "boolean" === typeof s.tabCharOnTab && !1 === s.tabCharOnTab ? "{enter}" !== t && "{numpadenter}" !== t || !s.newLineOnEnter ? t.includes("numpad") && Number.isInteger(Number(t[t.length - 2])) ? r = this.addStringAt.apply(this, [r, t[t.length - 2]].concat(a)) : "{numpaddivide}" === t ? r = this.addStringAt.apply(this, [r, "/"].concat(a)) : "{numpadmultiply}" === t ? r = this.addStringAt.apply(this, [r, "*"].concat(a)) : "{numpadsubtract}" === t ? r = this.addStringAt.apply(this, [r, "-"].concat(a)) : "{numpadadd}" === t ? r = this.addStringAt.apply(this, [r, "+"].concat(a)) : "{numpaddecimal}" === t ? r = this.addStringAt.apply(this, [r, "."].concat(a)) : "{" === t || "}" === t ? r = this.addStringAt.apply(this, [r, t].concat(a)) : t.includes("{") || t.includes("}") || (r = this.addStringAt.apply(this, [r, t].concat(a))) : r = this.addStringAt.apply(this, [r, "\n"].concat(a)) : r = this.addStringAt.apply(this, [r, "\t"].concat(a)), r
}
}, {
key: "updateCaretPos",
value: function(t, e) {
var n = this.updateCaretPosAction(t, e);
this.dispatch((function(t) {
t.setCaretPosition(n)
}))
}
}, {
key: "updateCaretPosAction",
value: function(t, e) {
var n = this.getOptions(),
o = this.getCaretPosition();
return e ? o > 0 && (o -= t) : o += t, n.debug && console.log("Caret at:", o, "(".concat(this.keyboardDOMClass, ")")), o
}
}, {
key: "addStringAt",
value: function(t, e) {
var n, o = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : t.length,
i = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : t.length,
s = arguments.length > 4 && void 0 !== arguments[4] && arguments[4];
return o || 0 === o ? (n = [t.slice(0, o), e, t.slice(i)].join(""), this.isMaxLengthReached() || s && this.updateCaretPos(e.length)) : n = t + e, n
}
}, {
key: "removeAt",
value: function(t) {
var e, n = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : t.length,
o = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : t.length,
i = arguments.length > 3 && void 0 !== arguments[3] && arguments[3];
if (0 === n && 0 === o) return t;
if (n === o) {
var s = /([\uD800-\uDBFF][\uDC00-\uDFFF])/g;
n && n >= 0 ? t.substring(n - 2, n).match(s) ? (e = t.substr(0, n - 2) + t.substr(n), i && this.updateCaretPos(2, !0)) : (e = t.substr(0, n - 1) + t.substr(n), i && this.updateCaretPos(1, !0)) : t.slice(-2).match(s) ? (e = t.slice(0, -2), i && this.updateCaretPos(2, !0)) : (e = t.slice(0, -1), i && this.updateCaretPos(1, !0))
} else e = t.slice(0, n) + t.slice(o), i && this.dispatch((function(t) {
t.setCaretPosition(n)
}));
return e
}
}, {
key: "handleMaxLength",
value: function(t, e) {
var n = this.getOptions(),
o = n.maxLength,
i = t[n.inputName],
s = e.length - 1 >= o;
if (e.length <= i.length) return !1;
if (Number.isInteger(o)) return n.debug && console.log("maxLength (num) reached:", s), s ? (this.maxLengthReached = !0, !0) : (this.maxLengthReached = !1, !1);
if ("object" === _typeof(o)) {
var a = e.length - 1 >= o[n.inputName];
return n.debug && console.log("maxLength (obj) reached:", a), a ? (this.maxLengthReached = !0, !0) : (this.maxLengthReached = !1, !1)
}
}
}, {
key: "isMaxLengthReached",
value: function() {
return Boolean(this.maxLengthReached)
}
}, {
key: "isTouchDevice",
value: function() {
return "ontouchstart" in window || navigator.maxTouchPoints
}
}, {
key: "pointerEventsSupported",
value: function() {
return window.PointerEvent
}
}, {
key: "camelCase",
value: function(t) {
return !!t && t.toLowerCase().trim().split(/[.\-_\s]/g).reduce((function(t, e) {
return e.length ? t + e[0].toUpperCase() + e.slice(1) : t
}))
}
}]) && _defineProperties(t.prototype, e), n && _defineProperties(t, n), Utilities
}();
s = function() {}, (i = "noop") in (o = a) ? Object.defineProperty(o, i, {
value: s,
enumerable: !0,
configurable: !0,
writable: !0
}) : o[i] = s;
var r = a;
function PhysicalKeyboard_defineProperties(t, e) {
for (var n = 0; n < e.length; n++) {
var o = e[n];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(t, o.key, o)
}
}
var u = function() {
function PhysicalKeyboard(t) {
var e = t.dispatch,
n = t.getOptions;
! function(t, e) {
if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
}(this, PhysicalKeyboard), this.dispatch = e, this.getOptions = n, r.bindMethods(PhysicalKeyboard, this)
}
var t, e, n;
return t = PhysicalKeyboard, (e = [{
key: "handleHighlightKeyDown",
value: function(t) {
var e = this.getOptions(),
n = this.getSimpleKeyboardLayoutKey(t);
this.dispatch((function(t) {
var o = t.getButtonElement(n) || t.getButtonElement("{".concat(n, "}"));
o && (o.style.backgroundColor = e.physicalKeyboardHighlightBgColor || "#dadce4", o.style.color = e.physicalKeyboardHighlightTextColor || "black", e.physicalKeyboardHighlightPress && (o.onpointerdown || o.onmousedown || o.ontouchstart || r.noop)())
}))
}
}, {
key: "handleHighlightKeyUp",
value: function(t) {
var e = this.getOptions(),
n = this.getSimpleKeyboardLayoutKey(t);
this.dispatch((function(t) {
var o = t.getButtonElement(n) || t.getButtonElement("{".concat(n, "}"));
o && o.removeAttribute && (o.removeAttribute("style"), e.physicalKeyboardHighlightPress && (o.onpointerup || o.onmouseup || o.ontouchend || r.noop)())
}))
}
}, {
key: "getSimpleKeyboardLayoutKey",
value: function(t) {
var e;
return ((e = t.code.includes("Numpad") || t.code.includes("Shift") || t.code.includes("Space") || t.code.includes("Backspace") || t.code.includes("Control") || t.code.includes("Alt") || t.code.includes("Meta") ? t.code : t.key) && e !== e.toUpperCase() || "F" === t.code[0] && Number.isInteger(Number(t.code[1])) && t.code.length <= 3) && (e = e ? e.toLowerCase() : e), e
}
}]) && PhysicalKeyboard_defineProperties(t.prototype, e), n && PhysicalKeyboard_defineProperties(t, n), PhysicalKeyboard
}();
function _toConsumableArray(t) {
return function(t) {
if (Array.isArray(t)) return Keyboard_arrayLikeToArray(t)
}(t) || function(t) {
if ("undefined" !== typeof Symbol && Symbol.iterator in Object(t)) return Array.from(t)
}(t) || function(t, e) {
if (!t) return;
if ("string" === typeof t) return Keyboard_arrayLikeToArray(t, e);
var n = Object.prototype.toString.call(t).slice(8, -1);
"Object" === n && t.constructor && (n = t.constructor.name);
if ("Map" === n || "Set" === n) return Array.from(t);
if ("Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return Keyboard_arrayLikeToArray(t, e)
}(t) || function() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")
}()
}
function Keyboard_arrayLikeToArray(t, e) {
(null == e || e > t.length) && (e = t.length);
for (var n = 0, o = new Array(e); n < e; n++) o[n] = t[n];
return o
}
function Keyboard_classCallCheck(t, e) {
if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
}
function Keyboard_defineProperties(t, e) {
for (var n = 0; n < e.length; n++) {
var o = e[n];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(t, o.key, o)
}
}
function Keyboard_defineProperty(t, e, n) {
return e in t ? Object.defineProperty(t, e, {
value: n,
enumerable: !0,
configurable: !0,
writable: !0
}) : t[e] = n, t
}
var c = function() {
function SimpleKeyboard() {
var t = this;
Keyboard_classCallCheck(this, SimpleKeyboard), Keyboard_defineProperty(this, "handleParams", (function(t) {
var e, n, o;
if ("string" === typeof t[0]) e = t[0].split(".").join(""), n = document.querySelector(".".concat(e)), o = t[1];
else if (t[0] instanceof HTMLDivElement) {
if (!t[0].className) throw console.warn("Any DOM element passed as parameter must have a class."), new Error("KEYBOARD_DOM_CLASS_ERROR");
e = t[0].className.split(" ")[0], n = t[0], o = t[1]
} else e = "simple-keyboard", n = document.querySelector(".".concat(e)), o = t[0];
return {
keyboardDOMClass: e,
keyboardDOM: n,
options: o
}
})), Keyboard_defineProperty(this, "getOptions", (function() {
return t.options
})), Keyboard_defineProperty(this, "getCaretPosition", (function() {
return t.caretPosition
})), Keyboard_defineProperty(this, "getCaretPositionEnd", (function() {
return t.caretPositionEnd
})), Keyboard_defineProperty(this, "registerModule", (function(e, n) {
t.modules[e] || (t.modules[e] = {}), n(t.modules[e])
})), Keyboard_defineProperty(this, "getKeyboardClassString", (function() {
for (var e = arguments.length, n = new Array(e), o = 0; o < e; o++) n[o] = arguments[o];
var i = [t.keyboardDOMClass].concat(n).filter((function(t) {
return !!t
}));
return i.join(" ")
}));
for (var e = arguments.length, n = new Array(e), o = 0; o < e; o++) n[o] = arguments[o];
var i = this.handleParams(n),
s = i.keyboardDOMClass,
a = i.keyboardDOM,
c = i.options,
l = void 0 === c ? {} : c;
if (this.utilities = new r({
getOptions: this.getOptions,
getCaretPosition: this.getCaretPosition,
getCaretPositionEnd: this.getCaretPositionEnd,
dispatch: this.dispatch
}), this.caretPosition = null, this.caretPositionEnd = null, this.keyboardDOM = a, this.options = l, this.options.layoutName = this.options.layoutName || "default", this.options.theme = this.options.theme || "hg-theme-default", this.options.inputName = this.options.inputName || "default", this.options.preventMouseDownDefault = this.options.preventMouseDownDefault || !1, this.keyboardPluginClasses = "", r.bindMethods(SimpleKeyboard, this), this.input = {}, this.input[this.options.inputName] = "", this.keyboardDOMClass = s, this.buttonElements = {}, window.SimpleKeyboardInstances || (window.SimpleKeyboardInstances = {}), this.currentInstanceName = this.utilities.camelCase(this.keyboardDOMClass), window.SimpleKeyboardInstances[this.currentInstanceName] = this, this.allKeyboardInstances = window.SimpleKeyboardInstances, this.keyboardInstanceNames = Object.keys(window.SimpleKeyboardInstances), this.isFirstKeyboardInstance = this.keyboardInstanceNames[0] === this.currentInstanceName, this.physicalKeyboard = new u({
dispatch: this.dispatch,
getOptions: this.getOptions
}), !this.keyboardDOM) throw console.warn('".'.concat(s, '" was not found in the DOM.')), new Error("KEYBOARD_DOM_ERROR");
this.render(), this.modules = {}, this.loadModules()
}
var t, e, n;
return t = SimpleKeyboard, (e = [{
key: "setCaretPosition",
value: function(t, e) {
this.caretPosition = t, this.caretPositionEnd = e || t
}
}, {
key: "handleButtonClicked",
value: function(t) {
var e = this.options.debug;
if ("{//}" === t) return !1;
"function" === typeof this.options.onKeyPress && this.options.onKeyPress(t), this.input[this.options.inputName] || (this.input[this.options.inputName] = "");
var n = this.utilities.getUpdatedInput(t, this.input[this.options.inputName], this.caretPosition, this.caretPositionEnd);
if (this.input[this.options.inputName] !== n && (!this.options.inputPattern || this.options.inputPattern && this.inputPatternIsValid(n))) {
if (this.options.maxLength && this.utilities.handleMaxLength(this.input, n)) return !1;
this.input[this.options.inputName] = this.utilities.getUpdatedInput(t, this.input[this.options.inputName], this.caretPosition, this.caretPositionEnd, !0), e && console.log("Input changed:", this.getAllInputs()), this.options.debug && console.log("Caret at: ", this.getCaretPosition(), this.getCaretPositionEnd(), "(".concat(this.keyboardDOMClass, ")")), this.options.syncInstanceInputs && this.syncInstanceInputs(), "function" === typeof this.options.onChange && this.options.onChange(this.getInput(this.options.inputName, !0)), "function" === typeof this.options.onChangeAll && this.options.onChangeAll(this.getAllInputs())
}
e && console.log("Key pressed:", t)
}
}, {
key: "handleButtonMouseDown",
value: function(t, e) {
var n = this;
e && (this.options.preventMouseDownDefault && e.preventDefault(), this.options.stopMouseDownPropagation && e.stopPropagation(), e.target.classList.add(this.activeButtonClass)), this.holdInteractionTimeout && clearTimeout(this.holdInteractionTimeout), this.holdTimeout && clearTimeout(this.holdTimeout), this.isMouseHold = !0, this.options.disableButtonHold || (this.holdTimeout = setTimeout((function() {
(n.isMouseHold && (!t.includes("{") && !t.includes("}") || "{delete}" === t || "{backspace}" === t || "{bksp}" === t || "{space}" === t || "{tab}" === t) || "{arrowright}" === t || "{arrowleft}" === t || "{arrowup}" === t || "{arrowdown}" === t) && (n.options.debug && console.log("Button held:", t), n.handleButtonHold(t, e)), clearTimeout(n.holdTimeout)
}), 500))
}
}, {
key: "handleButtonMouseUp",
value: function() {
var t = this,
e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : null,
n = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : null;
n && (this.options.preventMouseUpDefault && n.preventDefault(), this.options.stopMouseUpPropagation && n.stopPropagation()), this.recurseButtons((function(e) {
e.classList.remove(t.activeButtonClass)
})), this.isMouseHold = !1, this.holdInteractionTimeout && clearTimeout(this.holdInteractionTimeout), e && "function" === typeof this.options.onKeyReleased && this.options.onKeyReleased(e)
}
}, {
key: "handleKeyboardContainerMouseDown",
value: function(t) {
this.options.preventMouseDownDefault && t.preventDefault()
}
}, {
key: "handleButtonHold",
value: function(t) {
var e = this;
this.holdInteractionTimeout && clearTimeout(this.holdInteractionTimeout), this.holdInteractionTimeout = setTimeout((function() {
e.isMouseHold ? (e.handleButtonClicked(t), e.handleButtonHold(t)) : clearTimeout(e.holdInteractionTimeout)
}), 100)
}
}, {
key: "syncInstanceInputs",
value: function() {
var t = this;
this.dispatch((function(e) {
e.replaceInput(t.input), e.setCaretPosition(t.caretPosition, t.caretPositionEnd)
}))
}
}, {
key: "clearInput",
value: function(t) {
t = t || this.options.inputName, this.input[t] = "", this.setCaretPosition(0), this.options.syncInstanceInputs && this.syncInstanceInputs()
}
}, {
key: "getInput",
value: function(t) {
var e = arguments.length > 1 && void 0 !== arguments[1] && arguments[1];
if (t = t || this.options.inputName, this.options.syncInstanceInputs && !e && this.syncInstanceInputs(), this.options.rtl) {
var n = this.input[t].replace("\u202b", "").replace("\u202c", "");
return "\u202b" + n + "\u202c"
}
return this.input[t]
}
}, {
key: "getAllInputs",
value: function() {
var t = this,
e = {};
return Object.keys(this.input).forEach((function(n) {
e[n] = t.getInput(n, !0)
})), e
}
}, {
key: "setInput",
value: function(t, e) {
e = e || this.options.inputName, this.input[e] = t, this.options.syncInstanceInputs && this.syncInstanceInputs()
}
}, {
key: "replaceInput",
value: function(t) {
this.input = t
}
}, {
key: "setOptions",
value: function() {
var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
e = this.changedOptions(t);
this.options = Object.assign(this.options, t), e.length && (this.options.debug && console.log("changedOptions", e), this.onSetOptions(t), this.render())
}
}, {
key: "changedOptions",
value: function(t) {
var e = this;
return Object.keys(t).filter((function(n) {
return JSON.stringify(t[n]) !== JSON.stringify(e.options[n])
}))
}
}, {
key: "onSetOptions",
value: function(t) {
t.inputName && (this.options.debug && console.log("inputName changed. caretPosition reset."), this.setCaretPosition(null))
}
}, {
key: "clear",
value: function() {
this.keyboardDOM.innerHTML = "", this.keyboardDOM.className = this.keyboardDOMClass, this.buttonElements = {}
}
}, {
key: "dispatch",
value: function(t) {
if (!window.SimpleKeyboardInstances) throw console.warn("SimpleKeyboardInstances is not defined. Dispatch cannot be called."), new Error("INSTANCES_VAR_ERROR");
return Object.keys(window.SimpleKeyboardInstances).forEach((function(e) {
t(window.SimpleKeyboardInstances[e], e)
}))
}
}, {
key: "addButtonTheme",
value: function(t, e) {
var n = this;
if (!e || !t) return !1;
t.split(" ").forEach((function(o) {
e.split(" ").forEach((function(e) {
n.options.buttonTheme || (n.options.buttonTheme = []);
var i = !1;
n.options.buttonTheme.map((function(t) {
if (t.class.split(" ").includes(e)) {
i = !0;
var n = t.buttons.split(" ");
n.includes(o) || (i = !0, n.push(o), t.buttons = n.join(" "))
}
return t
})), i || n.options.buttonTheme.push({
class: e,
buttons: t
})
}))
})), this.render()
}
}, {
key: "removeButtonTheme",
value: function(t, e) {
var n = this;
if (!t && !e) return this.options.buttonTheme = [], this.render(), !1;
t && Array.isArray(this.options.buttonTheme) && this.options.buttonTheme.length && (t.split(" ").forEach((function(t) {
n.options.buttonTheme.map((function(o, i) {
if (e && e.includes(o.class) || !e) {
var s = o.buttons.split(" ").filter((function(e) {
return e !== t
}));
s.length ? o.buttons = s.join(" ") : (n.options.buttonTheme.splice(i, 1), o = null)
}
return o
}))
})), this.render())
}
}, {
key: "getButtonElement",
value: function(t) {
var e, n = this.buttonElements[t];
return n && (e = n.length > 1 ? n : n[0]), e
}
}, {
key: "inputPatternIsValid",
value: function(t) {
var e, n = this.options.inputPattern;
if ((e = n instanceof RegExp ? n : n[this.options.inputName]) && t) {
var o = e.test(t);
return this.options.debug && console.log('inputPattern ("'.concat(e, '"): ').concat(o ? "passed" : "did not pass!")), o
}
return !0
}
}, {
key: "setEventListeners",
value: function() {
!this.isFirstKeyboardInstance && this.allKeyboardInstances || (this.options.debug && console.log("Caret handling started (".concat(this.keyboardDOMClass, ")")), document.addEventListener("keyup", this.handleKeyUp), document.addEventListener("keydown", this.handleKeyDown), document.addEventListener("mouseup", this.handleMouseUp), document.addEventListener("touchend", this.handleTouchEnd))
}
}, {
key: "handleKeyUp",
value: function(t) {
this.caretEventHandler(t), this.options.physicalKeyboardHighlight && this.physicalKeyboard.handleHighlightKeyUp(t)
}
}, {
key: "handleKeyDown",
value: function(t) {
this.options.physicalKeyboardHighlight && this.physicalKeyboard.handleHighlightKeyDown(t)
}
}, {
key: "handleMouseUp",
value: function(t) {
this.caretEventHandler(t)
}
}, {
key: "handleTouchEnd",
value: function(t) {
this.caretEventHandler(t)
}
}, {
key: "caretEventHandler",
value: function(t) {
var e;
t.target.tagName && (e = t.target.tagName.toLowerCase()), this.dispatch((function(n) {
var o = t.target === n.keyboardDOM || t.target && n.keyboardDOM.contains(t.target);
n.isMouseHold && (n.isMouseHold = !1), "textarea" !== e && "input" !== e || !("selectionStart" in t.target) || !("selectionEnd" in t.target) || n.options.disableCaretPositioning ? !n.options.disableCaretPositioning && o || n.setCaretPosition(null) : (n.setCaretPosition(t.target.selectionStart, t.target.selectionEnd), n.options.debug && console.log("Caret at: ", n.getCaretPosition(), n.getCaretPositionEnd(), t && t.target.tagName.toLowerCase(), "(".concat(n.keyboardDOMClass, ")")))
}))
}
}, {
key: "recurseButtons",
value: function(t) {
var e = this;
t && Object.keys(this.buttonElements).forEach((function(n) {
return e.buttonElements[n].forEach(t)
}))
}
}, {
key: "destroy",
value: function() {
this.options.debug && console.log("Destroying simple-keyboard instance: ".concat(this.currentInstanceName)), document.removeEventListener("keyup", this.handleKeyUp), document.removeEventListener("keydown", this.handleKeyDown), document.removeEventListener("mouseup", this.handleMouseUp), document.removeEventListener("touchend", this.handleTouchEnd), document.onpointerup = null, document.ontouchend = null, document.ontouchcancel = null, document.onmouseup = null;
var deleteButton = function(t) {
t.onpointerdown = null, t.onpointerup = null, t.onpointercancel = null, t.ontouchstart = null, t.ontouchend = null, t.ontouchcancel = null, t.onclick = null, t.onmousedown = null, t.onmouseup = null, t.remove(), t = null
};
this.recurseButtons(deleteButton), this.recurseButtons = null, deleteButton = null, this.keyboardDOM.onpointerdown = null, this.keyboardDOM.ontouchstart = null, this.keyboardDOM.onmousedown = null, this.clear(), window.SimpleKeyboardInstances[this.currentInstanceName] = null, delete window.SimpleKeyboardInstances[this.currentInstanceName], this.initialized = !1
}
}, {
key: "getButtonThemeClasses",
value: function(t) {
var e = this.options.buttonTheme,
n = [];
return Array.isArray(e) && e.forEach((function(e) {
if (e.class && "string" === typeof e.class && e.buttons && "string" === typeof e.buttons) {
var o = e.class.split(" ");
e.buttons.split(" ").includes(t) && (n = [].concat(_toConsumableArray(n), _toConsumableArray(o)))
} else console.warn('Incorrect "buttonTheme". Please check the documentation.', e)
})), n
}
}, {
key: "setDOMButtonAttributes",
value: function(t, e) {
var n = this.options.buttonAttributes;
Array.isArray(n) && n.forEach((function(n) {
n.attribute && "string" === typeof n.attribute && n.value && "string" === typeof n.value && n.buttons && "string" === typeof n.buttons ? n.buttons.split(" ").includes(t) && e(n.attribute, n.value) : console.warn('Incorrect "buttonAttributes". Please check the documentation.', n)
}))
}
}, {
key: "onTouchDeviceDetected",
value: function() {
this.processAutoTouchEvents(), this.disableContextualWindow()
}
}, {
key: "disableContextualWindow",
value: function() {
window.oncontextmenu = function(t) {
if (t.target.classList.contains("hg-button")) return t.preventDefault(), t.stopPropagation(), !1
}
}
}, {
key: "processAutoTouchEvents",
value: function() {
this.options.autoUseTouchEvents && (this.options.useTouchEvents = !0, this.options.debug && console.log("autoUseTouchEvents: Touch device detected, useTouchEvents enabled."))
}
}, {
key: "onInit",
value: function() {
this.options.debug && console.log("".concat(this.keyboardDOMClass, " Initialized")), this.setEventListeners(), "function" === typeof this.options.onInit && this.options.onInit()
}
}, {
key: "beforeFirstRender",
value: function() {
this.utilities.isTouchDevice() && this.onTouchDeviceDetected(), "function" === typeof this.options.beforeFirstRender && this.options.beforeFirstRender(), this.isFirstKeyboardInstance && this.utilities.pointerEventsSupported() && !this.options.useTouchEvents && !this.options.useMouseEvents && this.options.debug && console.log("Using PointerEvents as it is supported by this browser"), this.options.useTouchEvents && this.options.debug && console.log("useTouchEvents has been enabled. Only touch events will be used.")
}
}, {
key: "beforeRender",
value: function() {
"function" === typeof this.options.beforeRender && this.options.beforeRender()
}
}, {
key: "onRender",
value: function() {
"function" === typeof this.options.onRender && this.options.onRender()
}
}, {
key: "onModulesLoaded",
value: function() {
"function" === typeof this.options.onModulesLoaded && this.options.onModulesLoaded(this)
}
}, {
key: "loadModules",
value: function() {
var t = this;
Array.isArray(this.options.modules) && (this.options.modules.forEach((function(e) {
(new e).init(t)
})), this.keyboardPluginClasses = "modules-loaded", this.render(), this.onModulesLoaded())
}
}, {
key: "getModuleProp",
value: function(t, e) {
return !!this.modules[t] && this.modules[t][e]
}
}, {
key: "getModulesList",
value: function() {
return Object.keys(this.modules)
}
}, {
key: "parseRowDOMContainers",
value: function(t, e, n, o) {
var i = this,
s = Array.from(t.children),
a = 0;
return s.length && n.forEach((function(n, r) {
var u = o[r];
if (!u || !(u > n)) return !1;
var c = n - a,
l = u - a,
h = document.createElement("div");
h.className += "hg-button-container";
var d = "".concat(i.options.layoutName, "-r").concat(e, "c").concat(r);
h.setAttribute("data-skUID", d);
var p = s.splice(c, l - c + 1);
a = l - c, p.forEach((function(t) {
return h.appendChild(t)
})), s.splice(c, 0, h), t.innerHTML = "", s.forEach((function(e) {
return t.appendChild(e)
})), i.options.debug && console.log("rowDOMContainer", p, c, l, a + 1)
})), t
}
}, {
key: "render",
value: function() {
var t = this;
this.clear(), this.initialized || this.beforeFirstRender(), this.beforeRender();
var e = "hg-layout-".concat(this.options.layoutName),
n = this.options.layout || {
default: ["` 1 2 3 4 5 6 7 8 9 0 - = {bksp}", "{tab} q w e r t y u i o p [ ] \\", "{lock} a s d f g h j k l ; ' {enter}", "{shift} z x c v b n m , . / {shift}", ".com @ {space}"],
shift: ["~ ! @ # $ % ^ & * ( ) _ + {bksp}", "{tab} Q W E R T Y U I O P { } |", '{lock} A S D F G H J K L : " {enter}', "{shift} Z X C V B N M < > ? {shift}", ".com @ {space}"]
},
o = this.options.useTouchEvents || !1,
i = o ? "hg-touch-events" : "",
s = this.options.useMouseEvents || !1,
a = this.options.disableRowButtonContainers;
this.keyboardDOM.className = this.getKeyboardClassString(this.options.theme, e, this.keyboardPluginClasses, i), n[this.options.layoutName].forEach((function(e, n) {
var i = e.split(" "),
r = document.createElement("div");
r.className += "hg-row";
var u = [],
c = [];
i.forEach((function(e, i) {
var l, h = !a && "string" === typeof e && e.length > 1 && 0 === e.indexOf("["),
d = !a && "string" === typeof e && e.length > 1 && e.indexOf("]") === e.length - 1;
h && (u.push(i), e = e.replace(/\[/g, "")), d && (c.push(i), e = e.replace(/\]/g, ""));
var p = t.utilities.getButtonClass(e),
f = t.utilities.getButtonDisplayName(e, t.options.display, t.options.mergeDisplay),
y = t.options.useButtonTag ? "button" : "div",
b = document.createElement(y);
b.className += "hg-button ".concat(p),
/*(l = b.classList).add.apply(l, _toConsumableArray(t.getButtonThemeClasses(e))),*/
t.setDOMButtonAttributes(e, (function(t, e) {
b.setAttribute(t, e)
})), t.activeButtonClass = "hg-activeButton", !t.utilities.pointerEventsSupported() || o || s ? o ? (b.ontouchstart = function(n) {
t.handleButtonClicked(e), t.handleButtonMouseDown(e, n)
}, b.ontouchend = function(n) {
t.handleButtonMouseUp(e, n)
}, b.ontouchcancel = function(n) {
t.handleButtonMouseUp(e, n)
}) : (b.onclick = function() {
t.isMouseHold = !1, t.handleButtonClicked(e)
}, b.onmousedown = function(n) {
t.handleButtonMouseDown(e, n)
}, b.onmouseup = function(n) {
t.handleButtonMouseUp(e, n)
}) : (b.onpointerdown = function(n) {
t.handleButtonClicked(e), t.handleButtonMouseDown(e, n)
}, b.onpointerup = function(n) {
t.handleButtonMouseUp(e, n)
}, b.onpointercancel = function(n) {
t.handleButtonMouseUp(e, n)
}), b.setAttribute("data-skBtn", e);
var m = "".concat(t.options.layoutName, "-r").concat(n, "b").concat(i);
b.setAttribute("data-skBtnUID", m);
var g = document.createElement("span");
g.innerHTML = f, b.appendChild(g), t.buttonElements[e] || (t.buttonElements[e] = []), t.buttonElements[e].push(b), r.appendChild(b)
})), r = t.parseRowDOMContainers(r, n, u, c), t.keyboardDOM.appendChild(r)
})), this.onRender(), this.initialized || (this.initialized = !0, !this.utilities.pointerEventsSupported() || o || s ? o ? (document.ontouchend = function() {
return t.handleButtonMouseUp()
}, document.ontouchcancel = function() {
return t.handleButtonMouseUp()
}, this.keyboardDOM.ontouchstart = function(e) {
return t.handleKeyboardContainerMouseDown(e)
}) : o || (document.onmouseup = function() {
return t.handleButtonMouseUp()
}, this.keyboardDOM.onmousedown = function(e) {
return t.handleKeyboardContainerMouseDown(e)
}) : (document.onpointerup = function() {
return t.handleButtonMouseUp()
}, this.keyboardDOM.onpointerdown = function(e) {
return t.handleKeyboardContainerMouseDown(e)
}), this.onInit())
}
}]) && Keyboard_defineProperties(t.prototype, e), n && Keyboard_defineProperties(t, n), SimpleKeyboard
}();
e.default = c
}])
}));
//# sourceMappingURL=index.js.map
+12
View File
@@ -0,0 +1,12 @@
/*!
*
* simple-keyboard v2.32.123
* https://github.com/hodgef/simple-keyboard
*
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/.hg-theme-default{width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.hg-theme-default .hg-button span{pointer-events:none}.hg-theme-default button.hg-button{border-width:0;outline:0;font-size:inherit}.hg-theme-default{font-family:"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;background-color:#ececec;padding:5px;border-radius:5px}.hg-theme-default .hg-button{display:inline-block;flex-grow:1}.hg-theme-default .hg-row{display:flex}.hg-theme-default .hg-row:not(:last-child){margin-bottom:5px}.hg-theme-default .hg-row .hg-button-container,.hg-theme-default .hg-row .hg-button:not(:last-child){margin-right:5px}.hg-theme-default .hg-row>div:last-child{margin-right:0}.hg-theme-default .hg-row .hg-button-container{display:flex}.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:flex;align-items:center;justify-content:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}.hg-theme-default .hg-button.hg-activeButton{background:#efefef}.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;align-items:center;display:flex;justify-content:center}.hg-theme-default .hg-button.hg-button-numpadadd,.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.hg-theme-default .hg-button.hg-button-com{max-width:85px}.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}
/*# sourceMappingURL=index.css.map */
+962
View File
@@ -0,0 +1,962 @@
/**
* SpatialNavigator simulates four-direction navigation in Javascript level.
*
* Navigation is the ability to navigate between focusable elements
* within a structured document or user interface according to the spatial
* location. Users are assumed navigating among elements on a 2D plane by
* arrow keys (up/down/left/right).
*
* SpatialNavigator keeps a 'focused' element by itself. When navigating,
* focus/unfocus events are triggered automatically. Notice the focus is just
* an internal state rather than actual focus of DOM Element. User should
* add event listeners of those events, and design required behaviors.
*
* @class SpatialNavigator
* @param {Array.<SpatialNavigatorElement>} [collection=[]]
* An initial set of traversable elements.
* @param {Object} [config]
* An initial set of configurations.
*/
/**
* SpatialNavigatorElement is a navigable element which can be traversed
* by {@link SpatialNavigator}. Valid types are as follows:
*
* 1. a standard HTMLElement.
* 2. an Object contains at least 4 properties: left, top, width, and height.
* 3. an Object implementing getBoundingRect() which returns an object of 2.
*
* @typedef {Object} SpatialNavigatorElement
*/
/**
* Fired when an element is focused.
* @event SpatialNavigator#focus
* @property {SpatialNavigatorElement} elem The element which got focus.
*/
/**
* Fired when an element is unfocused.
* @event SpatialNavigator#unfocus
* @property {SpatialNavigatorElement} elem The element which lost focus.
*/
var SpatialNavigator = function () {
this._focus = null;
this._previous = null;
this._collection = [];
//this.setCollection(collection);
/*
if (config) {
for (var key in config) {
this[key] = config[key];
}
}
*/
}
SpatialNavigator.prototype = {
/**
* Limit the navigating direction to vertical and horizontal only. Targets
* in oblique (left-top, right-top, left-bottom, and right-bottom)
* directions are always ignored.
* @type {Boolean}
* @default false
* @memberof SpatialNavigator.prototype
*/
straightOnly: true,
/**
* This threshold is used to determine whether an element is considered in
* straight (vertical or horizontal) directions. Valid number is between 0
* to 1.0. Setting it to 0.3 means an element is counted in the straight
* directions if it overlaps the straight area at least 0.3x of width of the
* area.
* @type {Number}
* @default 0.5
* @memberof SpatialNavigator.prototype
*/
straightOverlapThreshold: 0.5,
/**
* Ignore elements with "display: none", "visibility: hidden" or
* "aria-hidden=true".
* @type {Boolean}
* @default false
* @memberof SpatialNavigator.prototype
*/
ignoreHiddenElement: false,
/**
* The previous focused element has high priority to be chosen as the next
* candidate.
* @type {Boolean}
* @default false
* @memberof SpatialNavigator.prototype
*/
rememberSource: false,
/**
* A callback function that accepcts an element as the first argument will
* be triggered everytime when SpatialNavigator tries to traverse every
* single candidate. You can ignore arbitrary elements by returning "false"
* in this function.
* @type {Function}
* @default null
* @memberof SpatialNavigator.prototype
*/
navigableFilter: null,
/**
* setting this property true prevents spatialNavigator from emitting any
* events.
* @type {Boolean}
*/
silent: false,
/**
* Rect represents position and dimension of a 2D object.
* @typedef {Object} Rect
* @property {Integer} left Left position
* @property {Integer} top Top position
* @property {Integer} right Right position
* @property {Integer} bottom Bottom position
* @property {Integer} width Width dimension
* @property {Integer} height Height dimension
* @property {Rect} [center] Center position
* @property {Integer} [x] same as left
* @property {Integer} [y] same as top
* @access private
* @memberof SpatialNavigator.prototype
*/
follow: function ( type, listener ) {
if ( this._listeners === undefined ) this._listeners = {};
var listeners = this._listeners;
if ( listeners[ type ] === undefined ) {
listeners[ type ] = [];
}
if ( listeners[ type ].indexOf( listener ) === - 1 ) {
listeners[ type ].push( listener );
}
},
hasListener: function ( type, listener ) {
if ( this._listeners === undefined ) return false;
var listeners = this._listeners;
return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
},
removeListener: function ( type, listener ) {
if ( this._listeners === undefined ) return;
var listeners = this._listeners;
var listenerArray = listeners[ type ];
if ( listenerArray !== undefined ) {
var index = listenerArray.indexOf( listener );
if ( index !== - 1 ) {
listenerArray.splice( index, 1 );
}
}
},
send: function ( type,event ) {
if ( this._listeners === undefined ) return;
var listeners = this._listeners;
var listenerArray = listeners[ type ];
if ( listenerArray !== undefined ) {
event.target = this;
var array = listenerArray.slice( 0 );
for ( var i = 0, l = array.length; i < l; i ++ ) {
array[ i ].call( this, event );
}
}
},
/**
* Get {@link Rect} of a {@link SpatialNavigatorElement}.
*
* @param {SpatialNavigatorElement} elem
*
* @return {Rect} dimension of elem.
*
* @access private
* @memberof SpatialNavigator.prototype
*/
_getRect: function snGetRect(elem) {
var rect = null;
if (!this._isNavigable(elem)) {
return null;
}
if (elem.getBoundingClientRect) {
var cr = elem.getBoundingClientRect();
rect = {
left: cr.left,
top: cr.top,
width: cr.width,
height: cr.height
};
} else if (elem.left !== undefined) {
rect = {
left: parseInt(elem.left || 0, 10),
top: parseInt(elem.top || 0, 10),
width: parseInt(elem.width || 0, 10),
height: parseInt(elem.height || 0, 10)
};
} else {
return null;
}
rect.element = elem;
rect.right = rect.left + rect.width;
rect.bottom = rect.top + rect.height;
rect.center = {
x: rect.left + Math.floor(rect.width / 2),
y: rect.top + Math.floor(rect.height / 2)
};
rect.center.left = rect.center.right = rect.center.x;
rect.center.top = rect.center.bottom = rect.center.y;
return rect;
},
/**
* Get all {@link Rect} objects from the collection.
*
* @param {SpatialNavigatorElement} [excludedElem]
* You can pass excludedElem here to ignore it from calculating.
* (most likely, the currently focused element is passed).
*
* @return {Array.<Rect>} {@link Rect} objects of all traversable elements.
*
* @access private
* @memberof SpatialNavigator.prototype
*/
_getAllRects: function snGetAllRects(excludedElem) {
var rects = [];
this._collection.forEach(function (elem) {
if (!excludedElem || excludedElem !== elem) {
var rect = this._getRect(elem);
if (rect) {
rects.push(rect);
}
}
}, this);
return rects;
},
/**
* Check whether a {@link SpatialNavigatorElement} is navigable.
*
* @param {SpatialNavigatorElement} elem
*
* @return {Boolean} true if it's navigable.
*
* @access private
* @memberof SpatialNavigator.prototype
*/
_isNavigable: function snIsNavigable(elem) {
if (this.ignoreHiddenElement && elem instanceof HTMLElement) {
var computedStyle = window.getComputedStyle(elem);
if ((elem.offsetWidth <= 0 && elem.offsetHeight <= 0) ||
computedStyle.getPropertyValue('visibility') == 'hidden' ||
computedStyle.getPropertyValue('display') == 'none' ||
elem.hasAttribute('aria-hidden')) {
return false;
}
}
if (this.navigableFilter && !this.navigableFilter(elem)) {
return false;
}
return true;
},
/**
* Given a set of {@link Rect} array, divide them into 9 groups with
* respect to the position of targetRect. Rects centered inside targetRect
* are grouped as 4th group; straight left as 3rd group; straight right as
* 5th group; ..... and so on. See below for the corresponding group number:
*
* <pre>
* |---+---+---|
* | 0 | 1 | 2 |
* |---+---+---|
* | 3 | 4 | 5 |
* |---+---+---|
* | 6 | 7 | 8 |
* |---+---+---|
* </pre>
*
* @param {Array.<Rect>} rects
* {@link RectS} to be divided.
* @param {Rect} targetRect
* Reference position for groups.
*
* @return {Array.Array.<SpatialNavigatorElement>}
* A 9-elements array of array, where rects are categorized into
* these 9 arrays by their group number.
*
* @access private
* @memberof SpatialNavigator.prototype
*
*/
_partition: function snDemarcate(rects, targetRect) {
var groups = [[], [], [], [], [], [], [], [], []];
var threshold = this.straightOverlapThreshold;
if (threshold > 1 || threshold < 0) {
// Fallback to default value
threshold = 0.5;
}
rects.forEach(function (rect) {
var center = rect.center;
var x, y, groupId;
if (center.x < targetRect.left) {
x = 0;
} else if (center.x <= targetRect.right) {
x = 1;
} else {
x = 2;
}
if (center.y < targetRect.top) {
y = 0;
} else if (center.y <= targetRect.bottom) {
y = 1;
} else {
y = 2;
}
groupId = y * 3 + x;
groups[groupId].push(rect);
// Although a rect is in the oblique directions, we categorize it in
// the straight area as well if it overlaps the straight directions more
// than a specified threshold (0.5 by default).
if ([0, 2, 6, 8].indexOf(groupId) !== -1) {
if (rect.left <= targetRect.right - targetRect.width * threshold) {
if (groupId === 2) {
groups[1].push(rect);
} else if (groupId === 8) {
groups[7].push(rect);
}
}
if (rect.right >= targetRect.left + targetRect.width * threshold) {
if (groupId === 0) {
groups[1].push(rect);
} else if (groupId === 6) {
groups[7].push(rect);
}
}
if (rect.top <= targetRect.bottom - targetRect.height * threshold) {
if (groupId === 6) {
groups[3].push(rect);
} else if (groupId === 8) {
groups[5].push(rect);
}
}
if (rect.bottom >= targetRect.top + targetRect.height * threshold) {
if (groupId === 0) {
groups[3].push(rect);
} else if (groupId === 2) {
groups[5].push(rect);
}
}
}
});
return groups;
},
/**
* Bind targetRect to a set of distance functions for ranking. These
* functions work with another {@link Rect} object passed to get a ranking
* value relative to targetRect.
*
* @param {Rect} targetRect
*
* @return {Object.<function>}
* An object containing a bunch of functions bound with targetRect.
*
* @access private
* @memberof SpatialNavigator.prototype
*/
_getDistanceFunction: function snGetDistanceFunction(targetRect) {
return {
/* Plumb Line: a vertical line through the center of the
targetRect. */
nearPlumbLineIsBetter: function (rect) {
var d;
if (rect.center.x < targetRect.center.x) {
d = targetRect.center.x - rect.right;
} else {
d = rect.left - targetRect.center.x;
}
return d < 0 ? 0 : d;
},
/* Horizon: a horizontal line through the center of the
"targetRect". */
nearHorizonIsBetter: function (rect) {
var d;
if (rect.center.y < targetRect.center.y) {
d = targetRect.center.y - rect.bottom;
} else {
d = rect.top - targetRect.center.y;
}
return d < 0 ? 0 : d;
},
/* Target Left: a coincident line of the left edge of the
"targetRect". */
nearTargetLeftIsBetter: function (rect) {
var d;
if (rect.center.x < targetRect.center.x) {
d = targetRect.left - rect.right;
} else {
d = rect.left - targetRect.left;
}
return d < 0 ? 0 : d;
},
/* Target Top: a coincident line of the top edge of the
"targetRect". */
nearTargetTopIsBetter: function (rect) {
var d;
if (rect.center.y < targetRect.center.y) {
d = targetRect.top - rect.bottom;
} else {
d = rect.top - targetRect.top;
}
return d < 0 ? 0 : d;
},
/* top, bottom, left, and right: Just ranking by absolute coordinate
without respect to targetRect. Usually they are used as fallback
rules when ranks above are draw. */
topIsBetter: function (rect) {
return rect.top;
},
bottomIsBetter: function (rect) {
return -1 * rect.bottom;
},
leftIsBetter: function (rect) {
return rect.left;
},
rightIsBetter: function (rect) {
return -1 * rect.right;
}
};
},
/**
* PrioritySet contains a set of elements with distance functions that
* should be used to rank them (obtained from {@link
* SpatialNavigator#_getDistanceFunction}).
*
* @typedef PrioritySet
* @property {Array.<Rects>} group
* {@link Rects} of elements that need to be prioritized.
* @property {Array.<function>} distance
* Distance functions. Primary ranking rule should be put in index
* 0; secondary in index 1 (fallback rule when primary rule draws
* ); and so on.
* @access private
* @memberof SpatialNavigator.prototype
*/
/**
* Pick a {@link Rect} with highest priority.
*
* @param {Array.<PrioritySet>} priorities
* An array of {@link PrioritySet} that need to be prioritized. The
* set with lowest index containing non-empty {PrioritySet.group}
* would be prioritized.
* @param {SpatialNavigatorElement} target
* The origin of coordinates for traversal.
* @param {String} direction
* It should be "left", "right", "up" or "down".
*
* @return {Rect} the {@link Rect} of highest priority.
*
* @access private
* @memberof SpatialNavigator.prototype
*/
_prioritize: function snPrioritize(priorities, target, direction) {
var destPriority = priorities.find(function (p) {
return !!p.group.length;
});
if (!destPriority) {
return null;
}
if (this.rememberSource &&
this._previous &&
target == this._previous.destination &&
direction == this._previous.reverse) {
var source = this._previous.source;
var found = destPriority.group.find(function (dest) {
return dest.element == source;
});
if (found) {
return found;
}
}
destPriority.group.sort(function (a, b) {
return destPriority.distance.reduce(function (answer, distance) {
return answer || (distance(a) - distance(b));
}, 0);
});
return destPriority.group[0];
},
/**
* Replace the set of traversable elements.
*
* @param {Array.<SpatialNavigatorElement>} [collection=[]]
elements to be replaced. The array is deep-copied and never
be changed directly by SpatialNavigator.
*
* @fires SpatialNavigator#unfocus
* @memberof SpatialNavigator.prototype
*/
setCollection: function snSetCollection(collection) {
this.unfocus();
this._collection = [];
if (collection) {
this.multiAdd(collection);
}
},
/**
* Add an element to traversable set.
*
* @param {SpatialNavigatorElement} elem
* @return {Boolean} true if succeed.
*
* @memberof SpatialNavigator.prototype
*/
add: function snAdd(elem) {
var index = this._collection.indexOf(elem);
if (index >= 0) {
return false;
}
this._collection.push(elem);
return true;
},
/**
* Add a bunch of elements to traversable set.
*
* @param {Array.<SpatialNavigatorElement>} elements
* @return {Boolean} true if all elements are added successfully.
*
* @memberof SpatialNavigator.prototype
*/
multiAdd: function snMultiAdd(elements) {
return Array.from(elements).every(this.add, this);
},
/**
* Remove an element from traversable set.
*
* @param {SpatialNavigatorElement} elem
* @return {Boolean} true if succeed. false if elem does not exist.
*
* @fires SpatialNavigator#unfocus
* @memberof SpatialNavigator.prototype
*/
remove: function snRemove(elem) {
var index = this._collection.indexOf(elem);
if (index < 0) {
return false;
}
if (this._focus === elem) {
this.unfocus();
}
this._collection.splice(index, 1);
return true;
},
/**
* Remove a bunch of elements to traversable set.
*
* @param {Array.<SpatialNavigatorElement>} elements
* @return {Boolean} true if all elements are removed successfully.
*
* @memberof SpatialNavigator.prototype
*/
multiRemove: function snMultiRemove(elements) {
return Array.from(elements).every(this.remove, this);
},
focused: function (elem) {
this._focus = elem;
},
/**
* Move focus to an existing element.
*
* @param {SpatialNavigatorElement} [elem]
* when omitted, it focuses the last focused element or the first
* navigable element if no previously-focused element is found.
*
* @return {Boolean} true if succeed. false if element doesn't exist.
*
* @fires SpatialNavigator#focus
* @fires SpatialNavigator#unfocus
* @memberof SpatialNavigator.prototype
*/
focus: function snFocus(elem) {
// If no arguments are received, let current focused element be the
// default.
if (!elem && this._focus && this._isNavigable(this._focus)) {
elem = this._focus;
}
if (!this._collection) {
return false;
}
if (!elem) {
var navigableElems = this._collection.filter(this._isNavigable, this);
if (!navigableElems.length) {
return false;
}
elem = navigableElems[0];
} else if (this._collection.indexOf(elem) < 0 ||
!this._isNavigable(elem)) {
return false;
}
this.unfocus();
this._focus = elem;
if (!this.silent) {
this.send('focus',{elem: this._focus });
}
return true;
},
/**
* Remove focus if any.
*
* It will trigger "unfocus" event.
*
* @return {Boolean} succeed or not.
*
* @fires SpatialNavigator#unfocus
* @memberof SpatialNavigator.prototype
*/
unfocus: function snUnfocus() {
if (this._focus) {
var elem = this._focus;
this._focus = null;
if (!this.silent) {
this.send('unfocus',{ elem: elem });
}
}
return true;
},
/**
* Get the currently focused element.
*
* @return {SpatialNavigatorElement} or null if nothing focused.
*
* @memberof SpatialNavigator.prototype
*/
getFocusedElement: function snGetFocusedElement() {
return this._focus;
},
/**
* Given a direction, find the element nearest to the focus element in that
* direction. This is equivalent to {@link SpatialNavigator#navigate} with
* focused element passed as target.
*
* @param {String} direction
* It should be "left", "right", "up" or "down".
*
* @return {Boolean} true if succeed, false if nothing can be focused.
*
* @memberof SpatialNavigator.prototype
*/
move: function snMove(direction) {
var reverse = {
'left': 'right',
'up': 'down',
'right': 'left',
'down': 'up'
};
if (!this._focus) {
this._previous = null;
this.focus();
} else {
var elem = this.navigate(this._focus, direction);
if (!elem) {
return false;
}
if (this.rememberSource) {
this._previous = {
source: this._focus,
destination: elem,
reverse: reverse[direction.toLowerCase()]
};
}
this.unfocus();
this.focus(elem);
}
return true;
},
canmove: function (direction) {
if (this._focus) {
var elem = this.navigate(this._focus, direction);
if (elem !== null) return elem;
}
return false;
},
/**
* Given a direction, find an element nearest to the target element in that
* direction.
*
* @param {SpatialNavigatorElement} target
* The origin of coordinates for traversal.
* @param {String} direction
* It should be "left", "right", "up" or "down".
*
* @return {SpatialNavigatorElement}
* The destination of the element which has the highest priority.
*
* @memberof SpatialNavigator.prototype
*/
navigate: function snNavigate(target, direction) {
if (!target || !direction || !this._collection) {
return null;
}
direction = direction.toLowerCase();
var rects = this._getAllRects(target);
var targetRect = this._getRect(target);
if (!targetRect || !rects.length) {
return null;
}
/* Get distance functions for ranking priorities relative to targetRect */
var distanceFunction = this._getDistanceFunction(targetRect);
/* Candidate {@link Rect}s are divided into nine regions based on its
position with respect to targetRect. */
var groups = this._partition(rects, targetRect);
/* {@link Rect}s in group 4 overlaps with targetRect. We distribute them
further into 9 regions based on its position with respect to the
center point of targetRect. */
var internalGroups = this._partition(groups[4], targetRect.center);
/* priorities: This big array carrys candidate elements with related
* distance functions by appropriate priority we want. Depenging on the
* direction, 3 kinds of elements are added separately in the following
* order:
*
* - 1st: candidates centered inside targetRect (group 4)
* (so we pick up corresponding internalGroups).
* - 2nd: in groups of straight direction (group 1, 3, 5, 7).
* - 3rd: in groups of oblique direction (group 0, 2, 6, 8).
*
* For each kind of element above, ranking is performed by the following
* rules (distance functions) in order:
*
* - 1st: distance between candidate and target.
* - 2nd: absolute coordinate of candidates.
* - 3rd: distance of left or top coordinate between candidate and
* target (for oblique direction only)
*
* The switch...case block below is just to construct this array.
* We just pick the required order into array here, then call
* {SpatialNavigator#_prioritize} to do the trick.
*/
var priorities;
switch (direction) {
case 'left':
priorities = [
{
group: internalGroups[0].concat(internalGroups[3])
.concat(internalGroups[6]),
distance: [
distanceFunction.nearPlumbLineIsBetter,
distanceFunction.topIsBetter
]
},
{
group: groups[3],
distance: [
distanceFunction.nearPlumbLineIsBetter,
distanceFunction.topIsBetter
]
},
{
group: groups[0].concat(groups[6]),
distance: [
distanceFunction.nearHorizonIsBetter,
distanceFunction.rightIsBetter,
distanceFunction.nearTargetTopIsBetter
]
}
];
break;
case 'right':
priorities = [
{
group: internalGroups[2].concat(internalGroups[5])
.concat(internalGroups[8]),
distance: [
distanceFunction.nearPlumbLineIsBetter,
distanceFunction.topIsBetter
]
},
{
group: groups[5],
distance: [
distanceFunction.nearPlumbLineIsBetter,
distanceFunction.topIsBetter
]
},
{
group: groups[2].concat(groups[8]),
distance: [
distanceFunction.nearHorizonIsBetter,
distanceFunction.leftIsBetter,
distanceFunction.nearTargetTopIsBetter
]
}
];
break;
case 'up':
priorities = [
{
group: internalGroups[0].concat(internalGroups[1])
.concat(internalGroups[2]),
distance: [
distanceFunction.nearHorizonIsBetter,
distanceFunction.leftIsBetter
]
},
{
group: groups[1],
distance: [
distanceFunction.nearHorizonIsBetter,
distanceFunction.leftIsBetter
]
},
{
group: groups[0].concat(groups[2]),
distance: [
distanceFunction.nearPlumbLineIsBetter,
distanceFunction.bottomIsBetter,
distanceFunction.nearTargetLeftIsBetter
]
}
];
break;
case 'down':
priorities = [
{
group: internalGroups[6].concat(internalGroups[7])
.concat(internalGroups[8]),
distance: [
distanceFunction.nearHorizonIsBetter,
distanceFunction.leftIsBetter
]
},
{
group: groups[7],
distance: [
distanceFunction.nearHorizonIsBetter,
distanceFunction.leftIsBetter
]
},
{
group: groups[6].concat(groups[8]),
distance: [
distanceFunction.nearPlumbLineIsBetter,
distanceFunction.topIsBetter,
distanceFunction.nearTargetLeftIsBetter
]
}
];
break;
default:
return null;
}
if (this.straightOnly) {
// Ignore candidates in oblique direction.
priorities.pop();
}
var dest = this._prioritize(priorities, target, direction);
if (!dest) {
return null;
}
return dest.element;
}
};
var Navigator = new SpatialNavigator();
+625
View File
@@ -0,0 +1,625 @@
/* Notify.js - http://notifyjs.com/ Copyright (c) 2015 MIT */
(function (factory) {
// UMD start
// https://github.com/umdjs/umd/blob/master/jqueryPluginCommonjs.js
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = function( root, jQuery ) {
if ( jQuery === undefined ) {
// require('jQuery') returns a factory that requires window to
// build a jQuery instance, we normalize how we use modules
// that require this pattern but the window provided is a noop
// if it's defined (how jquery works)
if ( typeof window !== 'undefined' ) {
jQuery = require('jquery');
}
else {
jQuery = require('jquery')(root);
}
}
factory(jQuery);
return jQuery;
};
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
//IE8 indexOf polyfill
var indexOf = [].indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (i in this && this[i] === item) {
return i;
}
}
return -1;
};
var pluginName = "notify";
var pluginClassName = pluginName + "js";
var blankFieldName = pluginName + "!blank";
var positions = {
t: "top",
m: "middle",
b: "bottom",
l: "left",
c: "center",
r: "right"
};
var hAligns = ["l", "c", "r"];
var vAligns = ["t", "m", "b"];
var mainPositions = ["t", "b", "l", "r"];
var opposites = {
t: "b",
m: null,
b: "t",
l: "r",
c: null,
r: "l"
};
var parsePosition = function(str) {
var pos;
pos = [];
$.each(str.split(/\W+/), function(i, word) {
var w;
w = word.toLowerCase().charAt(0);
if (positions[w]) {
return pos.push(w);
}
});
return pos;
};
var styles = {};
var coreStyle = {
name: "core",
html: "<div class=\"" + pluginClassName + "-wrapper\">\n <div class=\"" + pluginClassName + "-arrow\"></div>\n <div class=\"" + pluginClassName + "-container\"></div>\n</div>",
css: "." + pluginClassName + "-corner {\n position: fixed;\n margin: 5px;\n z-index: 1050;\n}\n\n." + pluginClassName + "-corner ." + pluginClassName + "-wrapper,\n." + pluginClassName + "-corner ." + pluginClassName + "-container {\n position: relative;\n display: block;\n height: inherit;\n width: inherit;\n margin: 3px;\n}\n\n." + pluginClassName + "-wrapper {\n z-index: 1;\n position: absolute;\n display: inline-block;\n height: 0;\n width: 0;\n}\n\n." + pluginClassName + "-container {\n display: none;\n z-index: 1;\n position: absolute;\n}\n\n." + pluginClassName + "-hidable {\n cursor: pointer;\n}\n\n[data-notify-text],[data-notify-html] {\n position: relative;\n}\n\n." + pluginClassName + "-arrow {\n position: absolute;\n z-index: 2;\n width: 0;\n height: 0;\n}"
};
var stylePrefixes = {
"border-radius": ["-webkit-", "-moz-"]
};
var getStyle = function(name) {
return styles[name];
};
var removeStyle = function(name) {
if (!name) {
throw "Missing Style name";
}
if (styles[name]) {
delete styles[name];
}
};
var addStyle = function(name, def) {
if (!name) {
throw "Missing Style name";
}
if (!def) {
throw "Missing Style definition";
}
if (!def.html) {
throw "Missing Style HTML";
}
//remove existing style
var existing = styles[name];
if (existing && existing.cssElem) {
if (window.console) {
console.warn(pluginName + ": overwriting style '" + name + "'");
}
styles[name].cssElem.remove();
}
def.name = name;
styles[name] = def;
var cssText = "";
if (def.classes) {
$.each(def.classes, function(className, props) {
cssText += "." + pluginClassName + "-" + def.name + "-" + className + " {\n";
$.each(props, function(name, val) {
if (stylePrefixes[name]) {
$.each(stylePrefixes[name], function(i, prefix) {
return cssText += " " + prefix + name + ": " + val + ";\n";
});
}
return cssText += " " + name + ": " + val + ";\n";
});
return cssText += "}\n";
});
}
if (def.css) {
cssText += "/* styles for " + def.name + " */\n" + def.css;
}
if (cssText) {
def.cssElem = insertCSS(cssText);
def.cssElem.attr("id", "notify-" + def.name);
}
var fields = {};
var elem = $(def.html);
findFields("html", elem, fields);
findFields("text", elem, fields);
def.fields = fields;
};
var insertCSS = function(cssText) {
var e, elem, error;
elem = createElem("style");
elem.attr("type", 'text/css');
$("head").append(elem);
try {
elem.html(cssText);
} catch (_) {
elem[0].styleSheet.cssText = cssText;
}
return elem;
};
var findFields = function(type, elem, fields) {
var attr;
if (type !== "html") {
type = "text";
}
attr = "data-notify-" + type;
return find(elem, "[" + attr + "]").each(function() {
var name;
name = $(this).attr(attr);
if (!name) {
name = blankFieldName;
}
fields[name] = type;
});
};
var find = function(elem, selector) {
if (elem.is(selector)) {
return elem;
} else {
return elem.find(selector);
}
};
var pluginOptions = {
clickToHide: true,
autoHide: true,
autoHideDelay: 5000,
arrowShow: true,
arrowSize: 5,
breakNewLines: true,
elementPosition: "bottom",
globalPosition: "top right",
style: "bootstrap",
className: "error",
showAnimation: "slideDown",
showDuration: 400,
hideAnimation: "slideUp",
hideDuration: 200,
gap: 5
};
var inherit = function(a, b) {
var F;
F = function() {};
F.prototype = a;
return $.extend(true, new F(), b);
};
var defaults = function(opts) {
return $.extend(pluginOptions, opts);
};
var createElem = function(tag) {
return $("<" + tag + "></" + tag + ">");
};
var globalAnchors = {};
var getAnchorElement = function(element) {
var radios;
if (element.is('[type=radio]')) {
radios = element.parents('form:first').find('[type=radio]').filter(function(i, e) {
return $(e).attr("name") === element.attr("name");
});
element = radios.first();
}
return element;
};
var incr = function(obj, pos, val) {
var opp, temp;
if (typeof val === "string") {
val = parseInt(val, 10);
} else if (typeof val !== "number") {
return;
}
if (isNaN(val)) {
return;
}
opp = positions[opposites[pos.charAt(0)]];
temp = pos;
if (obj[opp] !== undefined) {
pos = positions[opp.charAt(0)];
val = -val;
}
if (obj[pos] === undefined) {
obj[pos] = val;
} else {
obj[pos] += val;
}
return null;
};
var realign = function(alignment, inner, outer) {
if (alignment === "l" || alignment === "t") {
return 0;
} else if (alignment === "c" || alignment === "m") {
return outer / 2 - inner / 2;
} else if (alignment === "r" || alignment === "b") {
return outer - inner;
}
throw "Invalid alignment";
};
var encode = function(text) {
encode.e = encode.e || createElem("div");
return encode.e.text(text).html();
};
function Notification(elem, data, options) {
if (typeof options === "string") {
options = {
className: options
};
}
this.options = inherit(pluginOptions, $.isPlainObject(options) ? options : {});
this.loadHTML();
this.wrapper = $(coreStyle.html);
if (this.options.clickToHide) {
this.wrapper.addClass(pluginClassName + "-hidable");
}
this.wrapper.data(pluginClassName, this);
this.arrow = this.wrapper.find("." + pluginClassName + "-arrow");
this.container = this.wrapper.find("." + pluginClassName + "-container");
this.container.append(this.userContainer);
if (elem && elem.length) {
this.elementType = elem.attr("type");
this.originalElement = elem;
this.elem = getAnchorElement(elem);
this.elem.data(pluginClassName, this);
this.elem.before(this.wrapper);
}
this.container.hide();
this.run(data);
}
Notification.prototype.loadHTML = function() {
var style;
style = this.getStyle();
this.userContainer = $(style.html);
this.userFields = style.fields;
};
Notification.prototype.show = function(show, userCallback) {
var args, callback, elems, fn, hidden;
callback = (function(_this) {
return function() {
if (!show && !_this.elem) {
_this.destroy();
}
if (userCallback) {
return userCallback();
}
};
})(this);
hidden = this.container.parent().parents(':hidden').length > 0;
elems = this.container.add(this.arrow);
args = [];
if (hidden && show) {
fn = "show";
} else if (hidden && !show) {
fn = "hide";
} else if (!hidden && show) {
fn = this.options.showAnimation;
args.push(this.options.showDuration);
} else if (!hidden && !show) {
fn = this.options.hideAnimation;
args.push(this.options.hideDuration);
} else {
return callback();
}
args.push(callback);
return elems[fn].apply(elems, args);
};
Notification.prototype.setGlobalPosition = function() {
var p = this.getPosition();
var pMain = p[0];
var pAlign = p[1];
var main = positions[pMain];
var align = positions[pAlign];
var key = pMain + "|" + pAlign;
var anchor = globalAnchors[key];
if (!anchor || !document.body.contains(anchor[0])) {
anchor = globalAnchors[key] = createElem("div");
var css = {};
css[main] = 0;
if (align === "middle") {
css.top = '45%';
} else if (align === "center") {
css.left = '45%';
} else {
css[align] = 0;
}
anchor.css(css).addClass(pluginClassName + "-corner");
$("body").append(anchor);
}
return anchor.prepend(this.wrapper);
};
Notification.prototype.setElementPosition = function() {
var arrowColor, arrowCss, arrowSize, color, contH, contW, css, elemH, elemIH, elemIW, elemPos, elemW, gap, j, k, len, len1, mainFull, margin, opp, oppFull, pAlign, pArrow, pMain, pos, posFull, position, ref, wrapPos;
position = this.getPosition();
pMain = position[0];
pAlign = position[1];
pArrow = position[2];
elemPos = this.elem.position();
elemH = this.elem.outerHeight();
elemW = this.elem.outerWidth();
elemIH = this.elem.innerHeight();
elemIW = this.elem.innerWidth();
wrapPos = this.wrapper.position();
contH = this.container.height();
contW = this.container.width();
mainFull = positions[pMain];
opp = opposites[pMain];
oppFull = positions[opp];
css = {};
css[oppFull] = pMain === "b" ? elemH : pMain === "r" ? elemW : 0;
incr(css, "top", elemPos.top - wrapPos.top);
incr(css, "left", elemPos.left - wrapPos.left);
ref = ["top", "left"];
for (j = 0, len = ref.length; j < len; j++) {
pos = ref[j];
margin = parseInt(this.elem.css("margin-" + pos), 10);
if (margin) {
incr(css, pos, margin);
}
}
gap = Math.max(0, this.options.gap - (this.options.arrowShow ? arrowSize : 0));
incr(css, oppFull, gap);
if (!this.options.arrowShow) {
this.arrow.hide();
} else {
arrowSize = this.options.arrowSize;
arrowCss = $.extend({}, css);
arrowColor = this.userContainer.css("border-color") || this.userContainer.css("border-top-color") || this.userContainer.css("background-color") || "white";
for (k = 0, len1 = mainPositions.length; k < len1; k++) {
pos = mainPositions[k];
posFull = positions[pos];
if (pos === opp) {
continue;
}
color = posFull === mainFull ? arrowColor : "transparent";
arrowCss["border-" + posFull] = arrowSize + "px solid " + color;
}
incr(css, positions[opp], arrowSize);
if (indexOf.call(mainPositions, pAlign) >= 0) {
incr(arrowCss, positions[pAlign], arrowSize * 2);
}
}
if (indexOf.call(vAligns, pMain) >= 0) {
incr(css, "left", realign(pAlign, contW, elemW));
if (arrowCss) {
incr(arrowCss, "left", realign(pAlign, arrowSize, elemIW));
}
} else if (indexOf.call(hAligns, pMain) >= 0) {
incr(css, "top", realign(pAlign, contH, elemH));
if (arrowCss) {
incr(arrowCss, "top", realign(pAlign, arrowSize, elemIH));
}
}
if (this.container.is(":visible")) {
css.display = "block";
}
this.container.removeAttr("style").css(css);
if (arrowCss) {
return this.arrow.removeAttr("style").css(arrowCss);
}
};
Notification.prototype.getPosition = function() {
var pos, ref, ref1, ref2, ref3, ref4, ref5, text;
text = this.options.position || (this.elem ? this.options.elementPosition : this.options.globalPosition);
pos = parsePosition(text);
if (pos.length === 0) {
pos[0] = "b";
}
if (ref = pos[0], indexOf.call(mainPositions, ref) < 0) {
throw "Must be one of [" + mainPositions + "]";
}
if (pos.length === 1 || ((ref1 = pos[0], indexOf.call(vAligns, ref1) >= 0) && (ref2 = pos[1], indexOf.call(hAligns, ref2) < 0)) || ((ref3 = pos[0], indexOf.call(hAligns, ref3) >= 0) && (ref4 = pos[1], indexOf.call(vAligns, ref4) < 0))) {
pos[1] = (ref5 = pos[0], indexOf.call(hAligns, ref5) >= 0) ? "m" : "l";
}
if (pos.length === 2) {
pos[2] = pos[1];
}
return pos;
};
Notification.prototype.getStyle = function(name) {
var style;
if (!name) {
name = this.options.style;
}
if (!name) {
name = "default";
}
style = styles[name];
if (!style) {
throw "Missing style: " + name;
}
return style;
};
Notification.prototype.updateClasses = function() {
var classes, style;
classes = ["base"];
if ($.isArray(this.options.className)) {
classes = classes.concat(this.options.className);
} else if (this.options.className) {
classes.push(this.options.className);
}
style = this.getStyle();
classes = $.map(classes, function(n) {
return pluginClassName + "-" + style.name + "-" + n;
}).join(" ");
return this.userContainer.attr("class", classes);
};
Notification.prototype.run = function(data, options) {
var d, datas, name, type, value;
if ($.isPlainObject(options)) {
$.extend(this.options, options);
} else if ($.type(options) === "string") {
this.options.className = options;
}
if (this.container && !data) {
this.show(false);
return;
} else if (!this.container && !data) {
return;
}
datas = {};
if ($.isPlainObject(data)) {
datas = data;
} else {
datas[blankFieldName] = data;
}
for (name in datas) {
d = datas[name];
type = this.userFields[name];
if (!type) {
continue;
}
if (type === "text") {
d = encode(d);
if (this.options.breakNewLines) {
d = d.replace(/\n/g, '<br/>');
}
}
value = name === blankFieldName ? '' : '=' + name;
find(this.userContainer, "[data-notify-" + type + value + "]").html(d);
}
this.updateClasses();
if (this.elem) {
this.setElementPosition();
} else {
this.setGlobalPosition();
}
this.show(true);
if (this.options.autoHide) {
clearTimeout(this.autohideTimer);
this.autohideTimer = setTimeout(this.show.bind(this, false), this.options.autoHideDelay);
}
};
Notification.prototype.destroy = function() {
this.wrapper.data(pluginClassName, null);
this.wrapper.remove();
};
$[pluginName] = function(elem, data, options) {
if ((elem && elem.nodeName) || elem.jquery) {
$(elem)[pluginName](data, options);
} else {
options = data;
data = elem;
new Notification(null, data, options);
}
return elem;
};
$.fn[pluginName] = function(data, options) {
$(this).each(function() {
var prev = getAnchorElement($(this)).data(pluginClassName);
if (prev) {
prev.destroy();
}
var curr = new Notification($(this), data, options);
});
return this;
};
$.extend($[pluginName], {
defaults: defaults,
addStyle: addStyle,
removeStyle: removeStyle,
pluginOptions: pluginOptions,
getStyle: getStyle,
insertCSS: insertCSS
});
//always include the default bootstrap style
addStyle("bootstrap", {
html: "<div>\n<span data-notify-text></span>\n</div>",
classes: {
base: {
"font-weight": "bold",
"padding": "8px 15px 8px 14px",
"text-shadow": "0 1px 0 rgba(255, 255, 255, 0.5)",
"background-color": "#fcf8e3",
"border": "1px solid #fbeed5",
"border-radius": "4px",
"white-space": "nowrap",
"padding-left": "25px",
"background-repeat": "no-repeat",
"background-position": "3px 7px"
},
error: {
"color": "#B94A48",
"background-color": "#F2DEDE",
"border-color": "#EED3D7",
"background-image": "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtRJREFUeNqkVc1u00AQHq+dOD+0poIQfkIjalW0SEGqRMuRnHos3DjwAH0ArlyQeANOOSMeAA5VjyBxKBQhgSpVUKKQNGloFdw4cWw2jtfMOna6JOUArDTazXi/b3dm55socPqQhFka++aHBsI8GsopRJERNFlY88FCEk9Yiwf8RhgRyaHFQpPHCDmZG5oX2ui2yilkcTT1AcDsbYC1NMAyOi7zTX2Agx7A9luAl88BauiiQ/cJaZQfIpAlngDcvZZMrl8vFPK5+XktrWlx3/ehZ5r9+t6e+WVnp1pxnNIjgBe4/6dAysQc8dsmHwPcW9C0h3fW1hans1ltwJhy0GxK7XZbUlMp5Ww2eyan6+ft/f2FAqXGK4CvQk5HueFz7D6GOZtIrK+srupdx1GRBBqNBtzc2AiMr7nPplRdKhb1q6q6zjFhrklEFOUutoQ50xcX86ZlqaZpQrfbBdu2R6/G19zX6XSgh6RX5ubyHCM8nqSID6ICrGiZjGYYxojEsiw4PDwMSL5VKsC8Yf4VRYFzMzMaxwjlJSlCyAQ9l0CW44PBADzXhe7xMdi9HtTrdYjFYkDQL0cn4Xdq2/EAE+InCnvADTf2eah4Sx9vExQjkqXT6aAERICMewd/UAp/IeYANM2joxt+q5VI+ieq2i0Wg3l6DNzHwTERPgo1ko7XBXj3vdlsT2F+UuhIhYkp7u7CarkcrFOCtR3H5JiwbAIeImjT/YQKKBtGjRFCU5IUgFRe7fF4cCNVIPMYo3VKqxwjyNAXNepuopyqnld602qVsfRpEkkz+GFL1wPj6ySXBpJtWVa5xlhpcyhBNwpZHmtX8AGgfIExo0ZpzkWVTBGiXCSEaHh62/PoR0p/vHaczxXGnj4bSo+G78lELU80h1uogBwWLf5YlsPmgDEd4M236xjm+8nm4IuE/9u+/PH2JXZfbwz4zw1WbO+SQPpXfwG/BBgAhCNZiSb/pOQAAAAASUVORK5CYII=)"
},
success: {
"color": "#468847",
"background-color": "#DFF0D8",
"border-color": "#D6E9C6",
"background-image": "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAutJREFUeNq0lctPE0Ecx38zu/RFS1EryqtgJFA08YCiMZIAQQ4eRG8eDGdPJiYeTIwHTfwPiAcvXIwXLwoXPaDxkWgQ6islKlJLSQWLUraPLTv7Gme32zoF9KSTfLO7v53vZ3d/M7/fIth+IO6INt2jjoA7bjHCJoAlzCRw59YwHYjBnfMPqAKWQYKjGkfCJqAF0xwZjipQtA3MxeSG87VhOOYegVrUCy7UZM9S6TLIdAamySTclZdYhFhRHloGYg7mgZv1Zzztvgud7V1tbQ2twYA34LJmF4p5dXF1KTufnE+SxeJtuCZNsLDCQU0+RyKTF27Unw101l8e6hns3u0PBalORVVVkcaEKBJDgV3+cGM4tKKmI+ohlIGnygKX00rSBfszz/n2uXv81wd6+rt1orsZCHRdr1Imk2F2Kob3hutSxW8thsd8AXNaln9D7CTfA6O+0UgkMuwVvEFFUbbAcrkcTA8+AtOk8E6KiQiDmMFSDqZItAzEVQviRkdDdaFgPp8HSZKAEAL5Qh7Sq2lIJBJwv2scUqkUnKoZgNhcDKhKg5aH+1IkcouCAdFGAQsuWZYhOjwFHQ96oagWgRoUov1T9kRBEODAwxM2QtEUl+Wp+Ln9VRo6BcMw4ErHRYjH4/B26AlQoQQTRdHWwcd9AH57+UAXddvDD37DmrBBV34WfqiXPl61g+vr6xA9zsGeM9gOdsNXkgpEtTwVvwOklXLKm6+/p5ezwk4B+j6droBs2CsGa/gNs6RIxazl4Tc25mpTgw/apPR1LYlNRFAzgsOxkyXYLIM1V8NMwyAkJSctD1eGVKiq5wWjSPdjmeTkiKvVW4f2YPHWl3GAVq6ymcyCTgovM3FzyRiDe2TaKcEKsLpJvNHjZgPNqEtyi6mZIm4SRFyLMUsONSSdkPeFtY1n0mczoY3BHTLhwPRy9/lzcziCw9ACI+yql0VLzcGAZbYSM5CCSZg1/9oc/nn7+i8N9p/8An4JMADxhH+xHfuiKwAAAABJRU5ErkJggg==)"
},
info: {
"color": "#3A87AD",
"background-color": "#D9EDF7",
"border-color": "#BCE8F1",
"background-image": "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QYFAhkSsdes/QAAA8dJREFUOMvVlGtMW2UYx//POaWHXg6lLaW0ypAtw1UCgbniNOLcVOLmAjHZolOYlxmTGXVZdAnRfXQm+7SoU4mXaOaiZsEpC9FkiQs6Z6bdCnNYruM6KNBw6YWewzl9z+sHImEWv+vz7XmT95f/+3/+7wP814v+efDOV3/SoX3lHAA+6ODeUFfMfjOWMADgdk+eEKz0pF7aQdMAcOKLLjrcVMVX3xdWN29/GhYP7SvnP0cWfS8caSkfHZsPE9Fgnt02JNutQ0QYHB2dDz9/pKX8QjjuO9xUxd/66HdxTeCHZ3rojQObGQBcuNjfplkD3b19Y/6MrimSaKgSMmpGU5WevmE/swa6Oy73tQHA0Rdr2Mmv/6A1n9w9suQ7097Z9lM4FlTgTDrzZTu4StXVfpiI48rVcUDM5cmEksrFnHxfpTtU/3BFQzCQF/2bYVoNbH7zmItbSoMj40JSzmMyX5qDvriA7QdrIIpA+3cdsMpu0nXI8cV0MtKXCPZev+gCEM1S2NHPvWfP/hL+7FSr3+0p5RBEyhEN5JCKYr8XnASMT0xBNyzQGQeI8fjsGD39RMPk7se2bd5ZtTyoFYXftF6y37gx7NeUtJJOTFlAHDZLDuILU3j3+H5oOrD3yWbIztugaAzgnBKJuBLpGfQrS8wO4FZgV+c1IxaLgWVU0tMLEETCos4xMzEIv9cJXQcyagIwigDGwJgOAtHAwAhisQUjy0ORGERiELgG4iakkzo4MYAxcM5hAMi1WWG1yYCJIcMUaBkVRLdGeSU2995TLWzcUAzONJ7J6FBVBYIggMzmFbvdBV44Corg8vjhzC+EJEl8U1kJtgYrhCzgc/vvTwXKSib1paRFVRVORDAJAsw5FuTaJEhWM2SHB3mOAlhkNxwuLzeJsGwqWzf5TFNdKgtY5qHp6ZFf67Y/sAVadCaVY5YACDDb3Oi4NIjLnWMw2QthCBIsVhsUTU9tvXsjeq9+X1d75/KEs4LNOfcdf/+HthMnvwxOD0wmHaXr7ZItn2wuH2SnBzbZAbPJwpPx+VQuzcm7dgRCB57a1uBzUDRL4bfnI0RE0eaXd9W89mpjqHZnUI5Hh2l2dkZZUhOqpi2qSmpOmZ64Tuu9qlz/SEXo6MEHa3wOip46F1n7633eekV8ds8Wxjn37Wl63VVa+ej5oeEZ/82ZBETJjpJ1Rbij2D3Z/1trXUvLsblCK0XfOx0SX2kMsn9dX+d+7Kf6h8o4AIykuffjT8L20LU+w4AZd5VvEPY+XpWqLV327HR7DzXuDnD8r+ovkBehJ8i+y8YAAAAASUVORK5CYII=)"
},
warn: {
"color": "#C09853",
"background-color": "#FCF8E3",
"border-color": "#FBEED5",
"background-image": "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABJlBMVEXr6eb/2oD/wi7/xjr/0mP/ykf/tQD/vBj/3o7/uQ//vyL/twebhgD/4pzX1K3z8e349vK6tHCilCWbiQymn0jGworr6dXQza3HxcKkn1vWvV/5uRfk4dXZ1bD18+/52YebiAmyr5S9mhCzrWq5t6ufjRH54aLs0oS+qD751XqPhAybhwXsujG3sm+Zk0PTwG6Shg+PhhObhwOPgQL4zV2nlyrf27uLfgCPhRHu7OmLgAafkyiWkD3l49ibiAfTs0C+lgCniwD4sgDJxqOilzDWowWFfAH08uebig6qpFHBvH/aw26FfQTQzsvy8OyEfz20r3jAvaKbhgG9q0nc2LbZxXanoUu/u5WSggCtp1anpJKdmFz/zlX/1nGJiYmuq5Dx7+sAAADoPUZSAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfdBgUBGhh4aah5AAAAlklEQVQY02NgoBIIE8EUcwn1FkIXM1Tj5dDUQhPU502Mi7XXQxGz5uVIjGOJUUUW81HnYEyMi2HVcUOICQZzMMYmxrEyMylJwgUt5BljWRLjmJm4pI1hYp5SQLGYxDgmLnZOVxuooClIDKgXKMbN5ggV1ACLJcaBxNgcoiGCBiZwdWxOETBDrTyEFey0jYJ4eHjMGWgEAIpRFRCUt08qAAAAAElFTkSuQmCC)"
}
}
});
$(function() {
insertCSS(coreStyle.css).attr("id", "core-notify");
$(document).on("click", "." + pluginClassName + "-hidable", function(e) {
$(this).trigger("notify-hide");
});
$(document).on("notify-hide", "." + pluginClassName + "-wrapper", function(e) {
var elem = $(this).data(pluginClassName);
if(elem) {
elem.show(false);
}
});
});
}));
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,791 @@
/*************** SCROLLBAR BASE CSS ***************/
.scroll-wrapper {
overflow: hidden !important;
padding: 0 !important;
position: relative;
}
.scroll-wrapper > .scroll-content {
border: none !important;
box-sizing: content-box !important;
height: auto;
left: 0;
margin: 0;
max-height: none;
max-width: none !important;
overflow: scroll !important;
padding: 0;
position: relative !important;
top: 0;
width: auto !important;
}
.scroll-wrapper > .scroll-content::-webkit-scrollbar {
height: 0;
width: 0;
}
.scroll-element {
display: none;
}
.scroll-element, .scroll-element div {
box-sizing: content-box;
}
.scroll-element.scroll-x.scroll-scrollx_visible,
.scroll-element.scroll-y.scroll-scrolly_visible {
display: block;
}
.scroll-element .scroll-bar,
.scroll-element .scroll-arrow {
cursor: default;
}
.scroll-textarea {
border: 1px solid #cccccc;
border-top-color: #999999;
}
.scroll-textarea > .scroll-content {
overflow: hidden !important;
}
.scroll-textarea > .scroll-content > textarea {
border: none !important;
box-sizing: border-box;
height: 100% !important;
margin: 0;
max-height: none !important;
max-width: none !important;
overflow: scroll !important;
outline: none;
padding: 2px;
position: relative !important;
top: 0;
width: 100% !important;
}
.scroll-textarea > .scroll-content > textarea::-webkit-scrollbar {
height: 0;
width: 0;
}
/*************** SIMPLE INNER SCROLLBAR ***************/
.scrollbar-inner > .scroll-element,
.scrollbar-inner > .scroll-element div
{
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-inner > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-inner > .scroll-element.scroll-x {
bottom: 2px;
height: 8px;
left: 0;
width: 100%;
}
.scrollbar-inner > .scroll-element.scroll-y {
height: 100%;
right: 2px;
top: 0;
width: 8px;
}
.scrollbar-inner > .scroll-element .scroll-element_outer {
overflow: hidden;
}
.scrollbar-inner > .scroll-element .scroll-element_outer,
.scrollbar-inner > .scroll-element .scroll-element_track,
.scrollbar-inner > .scroll-element .scroll-bar {
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.scrollbar-inner > .scroll-element .scroll-element_track,
.scrollbar-inner > .scroll-element .scroll-bar {
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
filter: alpha(opacity=40);
opacity: 0.4;
}
.scrollbar-inner > .scroll-element .scroll-element_track { background-color: #e0e0e0; }
.scrollbar-inner > .scroll-element .scroll-bar { background-color: #c2c2c2; }
.scrollbar-inner > .scroll-element:hover .scroll-bar { background-color: #919191; }
.scrollbar-inner > .scroll-element.scroll-draggable .scroll-bar { background-color: #919191; }
/* update scrollbar offset if both scrolls are visible */
.scrollbar-inner > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track { left: -12px; }
.scrollbar-inner > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track { top: -12px; }
.scrollbar-inner > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size { left: -12px; }
.scrollbar-inner > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size { top: -12px; }
/*************** SIMPLE OUTER SCROLLBAR ***************/
.scrollbar-outer > .scroll-element,
.scrollbar-outer > .scroll-element div
{
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-outer > .scroll-element {
background-color: #ffffff;
}
.scrollbar-outer > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-outer > .scroll-element.scroll-x {
bottom: 0;
height: 12px;
left: 0;
width: 100%;
}
.scrollbar-outer > .scroll-element.scroll-y {
height: 100%;
right: 0;
top: 0;
width: 12px;
}
.scrollbar-outer > .scroll-element.scroll-x .scroll-element_outer { height: 8px; top: 2px; }
.scrollbar-outer > .scroll-element.scroll-y .scroll-element_outer { left: 2px; width: 8px; }
.scrollbar-outer > .scroll-element .scroll-element_outer { overflow: hidden; }
.scrollbar-outer > .scroll-element .scroll-element_track { background-color: #eeeeee; }
.scrollbar-outer > .scroll-element .scroll-element_outer,
.scrollbar-outer > .scroll-element .scroll-element_track,
.scrollbar-outer > .scroll-element .scroll-bar {
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.scrollbar-outer > .scroll-element .scroll-bar { background-color: #d9d9d9; }
.scrollbar-outer > .scroll-element .scroll-bar:hover { background-color: #c2c2c2; }
.scrollbar-outer > .scroll-element.scroll-draggable .scroll-bar { background-color: #919191; }
/* scrollbar height/width & offset from container borders */
.scrollbar-outer > .scroll-content.scroll-scrolly_visible { left: -12px; margin-left: 12px; }
.scrollbar-outer > .scroll-content.scroll-scrollx_visible { top: -12px; margin-top: 12px; }
.scrollbar-outer > .scroll-element.scroll-x .scroll-bar { min-width: 10px; }
.scrollbar-outer > .scroll-element.scroll-y .scroll-bar { min-height: 10px; }
/* update scrollbar offset if both scrolls are visible */
.scrollbar-outer > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track { left: -14px; }
.scrollbar-outer > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track { top: -14px; }
.scrollbar-outer > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size { left: -14px; }
.scrollbar-outer > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size { top: -14px; }
/*************** SCROLLBAR MAC OS X ***************/
.scrollbar-macosx > .scroll-element,
.scrollbar-macosx > .scroll-element div
{
background: none;
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-macosx > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-macosx > .scroll-element .scroll-element_track { display: none; }
.scrollbar-macosx > .scroll-element .scroll-bar {
background-color: #6C6E71;
display: block;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity: 0;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
-ms-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.scrollbar-macosx:hover > .scroll-element .scroll-bar,
.scrollbar-macosx > .scroll-element.scroll-draggable .scroll-bar {
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
filter: alpha(opacity=70);
opacity: 0.7;
}
.scrollbar-macosx > .scroll-element.scroll-x {
bottom: 0px;
height: 0px;
left: 0;
min-width: 100%;
overflow: visible;
width: 100%;
}
.scrollbar-macosx > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 0px;
top: 0;
width: 0px;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-macosx > .scroll-element.scroll-x .scroll-bar { height: 7px; min-width: 10px; top: -9px; }
.scrollbar-macosx > .scroll-element.scroll-y .scroll-bar { left: -9px; min-height: 10px; width: 7px; }
.scrollbar-macosx > .scroll-element.scroll-x .scroll-element_outer { left: 2px; }
.scrollbar-macosx > .scroll-element.scroll-x .scroll-element_size { left: -4px; }
.scrollbar-macosx > .scroll-element.scroll-y .scroll-element_outer { top: 2px; }
.scrollbar-macosx > .scroll-element.scroll-y .scroll-element_size { top: -4px; }
/* update scrollbar offset if both scrolls are visible */
.scrollbar-macosx > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size { left: -11px; }
.scrollbar-macosx > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size { top: -11px; }
/*************** SCROLLBAR LIGHT ***************/
.scrollbar-light > .scroll-element,
.scrollbar-light > .scroll-element div {
border: none;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-light > .scroll-element {
background-color: #ffffff;
}
.scrollbar-light > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-light > .scroll-element .scroll-element_outer {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
.scrollbar-light > .scroll-element .scroll-element_size {
background: #dbdbdb;
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RiZGJkYiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlOGU4ZTgiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+');
background: -moz-linear-gradient(left, #dbdbdb 0%, #e8e8e8 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%,#dbdbdb), color-stop(100%,#e8e8e8));
background: -webkit-linear-gradient(left, #dbdbdb 0%,#e8e8e8 100%);
background: -o-linear-gradient(left, #dbdbdb 0%,#e8e8e8 100%);
background: -ms-linear-gradient(left, #dbdbdb 0%,#e8e8e8 100%);
background: linear-gradient(to right, #dbdbdb 0%,#e8e8e8 100%);
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
.scrollbar-light > .scroll-element.scroll-x {
bottom: 0;
height: 17px;
left: 0;
min-width: 100%;
width: 100%;
}
.scrollbar-light > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 0;
top: 0;
width: 17px;
}
.scrollbar-light > .scroll-element .scroll-bar {
background: #fefefe;
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZlZmVmZSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmNWY1ZjUiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+');
background: -moz-linear-gradient(left, #fefefe 0%, #f5f5f5 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%,#fefefe), color-stop(100%,#f5f5f5));
background: -webkit-linear-gradient(left, #fefefe 0%,#f5f5f5 100%);
background: -o-linear-gradient(left, #fefefe 0%,#f5f5f5 100%);
background: -ms-linear-gradient(left, #fefefe 0%,#f5f5f5 100%);
background: linear-gradient(to right, #fefefe 0%,#f5f5f5 100%);
border: 1px solid #dbdbdb;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-light > .scroll-content.scroll-scrolly_visible { left: -17px; margin-left: 17px; }
.scrollbar-light > .scroll-content.scroll-scrollx_visible { top: -17px; margin-top: 17px; }
.scrollbar-light > .scroll-element.scroll-x .scroll-bar { height: 10px; min-width: 10px; top: 0px; }
.scrollbar-light > .scroll-element.scroll-y .scroll-bar { left: 0px; min-height: 10px; width: 10px; }
.scrollbar-light > .scroll-element.scroll-x .scroll-element_outer { height: 12px; left: 2px; top: 2px; }
.scrollbar-light > .scroll-element.scroll-x .scroll-element_size { left: -4px; }
.scrollbar-light > .scroll-element.scroll-y .scroll-element_outer { left: 2px; top: 2px; width: 12px; }
.scrollbar-light > .scroll-element.scroll-y .scroll-element_size { top: -4px; }
/* update scrollbar offset if both scrolls are visible */
.scrollbar-light > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size { left: -19px; }
.scrollbar-light > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size { top: -19px; }
.scrollbar-light > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track { left: -19px; }
.scrollbar-light > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track { top: -19px; }
/*************** SCROLLBAR RAIL ***************/
.scrollbar-rail > .scroll-element,
.scrollbar-rail > .scroll-element div
{
border: none;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-rail > .scroll-element {
background-color: #ffffff;
}
.scrollbar-rail > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-rail > .scroll-element .scroll-element_size {
background-color: #999;
background-color: rgba(0, 0, 0, 0.3);
}
.scrollbar-rail > .scroll-element .scroll-element_outer:hover .scroll-element_size {
background-color: #666;
background-color: rgba(0, 0, 0, 0.5);
}
.scrollbar-rail > .scroll-element.scroll-x {
bottom: 0;
height: 12px;
left: 0;
min-width: 100%;
padding: 3px 0 2px;
width: 100%;
}
.scrollbar-rail > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
padding: 0 2px 0 3px;
right: 0;
top: 0;
width: 12px;
}
.scrollbar-rail > .scroll-element .scroll-bar {
background-color: #d0b9a0;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
}
.scrollbar-rail > .scroll-element .scroll-element_outer:hover .scroll-bar {
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
}
/* scrollbar height/width & offset from container borders */
.scrollbar-rail > .scroll-content.scroll-scrolly_visible { left: -17px; margin-left: 17px; }
.scrollbar-rail > .scroll-content.scroll-scrollx_visible { margin-top: 17px; top: -17px; }
.scrollbar-rail > .scroll-element.scroll-x .scroll-bar { height: 10px; min-width: 10px; top: 1px; }
.scrollbar-rail > .scroll-element.scroll-y .scroll-bar { left: 1px; min-height: 10px; width: 10px; }
.scrollbar-rail > .scroll-element.scroll-x .scroll-element_outer { height: 15px; left: 5px; }
.scrollbar-rail > .scroll-element.scroll-x .scroll-element_size { height: 2px; left: -10px; top: 5px; }
.scrollbar-rail > .scroll-element.scroll-y .scroll-element_outer { top: 5px; width: 15px; }
.scrollbar-rail > .scroll-element.scroll-y .scroll-element_size { left: 5px; top: -10px; width: 2px; }
/* update scrollbar offset if both scrolls are visible */
.scrollbar-rail > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size { left: -25px; }
.scrollbar-rail > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size { top: -25px; }
.scrollbar-rail > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track { left: -25px; }
.scrollbar-rail > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track { top: -25px; }
/*************** SCROLLBAR DYNAMIC ***************/
.scrollbar-dynamic > .scroll-element,
.scrollbar-dynamic > .scroll-element div
{
background: none;
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-dynamic > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-dynamic > .scroll-element.scroll-x {
bottom: 2px;
height: 7px;
left: 0;
min-width: 100%;
width: 100%;
}
.scrollbar-dynamic > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 2px;
top: 0;
width: 7px;
}
.scrollbar-dynamic > .scroll-element .scroll-element_outer {
opacity: 0.3;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
}
.scrollbar-dynamic > .scroll-element .scroll-element_size {
background-color: #cccccc;
opacity: 0;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
-webkit-transition: opacity 0.2s;
-moz-transition: opacity 0.2s;
-o-transition: opacity 0.2s;
-ms-transition: opacity 0.2s;
transition: opacity 0.2s;
}
.scrollbar-dynamic > .scroll-element .scroll-bar {
background-color: #6c6e71;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-dynamic > .scroll-element.scroll-x .scroll-bar {
bottom: 0;
height: 7px;
min-width: 24px;
top: auto;
}
.scrollbar-dynamic > .scroll-element.scroll-y .scroll-bar {
left: auto;
min-height: 24px;
right: 0;
width: 7px;
}
.scrollbar-dynamic > .scroll-element.scroll-x .scroll-element_outer {
bottom: 0;
top: auto;
left: 2px;
-webkit-transition: height 0.2s;
-moz-transition: height 0.2s;
-o-transition: height 0.2s;
-ms-transition: height 0.2s;
transition: height 0.2s;
}
.scrollbar-dynamic > .scroll-element.scroll-y .scroll-element_outer {
left: auto;
right: 0;
top: 2px;
-webkit-transition: width 0.2s;
-moz-transition: width 0.2s;
-o-transition: width 0.2s;
-ms-transition: width 0.2s;
transition: width 0.2s;
}
.scrollbar-dynamic > .scroll-element.scroll-x .scroll-element_size { left: -4px; }
.scrollbar-dynamic > .scroll-element.scroll-y .scroll-element_size { top: -4px; }
/* update scrollbar offset if both scrolls are visible */
.scrollbar-dynamic > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size { left: -11px; }
.scrollbar-dynamic > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size { top: -11px; }
/* hover & drag */
.scrollbar-dynamic > .scroll-element:hover .scroll-element_outer,
.scrollbar-dynamic > .scroll-element.scroll-draggable .scroll-element_outer {
overflow: hidden;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
filter: alpha(opacity=70);
opacity: 0.7;
}
.scrollbar-dynamic > .scroll-element:hover .scroll-element_outer .scroll-element_size,
.scrollbar-dynamic > .scroll-element.scroll-draggable .scroll-element_outer .scroll-element_size {
opacity: 1;
}
.scrollbar-dynamic > .scroll-element:hover .scroll-element_outer .scroll-bar,
.scrollbar-dynamic > .scroll-element.scroll-draggable .scroll-element_outer .scroll-bar {
height: 100%;
width: 100%;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
}
.scrollbar-dynamic > .scroll-element.scroll-x:hover .scroll-element_outer,
.scrollbar-dynamic > .scroll-element.scroll-x.scroll-draggable .scroll-element_outer {
height: 20px;
min-height: 7px;
}
.scrollbar-dynamic > .scroll-element.scroll-y:hover .scroll-element_outer,
.scrollbar-dynamic > .scroll-element.scroll-y.scroll-draggable .scroll-element_outer {
min-width: 7px;
width: 20px;
}
/*************** SCROLLBAR GOOGLE CHROME ***************/
.scrollbar-chrome > .scroll-element,
.scrollbar-chrome > .scroll-element div
{
border: none;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-chrome > .scroll-element {
background-color: #ffffff;
}
.scrollbar-chrome > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-chrome > .scroll-element .scroll-element_outer {}
.scrollbar-chrome > .scroll-element .scroll-element_track {
background: #f1f1f1;
border: 1px solid #dbdbdb;
}
.scrollbar-chrome > .scroll-element.scroll-x {
bottom: 0;
height: 16px;
left: 0;
min-width: 100%;
width: 100%;
}
.scrollbar-chrome > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 0;
top: 0;
width: 16px;
}
.scrollbar-chrome > .scroll-element .scroll-bar {
background-color: #d9d9d9;
border: 1px solid #bdbdbd;
cursor: default;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
.scrollbar-chrome > .scroll-element .scroll-bar:hover {
background-color: #c2c2c2;
border-color: #a9a9a9;
}
.scrollbar-chrome > .scroll-element.scroll-draggable .scroll-bar {
background-color: #919191;
border-color: #7e7e7e;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-chrome > .scroll-content.scroll-scrolly_visible { left: -16px; margin-left: 16px; }
.scrollbar-chrome > .scroll-content.scroll-scrollx_visible { top: -16px; margin-top: 16px; }
.scrollbar-chrome > .scroll-element.scroll-x .scroll-bar { height: 8px; min-width: 10px; top: 3px; }
.scrollbar-chrome > .scroll-element.scroll-y .scroll-bar { left: 3px; min-height: 10px; width: 8px; }
.scrollbar-chrome > .scroll-element.scroll-x .scroll-element_outer { border-left: 1px solid #dbdbdb; }
.scrollbar-chrome > .scroll-element.scroll-x .scroll-element_track { height: 14px; left: -3px; }
.scrollbar-chrome > .scroll-element.scroll-x .scroll-element_size { height: 14px; left: -4px; }
.scrollbar-chrome > .scroll-element.scroll-y .scroll-element_outer { border-top: 1px solid #dbdbdb; }
.scrollbar-chrome > .scroll-element.scroll-y .scroll-element_track { top: -3px; width: 14px; }
.scrollbar-chrome > .scroll-element.scroll-y .scroll-element_size { top: -4px; width: 14px; }
/* update scrollbar offset if both scrolls are visible */
.scrollbar-chrome > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size { left: -19px; }
.scrollbar-chrome > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size { top: -19px; }
.scrollbar-chrome > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track { left: -19px; }
.scrollbar-chrome > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track { top: -19px; }
@@ -0,0 +1,781 @@
/**
* jQuery CSS Customizable Scrollbar
*
* Copyright 2015, Yuriy Khabarov
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* If you found bug, please contact me via email <13real008@gmail.com>
*
* @author Yuriy Khabarov aka Gromo
* @version 0.2.10
* @url https://github.com/gromo/jquery.scrollbar/
*
*/
;
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else {
factory(root.jQuery);
}
}(this, function ($) {
'use strict';
// init flags & variables
var debug = false;
var browser = {
data: {
index: 0,
name: 'scrollbar'
},
macosx: /mac/i.test(navigator.platform),
mobile: /android|webos|iphone|ipad|ipod|blackberry/i.test(navigator.userAgent),
overlay: null,
scroll: null,
scrolls: [],
webkit: /webkit/i.test(navigator.userAgent) && !/edge\/\d+/i.test(navigator.userAgent)
};
browser.scrolls.add = function (instance) {
this.remove(instance).push(instance);
};
browser.scrolls.remove = function (instance) {
while ($.inArray(instance, this) >= 0) {
this.splice($.inArray(instance, this), 1);
}
return this;
};
var defaults = {
"autoScrollSize": true, // automatically calculate scrollsize
"autoUpdate": true, // update scrollbar if content/container size changed
"debug": false, // debug mode
"disableBodyScroll": false, // disable body scroll if mouse over container
"duration": 200, // scroll animate duration in ms
"ignoreMobile": false, // ignore mobile devices
"ignoreOverlay": false, // ignore browsers with overlay scrollbars (mobile, MacOS)
"scrollStep": 30, // scroll step for scrollbar arrows
"showArrows": false, // add class to show arrows
"stepScrolling": true, // when scrolling to scrollbar mousedown position
"scrollx": null, // horizontal scroll element
"scrolly": null, // vertical scroll element
"onDestroy": null, // callback function on destroy,
"onInit": null, // callback function on first initialization
"onScroll": null, // callback function on content scrolling
"onUpdate": null // callback function on init/resize (before scrollbar size calculation)
};
var BaseScrollbar = function (container) {
if (!browser.scroll) {
browser.overlay = isScrollOverlaysContent();
browser.scroll = getBrowserScrollSize();
updateScrollbars();
$(window).resize(function () {
var forceUpdate = false;
if (browser.scroll && (browser.scroll.height || browser.scroll.width)) {
var scroll = getBrowserScrollSize();
if (scroll.height !== browser.scroll.height || scroll.width !== browser.scroll.width) {
browser.scroll = scroll;
forceUpdate = true; // handle page zoom
}
}
updateScrollbars(forceUpdate);
});
}
this.container = container;
this.namespace = '.scrollbar_' + browser.data.index++;
this.options = $.extend({}, defaults, window.jQueryScrollbarOptions || {});
this.scrollTo = null;
this.scrollx = {};
this.scrolly = {};
container.data(browser.data.name, this);
browser.scrolls.add(this);
};
BaseScrollbar.prototype = {
destroy: function () {
if (!this.wrapper) {
return;
}
this.container.removeData(browser.data.name);
browser.scrolls.remove(this);
// init variables
var scrollLeft = this.container.scrollLeft();
var scrollTop = this.container.scrollTop();
this.container.insertBefore(this.wrapper).css({
"height": "",
"margin": "",
"max-height": ""
})
.removeClass('scroll-content scroll-scrollx_visible scroll-scrolly_visible')
.off(this.namespace)
.scrollLeft(scrollLeft)
.scrollTop(scrollTop);
this.scrollx.scroll.removeClass('scroll-scrollx_visible').find('div').andSelf().off(this.namespace);
this.scrolly.scroll.removeClass('scroll-scrolly_visible').find('div').andSelf().off(this.namespace);
this.wrapper.remove();
$(document).add('body').off(this.namespace);
if ($.isFunction(this.options.onDestroy)){
this.options.onDestroy.apply(this, [this.container]);
}
},
init: function (options) {
// init variables
var S = this,
c = this.container,
cw = this.containerWrapper || c,
namespace = this.namespace,
o = $.extend(this.options, options || {}),
s = {x: this.scrollx, y: this.scrolly},
w = this.wrapper;
var initScroll = {
"scrollLeft": c.scrollLeft(),
"scrollTop": c.scrollTop()
};
// do not init if in ignorable browser
if ((browser.mobile && o.ignoreMobile)
|| (browser.overlay && o.ignoreOverlay)
|| (browser.macosx && !browser.webkit) // still required to ignore nonWebKit browsers on Mac
) {
return false;
}
// init scroll container
if (!w) {
this.wrapper = w = $('<div>').addClass('scroll-wrapper').addClass(c.attr('class'))
.css('position', c.css('position') == 'absolute' ? 'absolute' : 'relative')
.insertBefore(c).append(c);
if (c.is('textarea')) {
this.containerWrapper = cw = $('<div>').insertBefore(c).append(c);
w.addClass('scroll-textarea');
}
cw.addClass('scroll-content').css({
"height": "auto",
"margin-bottom": browser.scroll.height * -1 + 'px',
"margin-right": browser.scroll.width * -1 + 'px',
"max-height": ""
});
c.on('scroll' + namespace, function (event) {
if ($.isFunction(o.onScroll)) {
o.onScroll.call(S, {
"maxScroll": s.y.maxScrollOffset,
"scroll": c.scrollTop(),
"size": s.y.size,
"visible": s.y.visible
}, {
"maxScroll": s.x.maxScrollOffset,
"scroll": c.scrollLeft(),
"size": s.x.size,
"visible": s.x.visible
});
}
s.x.isVisible && s.x.scroll.bar.css('left', c.scrollLeft() * s.x.kx + 'px');
s.y.isVisible && s.y.scroll.bar.css('top', c.scrollTop() * s.y.kx + 'px');
});
/* prevent native scrollbars to be visible on #anchor click */
w.on('scroll' + namespace, function () {
w.scrollTop(0).scrollLeft(0);
});
if (o.disableBodyScroll) {
var handleMouseScroll = function (event) {
isVerticalScroll(event) ?
s.y.isVisible && s.y.mousewheel(event) :
s.x.isVisible && s.x.mousewheel(event);
};
w.on('MozMousePixelScroll' + namespace, handleMouseScroll);
w.on('mousewheel' + namespace, handleMouseScroll);
if (browser.mobile) {
w.on('touchstart' + namespace, function (event) {
var touch = event.originalEvent.touches && event.originalEvent.touches[0] || event;
var originalTouch = {
"pageX": touch.pageX,
"pageY": touch.pageY
};
var originalScroll = {
"left": c.scrollLeft(),
"top": c.scrollTop()
};
$(document).on('touchmove' + namespace, function (event) {
var touch = event.originalEvent.targetTouches && event.originalEvent.targetTouches[0] || event;
c.scrollLeft(originalScroll.left + originalTouch.pageX - touch.pageX);
c.scrollTop(originalScroll.top + originalTouch.pageY - touch.pageY);
event.preventDefault();
});
$(document).on('touchend' + namespace, function () {
$(document).off(namespace);
});
});
}
}
if ($.isFunction(o.onInit)){
o.onInit.apply(this, [c]);
}
} else {
cw.css({
"height": "auto",
"margin-bottom": browser.scroll.height * -1 + 'px',
"margin-right": browser.scroll.width * -1 + 'px',
"max-height": ""
});
}
// init scrollbars & recalculate sizes
$.each(s, function (d, scrollx) {
var scrollCallback = null;
var scrollForward = 1;
var scrollOffset = (d === 'x') ? 'scrollLeft' : 'scrollTop';
var scrollStep = o.scrollStep;
var scrollTo = function () {
var currentOffset = c[scrollOffset]();
c[scrollOffset](currentOffset + scrollStep);
if (scrollForward == 1 && (currentOffset + scrollStep) >= scrollToValue)
currentOffset = c[scrollOffset]();
if (scrollForward == -1 && (currentOffset + scrollStep) <= scrollToValue)
currentOffset = c[scrollOffset]();
if (c[scrollOffset]() == currentOffset && scrollCallback) {
scrollCallback();
}
}
var scrollToValue = 0;
if (!scrollx.scroll) {
scrollx.scroll = S._getScroll(o['scroll' + d]).addClass('scroll-' + d);
if(o.showArrows){
scrollx.scroll.addClass('scroll-element_arrows_visible');
}
scrollx.mousewheel = function (event) {
if (!scrollx.isVisible || (d === 'x' && isVerticalScroll(event))) {
return true;
}
if (d === 'y' && !isVerticalScroll(event)) {
s.x.mousewheel(event);
return true;
}
var delta = event.originalEvent.wheelDelta * -1 || event.originalEvent.detail;
var maxScrollValue = scrollx.size - scrollx.visible - scrollx.offset;
if ((delta > 0 && scrollToValue < maxScrollValue) || (delta < 0 && scrollToValue > 0)) {
scrollToValue = scrollToValue + delta;
if (scrollToValue < 0)
scrollToValue = 0;
if (scrollToValue > maxScrollValue)
scrollToValue = maxScrollValue;
S.scrollTo = S.scrollTo || {};
S.scrollTo[scrollOffset] = scrollToValue;
setTimeout(function () {
if (S.scrollTo) {
c.stop().animate(S.scrollTo, 240, 'linear', function () {
scrollToValue = c[scrollOffset]();
});
S.scrollTo = null;
}
}, 1);
}
event.preventDefault();
return false;
};
scrollx.scroll
.on('MozMousePixelScroll' + namespace, scrollx.mousewheel)
.on('mousewheel' + namespace, scrollx.mousewheel)
.on('mouseenter' + namespace, function () {
scrollToValue = c[scrollOffset]();
});
// handle arrows & scroll inner mousedown event
scrollx.scroll.find('.scroll-arrow, .scroll-element_track')
.on('mousedown' + namespace, function (event) {
if (event.which != 1) // lmb
return true;
scrollForward = 1;
var data = {
"eventOffset": event[(d === 'x') ? 'pageX' : 'pageY'],
"maxScrollValue": scrollx.size - scrollx.visible - scrollx.offset,
"scrollbarOffset": scrollx.scroll.bar.offset()[(d === 'x') ? 'left' : 'top'],
"scrollbarSize": scrollx.scroll.bar[(d === 'x') ? 'outerWidth' : 'outerHeight']()
};
var timeout = 0, timer = 0;
if ($(this).hasClass('scroll-arrow')) {
scrollForward = $(this).hasClass("scroll-arrow_more") ? 1 : -1;
scrollStep = o.scrollStep * scrollForward;
scrollToValue = scrollForward > 0 ? data.maxScrollValue : 0;
} else {
scrollForward = (data.eventOffset > (data.scrollbarOffset + data.scrollbarSize) ? 1
: (data.eventOffset < data.scrollbarOffset ? -1 : 0));
scrollStep = Math.round(scrollx.visible * 0.75) * scrollForward;
scrollToValue = (data.eventOffset - data.scrollbarOffset -
(o.stepScrolling ? (scrollForward == 1 ? data.scrollbarSize : 0)
: Math.round(data.scrollbarSize / 2)));
scrollToValue = c[scrollOffset]() + (scrollToValue / scrollx.kx);
}
S.scrollTo = S.scrollTo || {};
S.scrollTo[scrollOffset] = o.stepScrolling ? c[scrollOffset]() + scrollStep : scrollToValue;
if (o.stepScrolling) {
scrollCallback = function () {
scrollToValue = c[scrollOffset]();
clearInterval(timer);
clearTimeout(timeout);
timeout = 0;
timer = 0;
};
timeout = setTimeout(function () {
timer = setInterval(scrollTo, 40);
}, o.duration + 100);
}
setTimeout(function () {
if (S.scrollTo) {
c.animate(S.scrollTo, o.duration);
S.scrollTo = null;
}
}, 1);
return S._handleMouseDown(scrollCallback, event);
});
// handle scrollbar drag'n'drop
scrollx.scroll.bar.on('mousedown' + namespace, function (event) {
if (event.which != 1) // lmb
return true;
var eventPosition = event[(d === 'x') ? 'pageX' : 'pageY'];
var initOffset = c[scrollOffset]();
scrollx.scroll.addClass('scroll-draggable');
$(document).on('mousemove' + namespace, function (event) {
var diff = parseInt((event[(d === 'x') ? 'pageX' : 'pageY'] - eventPosition) / scrollx.kx, 10);
c[scrollOffset](initOffset + diff);
});
return S._handleMouseDown(function () {
scrollx.scroll.removeClass('scroll-draggable');
scrollToValue = c[scrollOffset]();
}, event);
});
}
});
// remove classes & reset applied styles
$.each(s, function (d, scrollx) {
var scrollClass = 'scroll-scroll' + d + '_visible';
var scrolly = (d == "x") ? s.y : s.x;
scrollx.scroll.removeClass(scrollClass);
scrolly.scroll.removeClass(scrollClass);
cw.removeClass(scrollClass);
});
// calculate init sizes
$.each(s, function (d, scrollx) {
$.extend(scrollx, (d == "x") ? {
"offset": parseInt(c.css('left'), 10) || 0,
"size": c.prop('scrollWidth'),
"visible": w.width()
} : {
"offset": parseInt(c.css('top'), 10) || 0,
"size": c.prop('scrollHeight'),
"visible": w.height()
});
});
// update scrollbar visibility/dimensions
this._updateScroll('x', this.scrollx);
this._updateScroll('y', this.scrolly);
if ($.isFunction(o.onUpdate)){
o.onUpdate.apply(this, [c]);
}
// calculate scroll size
$.each(s, function (d, scrollx) {
var cssOffset = (d === 'x') ? 'left' : 'top';
var cssFullSize = (d === 'x') ? 'outerWidth' : 'outerHeight';
var cssSize = (d === 'x') ? 'width' : 'height';
var offset = parseInt(c.css(cssOffset), 10) || 0;
var AreaSize = scrollx.size;
var AreaVisible = scrollx.visible + offset;
var scrollSize = scrollx.scroll.size[cssFullSize]() + (parseInt(scrollx.scroll.size.css(cssOffset), 10) || 0);
if (o.autoScrollSize) {
scrollx.scrollbarSize = parseInt(scrollSize * AreaVisible / AreaSize, 10);
scrollx.scroll.bar.css(cssSize, scrollx.scrollbarSize + 'px');
}
scrollx.scrollbarSize = scrollx.scroll.bar[cssFullSize]();
scrollx.kx = ((scrollSize - scrollx.scrollbarSize) / (AreaSize - AreaVisible)) || 1;
scrollx.maxScrollOffset = AreaSize - AreaVisible;
});
c.scrollLeft(initScroll.scrollLeft).scrollTop(initScroll.scrollTop).trigger('scroll');
},
/**
* Get scrollx/scrolly object
*
* @param {Mixed} scroll
* @returns {jQuery} scroll object
*/
_getScroll: function (scroll) {
var types = {
advanced: [
'<div class="scroll-element">',
'<div class="scroll-element_corner"></div>',
'<div class="scroll-arrow scroll-arrow_less"></div>',
'<div class="scroll-arrow scroll-arrow_more"></div>',
'<div class="scroll-element_outer">',
'<div class="scroll-element_size"></div>', // required! used for scrollbar size calculation !
'<div class="scroll-element_inner-wrapper">',
'<div class="scroll-element_inner scroll-element_track">', // used for handling scrollbar click
'<div class="scroll-element_inner-bottom"></div>',
'</div>',
'</div>',
'<div class="scroll-bar">', // required
'<div class="scroll-bar_body">',
'<div class="scroll-bar_body-inner"></div>',
'</div>',
'<div class="scroll-bar_bottom"></div>',
'<div class="scroll-bar_center"></div>',
'</div>',
'</div>',
'</div>'
].join(''),
simple: [
'<div class="scroll-element">',
'<div class="scroll-element_outer">',
'<div class="scroll-element_size"></div>', // required! used for scrollbar size calculation !
'<div class="scroll-element_track"></div>', // used for handling scrollbar click
'<div class="scroll-bar"></div>', // required
'</div>',
'</div>'
].join('')
};
if (types[scroll]) {
scroll = types[scroll];
}
if (!scroll) {
scroll = types['simple'];
}
if (typeof (scroll) == 'string') {
scroll = $(scroll).appendTo(this.wrapper);
} else {
scroll = $(scroll);
}
$.extend(scroll, {
bar: scroll.find('.scroll-bar'),
size: scroll.find('.scroll-element_size'),
track: scroll.find('.scroll-element_track')
});
return scroll;
},
_handleMouseDown: function(callback, event) {
var namespace = this.namespace;
$(document).on('blur' + namespace, function () {
$(document).add('body').off(namespace);
callback && callback();
});
$(document).on('dragstart' + namespace, function (event) {
event.preventDefault();
return false;
});
$(document).on('mouseup' + namespace, function () {
$(document).add('body').off(namespace);
callback && callback();
});
$('body').on('selectstart' + namespace, function (event) {
event.preventDefault();
return false;
});
event && event.preventDefault();
return false;
},
_updateScroll: function (d, scrollx) {
var container = this.container,
containerWrapper = this.containerWrapper || container,
scrollClass = 'scroll-scroll' + d + '_visible',
scrolly = (d === 'x') ? this.scrolly : this.scrollx,
offset = parseInt(this.container.css((d === 'x') ? 'left' : 'top'), 10) || 0,
wrapper = this.wrapper;
var AreaSize = scrollx.size;
var AreaVisible = scrollx.visible + offset;
scrollx.isVisible = (AreaSize - AreaVisible) > 1; // bug in IE9/11 with 1px diff
if (scrollx.isVisible) {
scrollx.scroll.addClass(scrollClass);
scrolly.scroll.addClass(scrollClass);
containerWrapper.addClass(scrollClass);
} else {
scrollx.scroll.removeClass(scrollClass);
scrolly.scroll.removeClass(scrollClass);
containerWrapper.removeClass(scrollClass);
}
if (d === 'y') {
if(container.is('textarea') || AreaSize < AreaVisible){
containerWrapper.css({
"height": (AreaVisible + browser.scroll.height) + 'px',
"max-height": "none"
});
} else {
containerWrapper.css({
//"height": "auto", // do not reset height value: issue with height:100%!
"max-height": (AreaVisible + browser.scroll.height) + 'px'
});
}
}
if (scrollx.size != container.prop('scrollWidth')
|| scrolly.size != container.prop('scrollHeight')
|| scrollx.visible != wrapper.width()
|| scrolly.visible != wrapper.height()
|| scrollx.offset != (parseInt(container.css('left'), 10) || 0)
|| scrolly.offset != (parseInt(container.css('top'), 10) || 0)
) {
$.extend(this.scrollx, {
"offset": parseInt(container.css('left'), 10) || 0,
"size": container.prop('scrollWidth'),
"visible": wrapper.width()
});
$.extend(this.scrolly, {
"offset": parseInt(container.css('top'), 10) || 0,
"size": this.container.prop('scrollHeight'),
"visible": wrapper.height()
});
this._updateScroll(d === 'x' ? 'y' : 'x', scrolly);
}
}
};
var CustomScrollbar = BaseScrollbar;
/*
* Extend jQuery as plugin
*
* @param {Mixed} command to execute
* @param {Mixed} arguments as Array
* @return {jQuery}
*/
$.fn.scrollbar = function (command, args) {
if (typeof command !== 'string') {
args = command;
command = 'init';
}
if (typeof args === 'undefined') {
args = [];
}
if (!$.isArray(args)) {
args = [args];
}
this.not('body, .scroll-wrapper').each(function () {
var element = $(this),
instance = element.data(browser.data.name);
if (instance || command === 'init') {
if (!instance) {
instance = new CustomScrollbar(element);
}
if (instance[command]) {
instance[command].apply(instance, args);
}
}
});
return this;
};
/**
* Connect default options to global object
*/
$.fn.scrollbar.options = defaults;
/**
* Check if scroll content/container size is changed
*/
var updateScrollbars = (function () {
var timer = 0,
timerCounter = 0;
return function (force) {
var i, container, options, scroll, wrapper, scrollx, scrolly;
for (i = 0; i < browser.scrolls.length; i++) {
scroll = browser.scrolls[i];
container = scroll.container;
options = scroll.options;
wrapper = scroll.wrapper;
scrollx = scroll.scrollx;
scrolly = scroll.scrolly;
if (force || (options.autoUpdate && wrapper && wrapper.is(':visible') &&
(container.prop('scrollWidth') != scrollx.size || container.prop('scrollHeight') != scrolly.size || wrapper.width() != scrollx.visible || wrapper.height() != scrolly.visible))) {
scroll.init();
if (options.debug) {
window.console && console.log({
scrollHeight: container.prop('scrollHeight') + ':' + scroll.scrolly.size,
scrollWidth: container.prop('scrollWidth') + ':' + scroll.scrollx.size,
visibleHeight: wrapper.height() + ':' + scroll.scrolly.visible,
visibleWidth: wrapper.width() + ':' + scroll.scrollx.visible
}, true);
timerCounter++;
}
}
}
if (debug && timerCounter > 10) {
window.console && console.log('Scroll updates exceed 10');
updateScrollbars = function () {};
} else {
clearTimeout(timer);
timer = setTimeout(updateScrollbars, 300);
}
};
})();
/* ADDITIONAL FUNCTIONS */
/**
* Get native browser scrollbar size (height/width)
*
* @param {Boolean} actual size or CSS size, default - CSS size
* @returns {Object} with height, width
*/
function getBrowserScrollSize(actualSize) {
if (browser.webkit && !actualSize) {
return {
"height": 0,
"width": 0
};
}
if (!browser.data.outer) {
var css = {
"border": "none",
"box-sizing": "content-box",
"height": "200px",
"margin": "0",
"padding": "0",
"width": "200px"
};
browser.data.inner = $("<div>").css($.extend({}, css));
browser.data.outer = $("<div>").css($.extend({
"left": "-1000px",
"overflow": "scroll",
"position": "absolute",
"top": "-1000px"
}, css)).append(browser.data.inner).appendTo("body");
}
browser.data.outer.scrollLeft(1000).scrollTop(1000);
return {
"height": Math.ceil((browser.data.outer.offset().top - browser.data.inner.offset().top) || 0),
"width": Math.ceil((browser.data.outer.offset().left - browser.data.inner.offset().left) || 0)
};
}
/**
* Check if native browser scrollbars overlay content
*
* @returns {Boolean}
*/
function isScrollOverlaysContent() {
var scrollSize = getBrowserScrollSize(true);
return !(scrollSize.height || scrollSize.width);
}
function isVerticalScroll(event) {
var e = event.originalEvent;
if (e.axis && e.axis === e.HORIZONTAL_AXIS)
return false;
if (e.wheelDeltaX)
return false;
return true;
}
/**
* Extend AngularJS as UI directive
* and expose a provider for override default config
*
*/
if (window.angular) {
(function (angular) {
angular.module('jQueryScrollbar', [])
.provider('jQueryScrollbar', function () {
var defaultOptions = defaults;
return {
setOptions: function (options) {
angular.extend(defaultOptions, options);
},
$get: function () {
return {
options: angular.copy(defaultOptions)
};
}
};
})
.directive('jqueryScrollbar', ['jQueryScrollbar', '$parse', function (jQueryScrollbar, $parse) {
return {
"restrict": "AC",
"link": function (scope, element, attrs) {
var model = $parse(attrs.jqueryScrollbar),
options = model(scope);
element.scrollbar(options || jQueryScrollbar.options)
.on('$destroy', function () {
element.scrollbar('destroy');
});
}
};
}]);
})(window.angular);
}
}));
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long