summaryrefslogtreecommitdiffstats
path: root/web-tools/web/_static/jsuites
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@open-infrastructure.net>2021-10-14 14:59:23 +0000
committerDaniel Baumann <daniel.baumann@open-infrastructure.net>2022-01-27 07:04:33 +0000
commite7de04494b70ca62ac1abda7f9a3ef41994f4f51 (patch)
tree78a8387bbe7d9204f2c46a3e5128a7e2e58ba322 /web-tools/web/_static/jsuites
parentAdding debian packaging. (diff)
downloadnetwork-tools-e7de04494b70ca62ac1abda7f9a3ef41994f4f51.tar.xz
network-tools-e7de04494b70ca62ac1abda7f9a3ef41994f4f51.zip
Adding web-tools (WIP).
Signed-off-by: Daniel Baumann <daniel.baumann@open-infrastructure.net>
Diffstat (limited to 'web-tools/web/_static/jsuites')
-rw-r--r--web-tools/web/_static/jsuites/jsuites.basic.css1864
-rw-r--r--web-tools/web/_static/jsuites/jsuites.basic.js6737
-rw-r--r--web-tools/web/_static/jsuites/jsuites.css2208
-rw-r--r--web-tools/web/_static/jsuites/jsuites.js8470
-rw-r--r--web-tools/web/_static/jsuites/jsuites.layout.css1395
-rw-r--r--web-tools/web/_static/jsuites/jsuites.layout.js1491
-rw-r--r--web-tools/web/_static/jsuites/jsuites.mobile.css1015
-rw-r--r--web-tools/web/_static/jsuites/jsuites.mobile.js793
-rw-r--r--web-tools/web/_static/jsuites/jsuites.webcomponents.js502
9 files changed, 24475 insertions, 0 deletions
diff --git a/web-tools/web/_static/jsuites/jsuites.basic.css b/web-tools/web/_static/jsuites/jsuites.basic.css
new file mode 100644
index 0000000..7631bea
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.basic.css
@@ -0,0 +1,1864 @@
+
+/**
+ * (c) jSuites Javascript Web Components
+ *
+ * Author: Paul Hodel <paul.hodel@gmail.com>
+ * Website: https://bossanova.uk/jsuites/
+ * Description: Create amazing web based applications.
+ *
+ * MIT License
+ *
+ */
+
+:root {
+ --button-color: #298BA8;
+ --active-color: #007aff;
+}
+
+.unselectable {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.jdragging {
+ opacity:0.2;
+ filter: alpha(opacity=20);
+}
+
+.jupload.input {
+ padding-right:18px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z'/%3E%3C/svg%3E");
+ background-position:top 50% right 5px;
+ background-repeat:no-repeat;
+ box-sizing: border-box;
+ background-size: initial;
+ height: 33px;
+ min-height: initial;
+}
+
+.jupload.input img {
+ width: initial !important;
+ max-width: 100%;
+ height: 100%;
+}
+
+.jupload {
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAACXBIWXMAAAsTAAALEwEAmpwYAAA7emlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNyAoV2luZG93cyk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTctMTItMzFUMjI6NDM6MzBaPC94bXA6Q3JlYXRlRGF0ZT4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMTgtMDEtMDFUMjA6MDM6MjNaPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0wMS0wMVQyMDowMzoyM1o8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6ZDE3NGVkY2UtNWZkNC0wODRkLTkzNzAtZDRhODVmMzdkNjdiPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD54bXAuZGlkOjBmYzcxZDEyLTg1MGUtY2E0NS05MzE4LWRhYjI5YWZhMmQ4MjwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD54bXAuZGlkOjBmYzcxZDEyLTg1MGUtY2E0NS05MzE4LWRhYjI5YWZhMmQ4MjwveG1wTU06T3JpZ2luYWxEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgICAgICAgPHJkZjpTZXE+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDowZmM3MWQxMi04NTBlLWNhNDUtOTMxOC1kYWIyOWFmYTJkODI8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTctMTItMzFUMjI6NDM6MzBaPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNyAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjk2MTA5Y2Y0LTEwM2ItNTc0Ny1hZWE3LWI5NDMxOWY0NWFkZjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0wMS0wMVQyMDowMjoyMFo8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE3IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZDE3NGVkY2UtNWZkNC0wODRkLTkzNzAtZDRhODVmMzdkNjdiPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTAxLTAxVDIwOjAzOjIzWjwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjY1NTM1PC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj44MDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj44MDwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+tc8AsgAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAGjUlEQVR42uycW2xURRjHf91SoEIBUQpYI8VSVBDExniLERNUJBpQVEDFqE1AEYkX0JCC0YjgBdEYDOIFeVEEFRBilKBogg+KiQoV5Q6Khla8lrZRBLo+zLdazs7ZM2d3zsJu55/sy3dmz5797Vy+y8wWxONxnNJXzCFwAB1AB9ABdHIAHUAH0AF0Cq929fX1ufbMA4HLgSqgHOgPdJJrfwPbgb3AJuBD4KsoH6agrq4uF6CVAncC4wVYGP0ALAVeAva0NYDFwOPARKBzhvc6ArwG1AC/toU5cDSwFXjAAjyAQmACsAOozneATwLLgdMM2/8jLxN1AxYBC/J1CL8F3BjQZhOwCqgFvgd+AuJAT6ACOBMYCVwUcJ91siDlDcC3gRtSXF8IzAe+M7xfOXC3TAOFPm3WA0NzAeDp8oUGASeKrUF60R6Zn6an6CnTgI1pfnYFMAcY43N9GTDueAR4sQylK8RvS0dzgYcsPc9U4Bmfa9XA4uMF4GXypUdkeJ8Z0nNs6hbgdZ9rPcK6OLZX4XbisH5iAd68COABvAHc63NtwbHsgf2B94BKC/faAFwY8Zy8ErhWYx8EbM42wAuAj4ETAtptllh1N9AiC0t/YLCnXV9xT6JUJ6AOKPHYX5HIJ2sAK4BvgQ4+17fJ5LxKIgudzgBGySS/3sAPtKWZwCyPrQk4ydQxtwFwH9BbY4/LIvBEyF5RIF8iG+oC/K7xEUfLEI98EVnsA28/MCQkPIDmLMIDOCDOu1fXZGMVrgJu19gbZCKuJTek62mV2QD4XIoFZT+5o10a2ylRA6wCLtXYp8uikUv6Webr1uoOdIwS4HiNbS/wFLmnZuCgx9Y+hVdhBeBwjW1+BF9uFvBqFiDGDW3a0Cus+gADPLYWVB7PpiaJn5YYZjMigles6W2NskJH0gN1RZ1EJcyWJnvi0hpUbSQK9dRwaDGIqtIGeLbG9o3lnveCT2YmCogVPqvwdpOIKB2A7TU2W+XCiQEZkSggTvGxl8m0NNc2wDKNrcXCF5mASoUFaQYw2xK8Iv4vyvtpmsTxGQHsLPPQLp9frI+FYftyiPY1liAeBs5DZYNS/XgjgTXpApwq4Gaj0k86DbK4YISBmOlwjreaw+8CzvEDJa7bojAATwU+QtUQSg0Wlr4WFwxT2Z4Ta1GZ9Md8rlcDY00ADpFfZViID7/D8oJxrCACPCIjQ6elqOK8ryM9GPg64AM+B1YAW1BJ0r9M/aaQC0YYiAWWne0FQFf0dZnngdsgOaHaXVySLj43XSY3zCRVNclSz9NpTgQRywfAVRr7WcDWmKaxDl4TKuU+LkN4kyOEF1XEMk5GmFf3eOfAKcD5moY/ypy4OsMHeTjDBSPMcF5o8X4NPs70eKAoMYSLJIDuoOl5AwRiJroJWIIq1BwM8DcLDFyPpoAESTEqN/m0aVYlQF1RtRPviB2ZWEQeRJ//Gm0BHqhttieTutJVgkrGBu0FbEbtvmoMgNjLErxEL3yH5L01oxIA79O8aTVqj7ENmWSpGw1DwhZUJTBIf1ieGlZoAFbGxG3pESLIjkolBsMXaVNC9qWrnZTFZJh69SV283v5oHrNlNA9JvGfV0scL+3cm1Q7iaFPKNY6XimTD0fFwuWaRrscqyR11Hgqh2IkZ5gPy7LtdLRKNX7gnzHgkMdYGDIx0FZUrrHVxVBHBLzDup/jlaSrNbbdMWCn5sIAxyspsrlZY18TQ3/mYoxjdpQmkFx8OgKsjAHvat4wlFZZVyce1diWA80x4DOf7Ma8LD+kaYhmGvLZ0ovoa0LP0mpZ1qXXq4Fzs/igiSRBY8BrH3bq0Ca6HlWt82od6iTBfyn9Lj6+Xx2q2nYwSz3Q9FhrE/ZSVX66BPjU51q/RLCR6IEH0KfCe8sQL85SmNRo+Ioa3tgU8Ga2jtS8RaUdPj7gTtQRqS/yfLHogErf+6Xykk52ekOTESm67AbUrvuyPARXAtyPSvz6wduK5myx7pzIcPy3N4D6Z4w3pc0O1IbybAwrWyqSubZUOsYw4DrU4Ro/bUEd3m4wAZjoie8bPtARVNkvVwAWypxu6gqtRW0u0i6kqU4qDUEVUirasANdQ8BhoVSbizai/uRmbhsEtxp1lCPwpJXpWbmBqD++uTWPQ7xm1NaVJeIomzmvIQ8bdpO0zpWozea9Aibf41WHgd9QhaJtqAPia4FfQnv/7l98M5P79zYH0AF0AB1AJwfQAXQAHUCnNPTvAKemiFU6nb96AAAAAElFTkSuQmCC);
+ background-repeat: no-repeat;
+ background-size: 100px;
+ background-position: center;
+ background-color: rgba(230, 230, 230, 0.1);
+ border: 1px dotted #eee;
+ cursor: pointer;
+ box-sizing: border-box;
+ width:100%;
+ min-height:180px;
+}
+
+.jremove {
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+
+
+/** Animations **/
+.fade-in {
+ animation: fade-in 2s forwards;
+}
+
+.fade-out {
+ animation: fade-out 1s forwards;
+}
+
+.slide-left-in {
+ animation: slide-left-in 0.4s forwards;
+}
+
+.slide-left-out {
+ animation: slide-left-out 0.4s forwards;
+}
+
+.slide-right-in {
+ animation: slide-right-in 0.4s forwards;
+}
+
+.slide-right-out {
+ animation: slide-right-out 0.4s forwards;
+}
+
+.slide-top-in {
+ animation: slide-top-in 0.4s forwards;
+}
+
+.slide-top-out {
+ animation: slide-top-out 0.2s forwards;
+}
+
+.slide-bottom-in {
+ animation: slide-bottom-in 0.4s forwards;
+}
+
+.slide-bottom-out {
+ animation: slide-bottom-out 0.1s forwards;
+}
+
+/** Fadein and Fadeout **/
+@keyframes fade-in {
+ 0% { opacity: 0; }
+ 100% { opacity: 100; }
+}
+
+@-webkit-keyframes fade-in {
+ 0% { opacity: 0; }
+ 100% { opacity: 100; }
+}
+
+@keyframes fade-out {
+ 0% { opacity: 100; }
+ 100% { opacity: 0; }
+}
+
+@-webkit-keyframes fade-out {
+ 0% { opacity: 100; }
+ 100% { opacity: 0; }
+}
+
+/** Keyframes Left to Right **/
+@keyframes slide-left-in {
+ 0% { transform: translateX(-100%); }
+ 100% { transform: translateX(0%); }
+}
+
+@-webkit-keyframes slide-left-in {
+ 0% { transform: translateX(-100%); }
+ 100% { -webkit-transform: translateX(0%); }
+}
+
+@keyframes slide-left-out {
+ 0% { transform: translateX(0%); }
+ 100% { transform: translateX(-100%); }
+}
+
+@-webkit-keyframes slide-left-out {
+ 0% { -webkit-transform: translateX(0%); }
+ 100% { -webkit-transform: translateX(-100%); }
+}
+
+/** Keyframes Right to Left **/
+@keyframes slide-right-in {
+ 0% { transform: translateX(100%); }
+ 100% { transform: translateX(0%); }
+}
+
+@-webkit-keyframes slide-right-in
+{
+ 0% { transform: translateX(100%); }
+ 100% { -webkit-transform: translateX(0%); }
+}
+
+@keyframes slide-right-out {
+ 0% { transform: translateX(0%); }
+ 100% { transform: translateX(100%); }
+}
+
+@-webkit-keyframes slide-right-out {
+ 0% { -webkit-transform: translateX(0%); }
+ 100% { -webkit-transform: translateX(100%); }
+}
+
+/** Keyframes Top to Bottom **/
+@keyframes slide-top-in {
+ 0% { transform: translateY(-100%); }
+ 100% { transform: translateY(0%); }
+}
+
+@-webkit-keyframes slide-top-in {
+ 0% { transform: translateY(-100%); }
+ 100% { -webkit-transform: translateY(0%); }
+}
+
+@keyframes slide-top-out {
+ 0% { transform: translateY(0%); }
+ 100% { transform: translateY(-100%); }
+}
+
+@-webkit-keyframes slide-top-out {
+ 0% { -webkit-transform: translateY(0%); }
+ 100% { -webkit-transform: translateY(-100%); }
+}
+
+/** Keyframes Bottom to Top **/
+@keyframes slide-bottom-in {
+ 0% { transform: translateY(100%); }
+ 100% { transform: translateY(0%); }
+}
+
+@-webkit-keyframes slide-bottom-in {
+ 0% { transform: translateY(100%); }
+ 100% { -webkit-transform: translateY(0%); }
+}
+
+@keyframes slide-bottom-out {
+ 0% { transform: translateY(0%); }
+ 100% { transform: translateY(100%); }
+}
+
+@-webkit-keyframes slide-bottom-out {
+ 0% { -webkit-transform: translateY(0%); }
+ 100% { -webkit-transform: translateY(100%); }
+}
+
+@-webkit-keyframes spin {
+ from {
+ -webkit-transform:rotate(0deg);
+ }
+ to {
+ -webkit-transform:rotate(360deg);
+ }
+}
+
+@keyframes spin {
+ from {
+ transform:rotate(0deg);
+ }
+ to {
+ transform:rotate(360deg);
+ }
+}
+
+/**
+ * Date & Datetime picker v1.0.1
+ * Author: paul.hodel@gmail.com
+ * https://github.com/paulhodel/jtools
+ */
+
+.jcalendar {
+ position:absolute;
+ z-index:9000;
+ display:none;
+ box-sizing:border-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ -webkit-tap-highlight-color: transparent;
+ min-width:280px;
+}
+
+.jcalendar.jcalendar-focus {
+ display:block;
+}
+
+.jcalendar .jcalendar-backdrop {
+ position:fixed;
+ top:0px;
+ left:0px;
+ z-index:9000;
+ min-width:100%;
+ min-height:100%;
+ background-color:rgba(0,0,0,0.5);
+ border:0px;
+ padding:0px;
+ display:none;
+}
+
+.jcalendar .jcalendar-container {
+ position:relative;
+ box-sizing:border-box;
+}
+
+.jcalendar .jcalendar-content {
+ position:absolute;
+ z-index:9001;
+ -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ background-color:#fff;
+}
+
+.jcalendar-header {
+ text-align:center;
+}
+
+.jcalendar-header span {
+ margin-right:4px;
+ font-size:1.1em;
+ font-weight:bold;
+}
+
+.jcalendar-prev {
+ cursor:pointer;
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z' fill='%23000' /%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3C/svg%3E");
+ background-position:center;
+ background-repeat:no-repeat;
+}
+
+.jcalendar-next {
+ cursor:pointer;
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z' fill='%23000' /%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3C/svg%3E");
+ background-position:center;
+ background-repeat:no-repeat;
+}
+
+.jcalendar-weekday {
+ font-weight: 600;
+ background-color: #fcfcfc;
+ padding: 14px;
+}
+
+.jcalendar-table > table {
+ width:100%;
+ background-color:#fff;
+}
+
+.jcalendar-table > table > thead {
+ cursor:pointer;
+}
+
+.jcalendar-table thead td {
+ padding:10px;
+ height:40px;
+}
+
+.jcalendar-table > table > tbody td {
+ box-sizing:border-box;
+ cursor:pointer;
+ padding:9px;
+ font-size:0.9em;
+}
+
+
+.jcalendar-table tfoot td {
+ padding:10px;
+}
+
+.jcalendar-months td, .jcalendar-years td {
+ height:24px;
+}
+
+.jcalendar-input {
+ padding-right:18px;
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='gray'%3E%3Cpath d='M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V8h16v13z'/%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3C/svg%3E");
+ background-position:top 50% right 5px;
+ background-repeat:no-repeat;
+ box-sizing: border-box;
+}
+
+.jcalendar-done {
+ -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ background-color:#fff;
+}
+
+.jcalendar-update {
+ border:1px solid #ccc;
+ background-color:#fff;
+ border-radius:4px;
+ padding:5px;
+ width:100%;
+}
+
+.jcalendar-container select {
+ width:55px;
+ display:inline-block;
+ border:0px;
+ padding:4px;
+ text-align:center;
+ font-size:1.1em;
+ user-select:none;
+ margin-right:10px;
+}
+
+.jcalendar-container select:first-child {
+ margin-right:2px;
+}
+
+.jcalendar-selected {
+ background-color:#eee;
+}
+
+.jcalendar-reset, .jcalendar-confirm {
+ text-transform:uppercase;
+ cursor:pointer;
+ color: var(--active-color);
+}
+
+.jcalendar-controls {
+ padding:15px;
+
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align:middle;
+
+ display: -webkit-box;
+ display: -moz-box;
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+
+ -webkit-flex-flow: row wrap;
+ justify-content: space-between;
+ align-items:center;
+}
+
+.jcalendar-controls div {
+ font-weight:bold;
+}
+
+.jcalendar-fullsize {
+ position:fixed;
+ width:100%;
+ top:0px;
+ left:0px;
+}
+
+.jcalendar-fullsize .jcalendar-content
+{
+ position:fixed;
+ width:100%;
+ left:0px;
+ bottom:0px;
+}
+
+.jcalendar-focus.jcalendar-fullsize .jcalendar-backdrop {
+ display:block;
+}
+
+.jcalendar-sunday {
+ color: red;
+}
+.jcalendar-disabled {
+ color: #ccc;
+}
+
+.jcalendar-time {
+ display:flex;
+}
+
+
+.jcolor {
+ position: absolute;
+ display: none;
+ outline: none;
+}
+
+.jcolor-input {
+ padding-right:18px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z'/%3E%3C/svg%3E");
+ background-position:top 50% right 5px;
+ background-repeat:no-repeat;
+ box-sizing: border-box;
+}
+
+.jcolor-content {
+ position: absolute;
+ left: 0px;
+ z-index: 9000;
+ user-select: none;
+ -webkit-font-smoothing: antialiased;
+ font-size: .875rem;
+ letter-spacing: .2px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
+ box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
+ background-color:#fff;
+ box-sizing: border-box;
+}
+
+.jcolor-controls {
+ display: flex;
+ padding: 10px;
+ padding-bottom: 0px;
+}
+
+.jcolor-controls div {
+ flex: 1;
+ font-size: 1em;
+ color: var(--active-color);
+ text-transform: uppercase;
+ font-weight: bold;
+ box-sizing: border-box;
+}
+
+.jcolor-content table {
+ border-collapse: initial;
+ padding: 7px !important;
+ box-sizing: border-box;
+}
+
+.jcolor-focus {
+ display:block;
+}
+
+.jcolor table {
+ width:100%;
+ height:100%;
+}
+
+.jcolor td {
+ padding: 7px;
+ border:2px solid #fff;
+}
+
+.jcolor-selected {
+ border:2px solid #000 !important;
+ background-repeat:no-repeat;
+ background-size: 16px;
+ background-position: center;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z' fill='white'/%3E%3C/svg%3E");
+}
+
+.jcolor-fullscreen {
+ position: fixed;
+ bottom: 0px;
+ width:100%;
+ max-height:250px;
+ border-radius: 0px;
+ box-sizing: border-box;
+}
+
+.jcolor-fullscreen .jcolor-controls {
+ padding: 15px;
+ -webkit-box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
+ box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
+}
+
+.jcolor-reset {
+ text-align: left;
+}
+
+.jcolor-close {
+ text-align: right;
+}
+
+.jcolor-backdrop {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ min-width: 100%;
+ min-height: 100%;
+ background-color: rgba(0,0,0,0.5);
+ border: 0px;
+ padding: 0px;
+ z-index: 8000;
+ display: none;
+
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ -khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none; /* Non-prefixed version, currently
+ supported by Chrome and Opera */
+}
+
+/**
+ * Contextmenu v1.0.1
+ * Author: paul.hodel@gmail.com
+ * https://github.com/paulhodel/jsuites
+ */
+
+.jcontextmenu {
+ position:fixed;
+ z-index:10000;
+ background:#fff;
+ color: #555;
+ font-size: 11px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ -webkit-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
+ -moz-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
+ box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
+ border: 1px solid #C6C6C6;
+ padding: 0px;
+ padding-top:4px;
+ padding-bottom:4px;
+ margin:0px;
+ outline:none;
+ display:none;
+}
+
+.jcontextmenu.jcontextmenu-focus {
+ display:inline-block;
+}
+
+.jcontextmenu > div {
+ box-sizing: border-box;
+ display: flex;
+ padding: 8px 8px 8px 32px;
+ width: 250px;
+ position: relative;
+ cursor: default;
+ font-size: 11px;
+ font-family:sans-serif;
+}
+
+.jcontextmenu > div::before {
+ content: attr(data-icon);
+ font-family: 'Material Icons';
+ font-weight: normal;
+ font-style: normal;
+ font-size: 16px;
+ line-height: 1;
+ letter-spacing: normal;
+ text-transform: none;
+ display: inline-block;
+ white-space: nowrap;
+ word-wrap: normal;
+ direction: ltr;
+ -webkit-font-feature-settings: 'liga';
+ -webkit-font-smoothing: antialiased;
+ position: absolute;
+ left: 9px;
+}
+
+.jcontextmenu > div a {
+ color: #555;
+ text-decoration: none;
+ flex: 1;
+}
+
+.jcontextmenu > div span {
+ margin-right:10px;
+}
+
+.jcontextmenu .jcontextmenu-disabled a {
+ color: #ccc;
+}
+
+.jcontextmenu > div:hover {
+ background: #ebebeb;
+}
+
+.jcontextmenu hr {
+ border: 1px solid #e9e9e9;
+ border-bottom: 0;
+ margin-top:5px;
+ margin-bottom:5px;
+}
+
+.jcontextmenu > hr:hover {
+ background: transparent;
+}
+
+.jcontextmenu .jcontextmenu {
+ top: 4px;
+ left: 99%;
+ opacity: 0;
+ position: absolute;
+}
+
+.jcontextmenu > div:hover > .jcontextmenu {
+ display: block;
+ opacity: 1;
+ -webkit-transform: translate(0, 0) scale(1);
+ transform: translate(0, 0) scale(1);
+ pointer-events: auto;
+}
+
+/**
+ * (c) 2013 jDropdown
+ * http://www.github.com/paulhodel/jdropdown
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Custom dropdowns
+ */
+
+.jdropdown {
+ cursor:pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ box-sizing: border-box;
+ background:#fff;
+ -webkit-tap-highlight-color: transparent;
+ display: inline-block;
+}
+
+.jdropdown-header::placeholder {
+ color:#000;
+}
+
+.jdropdown-backdrop {
+ position:fixed;
+ top:0px;
+ left:0px;
+ min-width:100%;
+ min-height:100%;
+ background-color:rgba(0,0,0,0.5);
+ border:0px;
+ padding:0px;
+ z-index:8000;
+ display:none;
+}
+
+.jdropdown-focus {
+ position:relative;
+}
+
+.jdropdown-focus .jdropdown-container {
+ transform: translate3d(0,0,0);
+}
+
+.jdropdown-default.jdropdown-focus .jdropdown-header {
+ outline:auto 5px -webkit-focus-ring-color;
+}
+
+.jdropdown-default.jdropdown-focus .jdropdown-header.jdropdown-add {
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='gray' width='24px' height='24px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z'/%3E%3C/svg%3E");
+}
+
+.jdropdown-container-header
+{
+ padding:0px;
+ margin:0px;
+ position:relative;
+}
+
+.jdropdown-header
+{
+ width:100%;
+ appearance: none;
+ background-repeat: no-repeat;
+ background-position:top 50% right 5px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 10l5 5 5-5H7z' fill='gray'/%3E%3C/svg%3E");
+ text-overflow: ellipsis;
+ cursor:pointer;
+ box-sizing: border-box;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ padding-right:30px !important;
+}
+
+.jdropdown-insert-button
+{
+ font-size: 1.4em;
+ text-transform: uppercase;
+ position:absolute;
+ right: 30px;
+ top: 4px;
+ display:none;
+}
+
+.jdropdown-container
+{
+ min-width: inherit;
+ transform: translate3d(-10000px,0,0);
+ position:absolute;
+ z-index:9001;
+}
+
+.jdropdown-close
+{
+ display:none;
+ font-size:1em;
+ color: var(--active-color);
+ text-transform:uppercase;
+ text-align:right;
+ padding:15px;
+ font-weight:bold;
+}
+
+.jdropdown-content
+{
+ min-width:inherit;
+ margin:0px;
+ box-sizing:border-box;
+}
+
+.jdropdown-content:empty
+{
+}
+
+.jdropdown-item
+{
+ white-space: nowrap;
+ text-align: left;
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ color: #000;
+ display: flex;
+ align-items: center;
+}
+
+.jdropdown-description
+{
+ text-overflow: ellipsis;
+ overflow: hidden;
+ line-height: 1.5em;
+}
+
+.jdropdown-image
+{
+ margin-right:10px;
+ width: 32px;
+ height: 32px;
+ border-radius:20px;
+}
+
+.jdropdown-image-small
+{
+ width:24px;
+ height:24px;
+}
+
+.jdropdown-title
+{
+ font-size: 0.7em;
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ display: block;
+}
+
+/** Default visual **/
+
+.jdropdown-default .jdropdown-header
+{
+ border:1px solid #ccc;
+ padding:5px;
+ padding-left:10px;
+ padding-right:16px;
+}
+
+.jdropdown-default .jdropdown-container
+{
+ background-color:#fff;
+}
+
+.jdropdown-default.jdropdown-focus.jdropdown-insert .jdropdown-header {
+ padding-right:50px;
+}
+
+.jdropdown-default.jdropdown-focus.jdropdown-insert .jdropdown-insert-button {
+ display:block;
+}
+
+.jdropdown-default .jdropdown-content
+{
+ min-width:inherit;
+ border:1px solid #8fb1e3;
+ margin:0px;
+ background-color:#fff;
+ box-sizing:border-box;
+ min-height:10px;
+ max-height:215px;
+ overflow-y:auto;
+}
+
+.jdropdown-default .jdropdown-item
+{
+ padding:4px;
+ padding-left:8px;
+ padding-right:40px;
+}
+
+.jdropdown-default .jdropdown-item:hover
+{
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+.jdropdown-default .jdropdown-cursor
+{
+ background-color:#eee;
+}
+
+.jdropdown-default .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiIGZpbGw9IndoaXRlIiAvPjwvc3ZnPgo=');
+ background-repeat:no-repeat;
+ background-position:top 50% right 5px;
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+.jdropdown-default .jdropdown-group
+{
+ margin-top:5px;
+}
+
+.jdropdown-default .jdropdown-group .jdropdown-item
+{
+ padding-left:16px;
+}
+
+.jdropdown-default .jdropdown-group-name
+{
+ padding-left:8px;
+ font-weight:bold;
+}
+
+.jdropdown-default .jdropdown-reset_ {
+ content:'x';
+ position:absolute;
+ top:0;
+ right:0;
+ margin:5px;
+ margin-right:10px;
+ font-size:12px;
+ width:12px;
+ cursor:pointer;
+ text-shadow: 0px 0px 5px #fff;
+ display:none;
+ line-height: 1.8em;
+}
+
+.jdropdown-default.jdropdown-focus .jdropdown-reset_ {
+ display:block;
+}
+
+/** Default render for mobile **/
+
+.jdropdown-picker.jdropdown-focus .jdropdown-backdrop {
+ display:block;
+}
+
+.jdropdown-picker .jdropdown-header {
+ outline: none;
+}
+
+.jdropdown-picker .jdropdown-container
+{
+ position:fixed;
+ bottom:0px;
+ left:0px;
+ border-bottom:1px solid #e6e6e8;
+ width:100%;
+ background-color:#fff;
+ box-sizing: border-box;
+}
+
+.jdropdown-picker .jdropdown-close
+{
+ -webkit-box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
+ box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
+ background-color:#fff;
+ display:block;
+}
+
+.jdropdown-picker .jdropdown-content
+{
+ overflow-y:scroll;
+ height:280px;
+ background-color:#fafafa;
+ border-top:1px solid #e6e6e8;
+}
+
+.jdropdown-picker .jdropdown-group-name
+{
+ font-size: 1em;
+ text-transform: uppercase;
+ padding-top:10px;
+ padding-bottom:10px;
+ display: block;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:20px;
+ padding-right:20px;
+ text-align:center;
+ font-weight:bold;
+}
+
+.jdropdown-picker .jdropdown-item
+{
+ font-size: 1em;
+ text-transform: uppercase;
+ padding-top:10px;
+ padding-bottom:10px;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:20px;
+ padding-right:20px;
+}
+
+.jdropdown-picker .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiIGZpbGw9IndoaXRlIiAvPjwvc3ZnPgo=');
+ background-repeat:no-repeat;
+ background-position:top 50% right 15px;
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+.jdropdown-picker .jdropdown-cursor
+{
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+/** Default render for mobile searchbar **/
+
+.jdropdown-searchbar.jdropdown-focus
+{
+ position:fixed;
+ top:0px;
+ left:0px;
+ width:100%;
+ height:100%;
+ background-color:#fafafa;
+ padding:0px;
+ z-index:9001;
+ overflow-y:scroll;
+}
+
+.jdropdown-searchbar.jdropdown-focus .jdropdown-container-header
+{
+ padding:10px;
+ background-color:#fff;
+ box-shadow: 0 1px 2px rgba(0,0,0,.1);
+}
+
+.jdropdown-searchbar.jdropdown-focus .jdropdown-header
+{
+ border: 0px;
+ background-repeat: no-repeat;
+ background-position-x: 0%;
+ background-position-y: 40%;
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTUuNSAxNGgtLjc5bC0uMjgtLjI3QzE1LjQxIDEyLjU5IDE2IDExLjExIDE2IDkuNSAxNiA1LjkxIDEzLjA5IDMgOS41IDNTMyA1LjkxIDMgOS41IDUuOTEgMTYgOS41IDE2YzEuNjEgMCAzLjA5LS41OSA0LjIzLTEuNTdsLjI3LjI4di43OWw1IDQuOTlMMjAuNDkgMTlsLTQuOTktNXptLTYgMEM3LjAxIDE0IDUgMTEuOTkgNSA5LjVTNy4wMSA1IDkuNSA1IDE0IDcuMDEgMTQgOS41IDExLjk5IDE0IDkuNSAxNHoiIGZpbGw9IiNlNmU2ZTgiLz48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PC9zdmc+);
+ padding-left: 30px !important;
+ padding-right: 60px !important;
+}
+
+.jdropdown-searchbar.jdropdown-focus .jdropdown-close
+{
+ display:block;
+}
+
+.jdropdown-searchbar .jdropdown-header {
+ outline: none;
+}
+
+.jdropdown-searchbar .jdropdown-container
+{
+ width:100%;
+}
+
+.jdropdown-searchbar .jdropdown-close
+{
+ position:fixed;
+ top:0px;
+ right:0px;
+}
+
+.jdropdown-searchbar .jdropdown-content
+{
+ margin-top:10px;
+}
+
+.jdropdown-searchbar .jdropdown-group
+{
+ margin-top:10px;
+ margin-bottom:15px;
+ background-color:#fff;
+}
+
+.jdropdown-searchbar .jdropdown-group-name
+{
+ border-top: 1px solid #e6e6e8;
+ border-bottom: 1px solid #e6e6e8;
+ padding:10px;
+ padding-left:12px;
+ font-weight:bold;
+}
+
+.jdropdown-searchbar .jdropdown-group-arrow
+{
+ float:right;
+ width:24px;
+ height:24px;
+ background-repeat:no-repeat;
+}
+
+.jdropdown-searchbar .jdropdown-group-arrow-down
+{
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNy40MSA4LjU5TDEyIDEzLjE3bDQuNTktNC41OEwxOCAxMGwtNiA2LTYtNiAxLjQxLTEuNDF6Ii8+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgyNHYyNEgwVjB6Ii8+PC9zdmc+);
+}
+
+.jdropdown-searchbar .jdropdown-group-arrow-up
+{
+ background-image: url(data:image/svg+xml;base64,CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTcuNDEgMTUuNDFMMTIgMTAuODNsNC41OSA0LjU4TDE4IDE0bC02LTYtNiA2eiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=);
+}
+
+.jdropdown-searchbar .jdropdown-item
+{
+ padding-top:10px;
+ padding-bottom:10px;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:15px;
+ padding-right:40px;
+ background-color:#fff;
+ font-size:0.9em;
+}
+
+.jdropdown-searchbar .jdropdown-description {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ max-width: calc(100% - 20px);
+}
+
+.jdropdown-searchbar .jdropdown-content > .jdropdown-item:first-child
+{
+ border-top: 1px solid #e6e6e8;
+}
+
+.jdropdown-searchbar .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxeiIgZmlsbD0iIzAwN2FmZiIvPjwvc3ZnPg==');
+ background-repeat:no-repeat;
+ background-position:top 50% right 15px;
+}
+
+/** List render **/
+
+.jdropdown-list
+{
+}
+
+.jdropdown-list .jdropdown-container
+{
+ display:block;
+}
+
+.jdropdown-list .jdropdown-header
+{
+ display:none;
+}
+
+.jdropdown-list .jdropdown-group
+{
+ background-color:#fff;
+}
+
+.jdropdown-list .jdropdown-group-name
+{
+ border-bottom: 1px solid #e6e6e8;
+ padding-top:10px;
+ padding-bottom:10px;
+ font-weight:bold;
+}
+
+.jdropdown-list .jdropdown-item
+{
+ padding-top:10px;
+ padding-bottom:10px;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:10px;
+ padding-right:40px;
+ background-color:#fff;
+}
+
+.jdropdown-list .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxeiIgZmlsbD0iIzAwN2FmZiIvPjwvc3ZnPg==');
+ background-repeat:no-repeat;
+ background-position:top 50% right 10px;
+}
+
+@media only screen and (max-device-width : 800px)
+{
+ .jdropdown-list
+ {
+ width:100% !important;
+ border:0px;
+ padding:0px;
+ }
+
+ .jdropdown-list .jdropdown-container
+ {
+ min-width:100%;
+ }
+}
+
+.app .jdropdown-item {
+ text-transform:uppercase;
+}
+
+.jdropdown-create-container {
+ margin: 10px;
+ border: 1px solid #ccc;
+ border-radius: 2px;
+ padding: 6px;
+}
+
+.jdropdown-color {
+ background-color: #fff;
+ border: 1px solid transparent;
+ border-radius: 12px;
+ width: 12px;
+ height: 12px;
+ margin-right: 6px;
+}
+
+/**
+ * (c) jTools Text Editor
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Inline richtext editor
+ */
+
+ .jeditor-container {
+ border:1px solid #ccc;
+}
+
+.jeditor-dragging {
+ border:1px dashed #000;
+}
+
+.jeditor-container.jeditor-padding {
+ padding:10px;
+}
+
+.jeditor {
+ outline:none;
+ word-break: break-word;
+
+}
+
+.jeditor-container.jeditor-padding .jeditor {
+ min-height:160px;
+ margin-bottom:10px;
+ padding:10px;
+}
+
+.jeditor-thumbs {
+ display:inline-block;
+ margin-right:5px;
+}
+
+.jeditor-thumbs-container {
+ margin-top:15px;
+}
+
+.jeditor-thumbs .close {
+ position:absolute;
+ height:1px;
+}
+
+.jeditor-thumbs .close i {
+ color:#fff;
+ text-shadow: 0px 0px 2px #000;
+ position:relative;
+ top:5px;
+ left:72px;
+}
+
+.jeditor-thumbs img {
+ border:1px solid #eee;
+ width:100px;
+ height:100px;
+}
+
+.jeditor-users {
+ position:absolute;
+ border:1px solid #ccc;
+ background-color:#fff;
+ padding-top:5px;
+ padding-bottom:5px;
+ max-height:220px;
+ overflow-y:scroll;
+}
+
+.jeditor-users > div
+{
+ display:flex;
+ align-items:center;
+ min-width:220px;
+ padding:10px;
+ padding-top:5px;
+ padding-bottom:5px;
+}
+
+.jeditor-users > div:hover
+{
+ background-color:#efefef;
+}
+
+.jeditor-users > div img
+{
+ width:24px;
+ height:24px;
+ border-radius:12px;
+ margin-right:5px;
+}
+
+/** Snippet **/
+
+.jsnippet {
+ margin-top:15px;
+ cursor:pointer;
+ border: 1px solid #eee;
+ position:relative;
+}
+
+.jsnippet:focus {
+ outline: none;
+}
+
+.jsnippet img {
+ width:100%;
+}
+
+.jsnippet .jsnippet-title {
+ padding:15px;
+ font-size:1.4em;
+}
+
+.jsnippet .jsnippet-description {
+ padding-left:15px;
+ padding-right:15px;
+ font-size:1em;
+}
+
+.jsnippet .jsnippet-host {
+ padding:15px;
+ text-transform:uppercase;
+ font-size:0.8em;
+ color:#777;
+ text-align:right;
+}
+
+.jsnippet .jsnippet-url {
+ display:none;
+}
+
+.jeditor .jsnippet:after {
+ content:'';
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ position:absolute;
+ top:0;
+ right:0;
+ margin:14px;
+ font-size:24px;
+ width:24px;
+ height:24px;
+ cursor:pointer;
+ text-shadow: 0px 0px 5px #fff;
+}
+
+.jsnippet * {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+
+ -webkit-user-drag: none;
+ -khtml-user-drag: none;
+ -moz-user-drag: none;
+ -o-user-drag: none;
+}
+
+.jeditor img {
+ border:2px solid transparent;
+ box-sizing: border-box;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+
+ -webkit-user-drag: none;
+ -khtml-user-drag: none;
+ -moz-user-drag: none;
+ -o-user-drag: none;
+}
+
+.jeditor img:focus {
+ border:2px solid #0096FD;
+}
+
+.jeditor .pdf {
+ background-image: url("data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 512 512' style='enable-background:new 0 0 512 512;' xml:space='preserve'%3E%3Cpath style='fill:%23C30B15;' d='M511.344,274.266C511.77,268.231,512,262.143,512,256C512,114.615,397.385,0,256,0S0,114.615,0,256 c0,117.769,79.53,216.949,187.809,246.801L511.344,274.266z'/%3E%3Cpath style='fill:%2385080E;' d='M511.344,274.266L314.991,77.913L119.096,434.087l68.714,68.714C209.522,508.787,232.385,512,256,512 C391.243,512,501.976,407.125,511.344,274.266z'/%3E%3Cpolygon style='fill:%23FFFFFF;' points='278.328,333.913 255.711,77.913 119.096,77.913 119.096,311.652 '/%3E%3Cpolygon style='fill:%23E8E6E6;' points='392.904,311.652 392.904,155.826 337.252,133.565 314.991,77.913 255.711,77.913 256.067,333.913 '/%3E%3Cpolygon style='fill:%23FFFFFF;' points='314.991,155.826 314.991,77.913 392.904,155.826 '/%3E%3Crect x='119.096' y='311.652' style='fill:%23FC0F1A;' width='273.809' height='122.435'/%3E%3Cg%3E%3Cpath style='fill:%23FFFFFF;' d='M204.871,346.387c13.547,0,21.341,6.659,21.341,18.465c0,12.412-7.795,19.601-21.341,19.601h-9.611 v14.909h-13.471v-52.975L204.871,346.387L204.871,346.387z M195.26,373.858h8.93c5.904,0,9.308-2.952,9.308-8.552 c0-5.525-3.406-8.324-9.308-8.324h-8.93V373.858z'/%3E%3Cpath style='fill:%23FFFFFF;' d='M257.928,346.387c16.649,0,28.152,10.746,28.152,26.487c0,15.666-11.655,26.488-28.683,26.488 h-22.25v-52.975H257.928z M248.619,388.615h9.611c8.249,0,14.151-6.357,14.151-15.665c0-9.384-6.205-15.817-14.757-15.817h-9.006 V388.615z'/%3E%3Cpath style='fill:%23FFFFFF;' d='M308.563,356.982v12.26h23.763v10.596h-23.763v19.525h-13.471v-52.975h39.277v10.595h-25.806 V356.982z'/%3E%3C/g%3E%3C/svg%3E%0A");
+ background-repeat: no-repeat;
+ background-size: cover;
+ width:60px;
+ height:60px;
+}
+
+
+/**
+ * (c) jLoading
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Page loading spin
+ */
+
+.jloading {
+ position:fixed;
+ z-index:10001;
+ width:100%;
+ left:0;
+ right:0;
+ top:0;
+ bottom:0;
+ background-color: rgba(0,0,0,0.7);
+}
+
+.jloading::after {
+ content:'';
+ display:block;
+ margin:0 auto;
+ margin-top:50vh;
+ width:40px;
+ height:40px;
+ border-style:solid;
+ border-color:white;
+ border-top-color:transparent;
+ border-width:4px;
+ border-radius:50%;
+ -webkit-animation: spin .8s linear infinite;
+ animation: spin .8s linear infinite;
+}
+
+.jloading.spin {
+ background-color:transparent;
+}
+
+.jloading.spin::after {
+ margin:0 auto;
+ margin-top:80px;
+ border-color:#aaa;
+ border-top-color:transparent;
+}
+
+
+.jnotification {
+ position: fixed;
+ z-index: 10000;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 10px;
+}
+
+.jnotification-container {
+ -webkit-box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
+ box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
+ padding: 12px;
+ border-radius: 8px;
+}
+
+.jnotification-close {
+ content: '';
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ font-size: 20px;
+ width: 20px;
+ height: 20px;
+ cursor: pointer;
+}
+
+.jnotification-title {
+ font-weight: bold;
+}
+
+.jnotification-header {
+ display: flex;
+ padding-bottom: 5px;
+}
+
+.jnotification-header:empty {
+ display: none;
+}
+
+.jnotification-image {
+ margin-right: 5px;
+}
+
+.jnotification-image:empty {
+ display: none;
+}
+
+.jnotification-image img {
+ width: 24px;
+}
+
+.jnotification-name {
+ text-transform: uppercase;
+ font-size: 0.9em;
+ flex: 1;
+ letter-spacing: 0.1em;
+}
+
+.jnotification {
+ bottom: 0px;
+}
+.jnotification-container {
+ background-color: #000;
+ background: rgba(92,92,92,1);
+ background: linear-gradient(0deg, rgba(92,92,92,1) 0%, rgba(77,77,77,1) 100%);
+ color: #fff;
+ width: 320px;
+ margin: 30px;
+ padding: 20px;
+}
+
+.jnotification-error .jnotification-container {
+ background: rgb(182,38,6);
+ background: linear-gradient(0deg, rgba(170,41,13,1) 0%, rgba(149,11,11,1) 100%);
+}
+
+@media (max-width: 800px) {
+ .jnotification {
+ top: 0px;
+ width: 100%;
+ }
+ .jnotification-container {
+ background: rgba(255,255,255,0.95);
+ border: 1px solid #eee;
+ color: #444;
+ }
+ .jnotification-error .jnotification-container {
+ background: rgba(255,255,255,0.95);
+ color: #790909;
+ }
+ .jnotification-close {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ }
+}
+
+.jnotification-header {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+}
+
+.jpicker {
+ cursor: pointer;
+ white-space: nowrap;
+ display: inline-flex;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ outline: none;
+}
+
+.jpicker-header {
+ background-repeat: no-repeat;
+ background-position: top 50% right 5px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 10l5 5 5-5H7z' fill='gray'/%3E%3C/svg%3E");
+ text-overflow: ellipsis;
+ cursor: pointer;
+ box-sizing: border-box;
+ text-align: left;
+ outline: none;
+
+ line-height: 24px;
+ padding: 2px;
+ padding-left: 12px;
+ padding-right: 35px;
+ outline: none;
+ border-radius: 4px;
+}
+
+.jpicker-header:hover {
+ background-color: #eee;
+}
+
+.jpicker-content {
+ position: absolute;
+ display: none;
+ box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
+ border-radius: 4px;
+ background-color: #fff;
+ padding: 4px;
+ z-index: 50;
+ text-align: left;
+}
+
+.jpicker-content div {
+ padding: 6px;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+.jpicker-focus .jpicker-content {
+ display: block;
+}
+
+.jpicker-content div:hover {
+ background-color:#efefef;
+}
+
+
+
+.jrating {
+ display:flex;
+}
+.jrating > div {
+ width:24px;
+ height:24px;
+ line-height:24px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z' fill='gray'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+}
+
+.jrating .jrating-over {
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ opacity: 0.7;
+}
+
+.jrating .jrating-selected {
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='red'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+}
+
+
+.jtabs {
+ max-width: 100vw;
+ position: relative;
+}
+
+.jtabs .jtabs-headers-container {
+ display: flex;
+ align-items: center;
+}
+
+.jtabs .jtabs-headers {
+ display: flex;
+ align-items: center;
+ overflow: hidden;
+ position: relative;
+}
+
+.jtabs .jtabs-headers > div:not(.jtabs-border) {
+ padding: 6px;
+ padding-left: 20px;
+ padding-right: 20px;
+ margin-left: 1px;
+ margin-right: 1px;
+ margin-bottom: 1px;
+ background-color: #f1f1f1;
+ cursor: pointer;
+ white-space: nowrap;
+}
+
+.jtabs .jtabs-headers > div.jtabs-selected {
+ background-color: #e8e8e8;
+ color: #000;
+}
+
+.jtabs .jtabs-content {
+ box-sizing: border-box;
+}
+
+.jtabs .jtabs-content > div {
+ display: none;
+ box-sizing: border-box;
+}
+
+.jtabs .jtabs-content > div.jtabs-selected {
+ display: block;
+}
+
+.jtabs .jtabs-border {
+ position: absolute;
+ height: 2px;
+ background-color: #888;
+ transform-origin: left;
+ transition: all .2s cubic-bezier(0.4,0,0.2,1);
+ transition-property: color,left,transform;
+ display: none;
+}
+
+.jtabs-animation .jtabs-border {
+ display: initial;
+}
+
+.jtabs .jtabs-controls {
+ margin: 3px;
+ margin-left: 10px;
+ display: flex;
+ min-width: 82px;
+}
+
+.jtabs .jtabs-controls > div {
+ cursor: pointer;
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 24px;
+ height: 24px;
+ line-height: 24px;
+}
+
+.jtabs .jtabs-prev {
+ margin-left: 10px;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='gray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-prev.disabled {
+ margin-left: 10px;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='lightgray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-next {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='gray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-next.disabled {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='lightgray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-add {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24' viewBox='0 0 24 24' width='24'%3E%3Cpath d='M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z' fill='%23bbbbbb'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+}
+
+.jtoolbar-container {
+ border-radius: 2px;
+ margin-bottom: 5px;
+ box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
+ display: inline-flex !important;
+}
+
+.jtoolbar {
+ cursor: pointer;
+ white-space: nowrap;
+ display: flex;
+ padding:4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.jtoolbar-mobile {
+ display: flex;
+ position:fixed;
+ bottom: 0;
+ margin: 0;
+ left: 0;
+ width: 100%;
+ background: #f7f7f8;
+ z-index: 1;
+ box-sizing: border-box;
+ box-shadow: 0 -1px 2px rgba(0,0,0,.1);
+ border-radius: 0px;
+}
+
+.jtoolbar > div {
+ display: inline-flex;
+ align-items: center;
+ box-sizing: border-box;
+ vertical-align:middle;
+ justify-content: space-evenly;
+}
+
+.jtoolbar-mobile > div {
+ display: flex;
+ width: 100%;
+}
+
+.jtoolbar .jtoolbar-item {
+ position: relative;
+ text-align: center;
+ margin: auto;
+ padding: 2px;
+ padding-left:4px;
+ padding-right:4px;
+}
+
+.jtoolbar-mobile .jtoolbar-item {
+ flex:1;
+}
+
+.jtoolbar .jtoolbar-divisor {
+ width: 2px;
+ height: 24px;
+ padding: 0px;
+ margin-left: 4px;
+ margin-right: 4px;
+ background-color: #f2f2f2;
+}
+
+
+.jtoolbar-mobile a
+{
+ text-decoration:none;
+ display:inline-block;
+}
+
+.jtoolbar-mobile i {
+ display: inline-flex !important;
+ color:#929292;
+}
+
+.jtoolbar-mobile span {
+ font-size:0.7em;
+ display:block;
+ color:#929292;
+}
+
+.jtoolbar-mobile .jtoolbar-selected a, .jtoolbar-mobile .jtoolbar-selected i, .jtoolbar-mobile .jtoolbar-selected span {
+ color:var(--active-color) !important;
+ background-color:transparent;
+}
+
+.jtoolbar-item {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.jtoolbar-item i {
+ display: block;
+ color:#333;
+}
+
+.jtoolbar-item:hover {
+ background-color:#f2f2f2;
+}
+
+
+.jtoolbar .jpicker {
+ padding-left:0px;
+ padding-right:0px;
+}
+
+.jtoolbar .jpicker-header {
+ height: 24px;
+ line-height: 24px;
+ padding: 0px;
+ padding-right: 20px;
+ padding-left: 4px;
+ background-position: top 50% right 0px;
+}
+
+.jtoolbar .jpicker-content div {
+ padding: 6px;
+}
+
+.jtoolbar-active {
+ background-color:#eee;
+}
+
+.jtoolbar .fa {
+ width: 24px;
+ height: 24px;
+ display: block;
+ line-height: 24px;
+}
+
+
+
diff --git a/web-tools/web/_static/jsuites/jsuites.basic.js b/web-tools/web/_static/jsuites/jsuites.basic.js
new file mode 100644
index 0000000..e6cef59
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.basic.js
@@ -0,0 +1,6737 @@
+/**
+ * (c) jSuites Javascript Web Components (v3.7.0)
+ *
+ * Author: Paul Hodel <paul.hodel@gmail.com>
+ * Website: https://bossanova.uk/jsuites/
+ * Description: Create amazing web based applications.
+ *
+ * MIT License
+ *
+ */
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ global.jSuites = factory();
+}(this, (function () {
+
+ 'use strict';
+
+var jSuites = function(options) {
+ var obj = {}
+
+ obj.init = function() {
+ }
+
+ return obj;
+}
+
+jSuites.ajax = (function(options, complete) {
+ if (Array.isArray(options)) {
+ // Create multiple request controller
+ var multiple = {
+ instance: [],
+ complete: complete,
+ }
+
+ if (options.length > 0) {
+ for (var i = 0; i < options.length; i++) {
+ options[i].multiple = multiple;
+ multiple.instance.push(jSuites.ajax(options[i]));
+ }
+ }
+
+ return multiple;
+ }
+
+ if (! options.data) {
+ options.data = {};
+ }
+
+ if (options.type) {
+ options.method = options.type;
+ }
+
+ // Default method
+ if (! options.method) {
+ options.method = 'GET';
+ }
+
+ // Default type
+ if (! options.dataType) {
+ options.dataType = 'json';
+ }
+
+ if (options.data) {
+ // Parse object to variables format
+ var parseData = function(value, key) {
+ var vars = [];
+ var keys = Object.keys(value);
+ if (keys.length) {
+ for (var i = 0; i < keys.length; i++) {
+ if (key) {
+ var k = key + '[' + keys[i] + ']';
+ } else {
+ var k = keys[i];
+ }
+
+ if (typeof(value[keys[i]]) == 'object') {
+ var r = parseData(value[keys[i]], k);
+ var o = Object.keys(r);
+ for (var j = 0; j < o.length; j++) {
+ vars[o[j]] = r[o[j]];
+ }
+ } else {
+ vars[k] = value[keys[i]];
+ }
+ }
+ }
+
+ return vars;
+ }
+
+ var data = [];
+ var d = parseData(options.data);
+ var k = Object.keys(d);
+ for (var i = 0; i < k.length; i++) {
+ data.push(k[i] + '=' + encodeURIComponent(d[k[i]]));
+ }
+
+ if (options.method == 'GET' && data.length > 0) {
+ if (options.url.indexOf('?') < 0) {
+ options.url += '?';
+ }
+ options.url += data.join('&');
+ }
+ }
+
+ var httpRequest = new XMLHttpRequest();
+ httpRequest.open(options.method, options.url, true);
+ httpRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+
+ if (options.method == 'POST') {
+ httpRequest.setRequestHeader('Accept', 'application/json');
+ httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ } else {
+ if (options.dataType == 'json') {
+ httpRequest.setRequestHeader('Content-Type', 'text/json');
+ }
+ }
+
+ // No cache
+ if (options.cache != true) {
+ httpRequest.setRequestHeader('pragma', 'no-cache');
+ httpRequest.setRequestHeader('cache-control', 'no-cache');
+ }
+
+ // Authentication
+ if (options.withCredentials == true) {
+ httpRequest.withCredentials = true
+ }
+
+ // Before send
+ if (typeof(options.beforeSend) == 'function') {
+ options.beforeSend(httpRequest);
+ }
+
+ httpRequest.onload = function() {
+ if (httpRequest.status === 200) {
+ if (options.dataType == 'json') {
+ try {
+ var result = JSON.parse(httpRequest.responseText);
+
+ if (options.success && typeof(options.success) == 'function') {
+ options.success(result);
+ }
+ } catch(err) {
+ if (options.error && typeof(options.error) == 'function') {
+ options.error(err, result);
+ }
+ }
+ } else {
+ var result = httpRequest.responseText;
+
+ if (options.success && typeof(options.success) == 'function') {
+ options.success(result);
+ }
+ }
+ } else {
+ if (options.error && typeof(options.error) == 'function') {
+ options.error(httpRequest.responseText);
+ }
+ }
+
+ // Global queue
+ if (jSuites.ajax.queue && jSuites.ajax.queue.length > 0) {
+ jSuites.ajax.send(jSuites.ajax.queue.shift());
+ }
+
+ // Global complete method
+ if (jSuites.ajax.requests && jSuites.ajax.requests.length) {
+ // Get index of this request in the container
+ var index = jSuites.ajax.requests.indexOf(httpRequest);
+ // Remove from the ajax requests container
+ jSuites.ajax.requests.splice(index, 1);
+ // Last one?
+ if (! jSuites.ajax.requests.length) {
+ if (options.complete && typeof(options.complete) == 'function') {
+ options.complete(result);
+ }
+ }
+ // Controllers
+ if (options.multiple && options.multiple.instance) {
+ // Get index of this request in the container
+ var index = options.multiple.instance.indexOf(httpRequest);
+ // Remove from the ajax requests container
+ options.multiple.instance.splice(index, 1);
+ // If this is the last one call method complete
+ if (! options.multiple.instance.length) {
+ if (options.multiple.complete && typeof(options.multiple.complete) == 'function') {
+ options.multiple.complete(result);
+ }
+ }
+ }
+ }
+ }
+
+ // Data
+ httpRequest.data = data;
+
+ // Queue
+ if (options.queue == true && jSuites.ajax.requests.length > 0) {
+ jSuites.ajax.queue.push(httpRequest);
+ } else {
+ jSuites.ajax.send(httpRequest)
+ }
+
+ return httpRequest;
+});
+
+jSuites.ajax.send = function(httpRequest) {
+ if (httpRequest.data) {
+ httpRequest.send(httpRequest.data.join('&'));
+ } else {
+ httpRequest.send();
+ }
+
+ jSuites.ajax.requests.push(httpRequest);
+}
+
+jSuites.ajax.exists = function(url, __callback) {
+ var http = new XMLHttpRequest();
+ http.open('HEAD', url, false);
+ http.send();
+ if (http.status) {
+ __callback(http.status);
+ }
+}
+
+jSuites.ajax.requests = [];
+
+jSuites.ajax.queue = [];
+
+jSuites.animation = {};
+
+jSuites.animation.slideLeft = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-left-in');
+ setTimeout(function() {
+ element.classList.remove('slide-left-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-left-out');
+ setTimeout(function() {
+ element.classList.remove('slide-left-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ }
+}
+
+jSuites.animation.slideRight = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-right-in');
+ setTimeout(function() {
+ element.classList.remove('slide-right-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-right-out');
+ setTimeout(function() {
+ element.classList.remove('slide-right-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ }
+}
+
+jSuites.animation.slideTop = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-top-in');
+ setTimeout(function() {
+ element.classList.remove('slide-top-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-top-out');
+ setTimeout(function() {
+ element.classList.remove('slide-top-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ }
+}
+
+jSuites.animation.slideBottom = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-bottom-in');
+ setTimeout(function() {
+ element.classList.remove('slide-bottom-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-bottom-out');
+ setTimeout(function() {
+ element.classList.remove('slide-bottom-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 100);
+ }
+}
+
+jSuites.animation.fadeIn = function(element, done) {
+ element.classList.add('fade-in');
+ setTimeout(function() {
+ element.classList.remove('fade-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 2000);
+}
+
+jSuites.animation.fadeOut = function(element, done) {
+ element.classList.add('fade-out');
+ setTimeout(function() {
+ element.classList.remove('fade-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 1000);
+}
+
+jSuites.calendar = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Global container
+ if (! jSuites.calendar.current) {
+ jSuites.calendar.current = null;
+ }
+
+ // Default configuration
+ var defaults = {
+ // Render type: [ default | year-month-picker ]
+ type: 'default',
+ // Restrictions
+ validRange: null,
+ // Starting weekday - 0 for sunday, 6 for saturday
+ startingDay: null,
+ // Date format
+ format: 'DD/MM/YYYY',
+ // Allow keyboard date entry
+ readonly: true,
+ // Today is default
+ today: false,
+ // Show timepicker
+ time: false,
+ // Show the reset button
+ resetButton: true,
+ // Placeholder
+ placeholder: '',
+ // Translations can be done here
+ months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ monthsFull: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ weekdays: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
+ weekdays_short: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
+ textDone: 'Done',
+ textReset: 'Reset',
+ textUpdate: 'Update',
+ // Value
+ value: null,
+ // Fullscreen (this is automatic set for screensize < 800)
+ fullscreen: false,
+ // Create the calendar closed as default
+ opened: false,
+ // Events
+ onopen: null,
+ onclose: null,
+ onchange: null,
+ onupdate: null,
+ // Internal mode controller
+ mode: null,
+ position: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Value
+ if (! obj.options.value) {
+ if (el.tagName == 'INPUT' && el.value) {
+ obj.options.value = el.value;
+ }
+ }
+
+ // Date
+ obj.date = null;
+
+ if (obj.options.value) {
+ obj.date = jSuites.calendar.toArray(obj.options.value);
+ } else {
+ if (obj.options.today) {
+ var date = new Date();
+ var y = date.getFullYear();
+ var m = date.getMonth() + 1;
+ var d = date.getDate();
+ var h = date.getHours();
+ var i = date.getMinutes();
+
+ obj.date = [ y, m, d, h, i, 0 ];
+ }
+ }
+
+ // Calendar elements
+ var calendarReset = document.createElement('div');
+ calendarReset.className = 'jcalendar-reset';
+ calendarReset.innerHTML = obj.options.textReset;
+
+ var calendarConfirm = document.createElement('div');
+ calendarConfirm.className = 'jcalendar-confirm';
+ calendarConfirm.innerHTML = obj.options.textDone;
+
+ var calendarControls = document.createElement('div');
+ calendarControls.className = 'jcalendar-controls'
+ calendarControls.style.borderBottom = '1px solid #ddd';
+
+ if (obj.options.resetButton) {
+ calendarControls.appendChild(calendarReset);
+ }
+ calendarControls.appendChild(calendarConfirm);
+
+ var calendarContainer = document.createElement('div');
+ calendarContainer.className = 'jcalendar-container';
+
+ var calendarContent = document.createElement('div');
+ calendarContent.className = 'jcalendar-content';
+ calendarContainer.appendChild(calendarContent);
+
+ // Main element
+ if (el.tagName == 'DIV') {
+ var calendar = el;
+ calendar.className = 'jcalendar-inline';
+ } else {
+ // Add controls to the screen
+ calendarContent.appendChild(calendarControls);
+
+ var calendar = document.createElement('div');
+ calendar.className = 'jcalendar';
+ }
+ calendar.appendChild(calendarContainer);
+
+ // Table container
+ var calendarTableContainer = document.createElement('div');
+ calendarTableContainer.className = 'jcalendar-table';
+ calendarContent.appendChild(calendarTableContainer);
+
+ // Previous button
+ var calendarHeaderPrev = document.createElement('td');
+ calendarHeaderPrev.setAttribute('colspan', '2');
+ calendarHeaderPrev.className = 'jcalendar-prev';
+
+ // Header with year and month
+ var calendarLabelYear = document.createElement('span');
+ calendarLabelYear.className = 'jcalendar-year';
+
+ var calendarLabelMonth = document.createElement('span');
+ calendarLabelMonth.className = 'jcalendar-month';
+
+ var calendarHeaderTitle = document.createElement('td');
+ calendarHeaderTitle.className = 'jcalendar-header';
+ calendarHeaderTitle.setAttribute('colspan', '3');
+ calendarHeaderTitle.appendChild(calendarLabelMonth);
+ calendarHeaderTitle.appendChild(calendarLabelYear);
+
+ var calendarHeaderNext = document.createElement('td');
+ calendarHeaderNext.setAttribute('colspan', '2');
+ calendarHeaderNext.className = 'jcalendar-next';
+
+ var calendarHeaderRow = document.createElement('tr');
+ calendarHeaderRow.appendChild(calendarHeaderPrev);
+ calendarHeaderRow.appendChild(calendarHeaderTitle);
+ calendarHeaderRow.appendChild(calendarHeaderNext);
+
+ var calendarHeader = document.createElement('thead');
+ calendarHeader.appendChild(calendarHeaderRow);
+
+ var calendarBody = document.createElement('tbody');
+ var calendarFooter = document.createElement('tfoot');
+
+ // Calendar table
+ var calendarTable = document.createElement('table');
+ calendarTable.setAttribute('cellpadding', '0');
+ calendarTable.setAttribute('cellspacing', '0');
+ calendarTable.appendChild(calendarHeader);
+ calendarTable.appendChild(calendarBody);
+ calendarTable.appendChild(calendarFooter);
+ calendarTableContainer.appendChild(calendarTable);
+
+ var calendarSelectHour = document.createElement('select');
+ calendarSelectHour.className = 'jcalendar-select';
+ calendarSelectHour.onchange = function() {
+ obj.date[3] = this.value;
+
+ // Event
+ if (typeof(obj.options.onupdate) == 'function') {
+ obj.options.onupdate(el, obj.getValue());
+ }
+ }
+
+ for (var i = 0; i < 24; i++) {
+ var element = document.createElement('option');
+ element.value = i;
+ element.innerHTML = jSuites.two(i);
+ calendarSelectHour.appendChild(element);
+ }
+
+ var calendarSelectMin = document.createElement('select');
+ calendarSelectMin.className = 'jcalendar-select';
+ calendarSelectMin.onchange = function() {
+ obj.date[4] = this.value;
+
+ // Event
+ if (typeof(obj.options.onupdate) == 'function') {
+ obj.options.onupdate(el, obj.getValue());
+ }
+ }
+
+ for (var i = 0; i < 60; i++) {
+ var element = document.createElement('option');
+ element.value = i;
+ element.innerHTML = jSuites.two(i);
+ calendarSelectMin.appendChild(element);
+ }
+
+ // Footer controls
+ var calendarControlsFooter = document.createElement('div');
+ calendarControlsFooter.className = 'jcalendar-controls';
+
+ var calendarControlsTime = document.createElement('div');
+ calendarControlsTime.className = 'jcalendar-time';
+ calendarControlsTime.style.maxWidth = '140px';
+ calendarControlsTime.appendChild(calendarSelectHour);
+ calendarControlsTime.appendChild(calendarSelectMin);
+
+ var calendarControlsUpdateButton = document.createElement('input');
+ calendarControlsUpdateButton.setAttribute('type', 'button');
+ calendarControlsUpdateButton.className = 'jcalendar-update';
+ calendarControlsUpdateButton.value = obj.options.textUpdate;
+
+ var calendarControlsUpdate = document.createElement('div');
+ calendarControlsUpdate.style.flexGrow = '10';
+ calendarControlsUpdate.appendChild(calendarControlsUpdateButton);
+ calendarControlsFooter.appendChild(calendarControlsTime);
+
+ // Only show the update button for input elements
+ if (el.tagName == 'INPUT') {
+ calendarControlsFooter.appendChild(calendarControlsUpdate);
+ }
+
+ calendarContent.appendChild(calendarControlsFooter);
+
+ var calendarBackdrop = document.createElement('div');
+ calendarBackdrop.className = 'jcalendar-backdrop';
+ calendar.appendChild(calendarBackdrop);
+
+ // Update actions button
+ var updateActions = function() {
+ var currentDay = calendar.querySelector('.jcalendar-selected');
+
+ if (currentDay && currentDay.classList.contains('jcalendar-disabled')) {
+ calendarControlsUpdateButton.setAttribute('disabled', 'disabled');
+ calendarSelectHour.setAttribute('disabled', 'disabled');
+ calendarSelectMin.setAttribute('disabled', 'disabled');
+ } else {
+ calendarControlsUpdateButton.removeAttribute('disabled');
+ calendarSelectHour.removeAttribute('disabled');
+ calendarSelectMin.removeAttribute('disabled');
+ }
+ }
+
+ /**
+ * Open the calendar
+ */
+ obj.open = function (value) {
+ if (! calendar.classList.contains('jcalendar-focus')) {
+ if (! calendar.classList.contains('jcalendar-inline')) {
+ obj.getDays();
+ // Get content
+ if (obj.options.type == 'year-month-picker') {
+ obj.getMonths();
+ }
+ // Get time
+ if (obj.options.time) {
+ calendarSelectHour.value = obj.date[3];
+ calendarSelectMin.value = obj.date[4];
+ }
+
+ if (jSuites.calendar.current) {
+ jSuites.calendar.current.close();
+ }
+ // Current
+ jSuites.calendar.current = obj;
+ // Show calendar
+ calendar.classList.add('jcalendar-focus');
+
+ // Get the position of the corner helper
+ if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen) {
+ // Full
+ calendar.classList.add('jcalendar-fullsize');
+ // Animation
+ jSuites.animation.slideBottom(calendarContent, 1);
+ } else {
+ var rect = el.getBoundingClientRect();
+ var rectContent = calendarContent.getBoundingClientRect();
+
+ if (obj.options.position) {
+ calendarContainer.style.position = 'fixed';
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ calendarContainer.style.top = (rect.top - (rectContent.height + 2)) + 'px';
+ } else {
+ calendarContainer.style.top = (rect.top + rect.height + 2) + 'px';
+ }
+ calendarContainer.style.left = rect.left + 'px';
+ } else {
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ calendarContainer.style.bottom = (1 * rect.height + rectContent.height + 2) + 'px';
+ } else {
+ calendarContainer.style.top = 2 + 'px';
+ }
+ }
+ }
+
+ // Events
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el);
+ }
+ }
+ }
+ }
+
+ obj.close = function (ignoreEvents, update) {
+ if (jSuites.calendar.current) {
+ // Current
+ jSuites.calendar.current = null;
+
+ if (update !== false) {
+ var element = calendar.querySelector('.jcalendar-selected');
+
+ if (typeof(update) == 'string') {
+ var value = update;
+ } else if (element && element.classList.contains('jcalendar-disabled')) {
+ var value = obj.options.value
+ } else {
+ var value = obj.getValue();
+ }
+
+ obj.setValue(value);
+ }
+
+ // Events
+ if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el);
+ }
+
+ // Hide
+ calendar.classList.remove('jcalendar-focus');
+ }
+
+ return obj.options.value;
+ }
+
+ obj.prev = function() {
+ // Check if the visualization is the days picker or years picker
+ if (obj.options.mode == 'years') {
+ obj.date[0] = obj.date[0] - 12;
+
+ // Update picker table of days
+ obj.getYears();
+ } else if (obj.options.mode == 'months') {
+ obj.date[0] = parseInt(obj.date[0]) - 1;
+ // Update picker table of months
+ obj.getMonths();
+ } else {
+ // Go to the previous month
+ if (obj.date[1] < 2) {
+ obj.date[0] = obj.date[0] - 1;
+ obj.date[1] = 12;
+ } else {
+ obj.date[1] = obj.date[1] - 1;
+ }
+
+ // Update picker table of days
+ obj.getDays();
+ }
+ }
+
+ obj.next = function() {
+ // Check if the visualization is the days picker or years picker
+ if (obj.options.mode == 'years') {
+ obj.date[0] = parseInt(obj.date[0]) + 12;
+
+ // Update picker table of days
+ obj.getYears();
+ } else if (obj.options.mode == 'months') {
+ obj.date[0] = parseInt(obj.date[0]) + 1;
+ // Update picker table of months
+ obj.getMonths();
+ } else {
+ // Go to the previous month
+ if (obj.date[1] > 11) {
+ obj.date[0] = parseInt(obj.date[0]) + 1;
+ obj.date[1] = 1;
+ } else {
+ obj.date[1] = parseInt(obj.date[1]) + 1;
+ }
+
+ // Update picker table of days
+ obj.getDays();
+ }
+ }
+
+ obj.setValue = function(val) {
+ if (! val) {
+ val = '' + val;
+ }
+ // Values
+ var newValue = val;
+ var oldValue = obj.options.value;
+
+ if (oldValue != newValue) {
+ // Set label
+ var value = obj.setLabel(newValue, obj.options);
+ var date = newValue.split(' ');
+ if (! date[1]) {
+ date[1] = '00:00:00';
+ }
+ var time = date[1].split(':')
+ var date = date[0].split('-');
+ var y = parseInt(date[0]);
+ var m = parseInt(date[1]);
+ var d = parseInt(date[2]);
+ var h = parseInt(time[0]);
+ var i = parseInt(time[1]);
+ obj.date = [ y, m, d, h, i, 0 ];
+ var val = obj.setLabel(newValue, obj.options);
+
+ // New value
+ obj.options.value = newValue;
+
+ // Input value
+ if (el.tagName == 'INPUT') {
+ el.value = val;
+ }
+
+ // Events
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: el });
+ }
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, newValue, oldValue);
+ }
+ }
+
+ obj.getDays();
+ }
+
+ obj.getValue = function() {
+ if (obj.date) {
+ if (obj.options.time) {
+ return jSuites.two(obj.date[0]) + '-' + jSuites.two(obj.date[1]) + '-' + jSuites.two(obj.date[2]) + ' ' + jSuites.two(obj.date[3]) + ':' + jSuites.two(obj.date[4]) + ':' + jSuites.two(0);
+ } else {
+ return jSuites.two(obj.date[0]) + '-' + jSuites.two(obj.date[1]) + '-' + jSuites.two(obj.date[2]) + ' ' + jSuites.two(0) + ':' + jSuites.two(0) + ':' + jSuites.two(0);
+ }
+ } else {
+ return "";
+ }
+ }
+
+ /**
+ * Calendar
+ */
+ obj.update = function(element) {
+ if (element.classList.contains('jcalendar-disabled')) {
+ // Do nothing
+ } else {
+ obj.date[2] = element.innerText;
+
+ var elements = calendar.querySelector('.jcalendar-selected');
+ if (elements) {
+ elements.classList.remove('jcalendar-selected');
+ }
+ element.classList.add('jcalendar-selected');
+
+ if (! obj.options.time) {
+ obj.close();
+ } else {
+ obj.date[3] = calendarSelectHour.value;
+ obj.date[4] = calendarSelectMin.value;
+ }
+
+ // Event
+ if (typeof(obj.options.onupdate) == 'function') {
+ obj.options.onupdate(el, obj.getValue());
+ }
+ }
+
+ // Update
+ updateActions();
+ }
+
+ /**
+ * Set to blank
+ */
+ obj.reset = function() {
+ // Close calendar
+ obj.setValue('');
+ obj.close(false, false);
+ }
+
+ /**
+ * Get calendar days
+ */
+ obj.getDays = function() {
+ // Mode
+ obj.options.mode = 'days';
+
+ // Setting current values in case of NULLs
+ var date = new Date();
+
+ // Current selection
+ var year = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear());
+ var month = obj.date && jSuites.isNumeric(obj.date[1]) ? obj.date[1] : parseInt(date.getMonth()) + 1;
+ var day = obj.date && jSuites.isNumeric(obj.date[2]) ? obj.date[2] : parseInt(date.getDate());
+ var hour = obj.date && jSuites.isNumeric(obj.date[3]) ? obj.date[3] : parseInt(date.getHours());
+ var min = obj.date && jSuites.isNumeric(obj.date[4]) ? obj.date[4] : parseInt(date.getMinutes());
+
+ // Selection container
+ obj.date = [ year, month, day, hour, min, 0 ];
+
+ // Update title
+ calendarLabelYear.innerHTML = year;
+ calendarLabelMonth.innerHTML = obj.options.months[month - 1];
+
+ // Current month and Year
+ var isCurrentMonthAndYear = (date.getMonth() == month - 1) && (date.getFullYear() == year) ? true : false;
+ var currentDay = date.getDate();
+
+ // Number of days in the month
+ var date = new Date(year, month, 0, 0, 0);
+ var numberOfDays = date.getDate();
+
+ // First day
+ var date = new Date(year, month-1, 0, 0, 0);
+ var firstDay = date.getDay() + 1;
+
+ // Index value
+ var index = obj.options.startingDay || 0;
+
+ // First of day relative to the starting calendar weekday
+ firstDay = firstDay - index;
+
+ // Reset table
+ calendarBody.innerHTML = '';
+
+ // Weekdays Row
+ var row = document.createElement('tr');
+ row.setAttribute('align', 'center');
+ calendarBody.appendChild(row);
+
+ // Create weekdays row
+ for (var i = 0; i < 7; i++) {
+ var cell = document.createElement('td');
+ cell.classList.add('jcalendar-weekday')
+ cell.innerHTML = obj.options.weekdays_short[index];
+ row.appendChild(cell);
+ // Next week day
+ index++;
+ // Restart index
+ if (index > 6) {
+ index = 0;
+ }
+ }
+
+ // Index of days
+ var index = 0;
+ var d = 0;
+
+ // Calendar table
+ for (var j = 0; j < 6; j++) {
+ // Reset cells container
+ var row = document.createElement('tr');
+ row.setAttribute('align', 'center');
+ // Data control
+ var emptyRow = true;
+ // Create cells
+ for (var i = 0; i < 7; i++) {
+ // Create cell
+ var cell = document.createElement('td');
+ cell.classList.add('jcalendar-set-day');
+
+ if (index >= firstDay && index < (firstDay + numberOfDays)) {
+ // Day cell
+ d++;
+ cell.innerHTML = d;
+
+ // Selected
+ if (d == day) {
+ cell.classList.add('jcalendar-selected');
+ }
+
+ // Current selection day is today
+ if (isCurrentMonthAndYear && currentDay == d) {
+ cell.style.fontWeight = 'bold';
+ }
+
+ // Current selection day
+ var current = jSuites.calendar.now(new Date(year, month-1, d), true);
+
+ // Available ranges
+ if (obj.options.validRange) {
+ if (! obj.options.validRange[0] || current >= obj.options.validRange[0]) {
+ var test1 = true;
+ } else {
+ var test1 = false;
+ }
+
+ if (! obj.options.validRange[1] || current <= obj.options.validRange[1]) {
+ var test2 = true;
+ } else {
+ var test2 = false;
+ }
+
+ if (! (test1 && test2)) {
+ cell.classList.add('jcalendar-disabled');
+ }
+ }
+
+ // Control
+ emptyRow = false;
+ }
+ // Day cell
+ row.appendChild(cell);
+ // Index
+ index++;
+ }
+
+ // Add cell to the calendar body
+ if (emptyRow == false) {
+ calendarBody.appendChild(row);
+ }
+ }
+
+ // Show time controls
+ if (obj.options.time) {
+ calendarControlsTime.style.display = '';
+ } else {
+ calendarControlsTime.style.display = 'none';
+ }
+
+ // Update
+ updateActions();
+ }
+
+ obj.getMonths = function() {
+ // Mode
+ obj.options.mode = 'months';
+
+ // Loading month labels
+ var months = obj.options.months;
+
+ // Update title
+ calendarLabelYear.innerHTML = obj.date[0];
+ calendarLabelMonth.innerHTML = '';
+
+ // Create months table
+ var html = '<td colspan="7"><table width="100%"><tr align="center">';
+
+ for (i = 0; i < 12; i++) {
+ if ((i > 0) && (!(i % 4))) {
+ html += '</tr><tr align="center">';
+ }
+
+ var month = parseInt(i) + 1;
+ html += '<td class="jcalendar-set-month" data-value="' + month + '">' + months[i] +'</td>';
+ }
+
+ html += '</tr></table></td>';
+
+ calendarBody.innerHTML = html;
+ }
+
+ obj.getYears = function() {
+ // Mode
+ obj.options.mode = 'years';
+
+ // Array of years
+ var y = [];
+ for (i = 0; i < 25; i++) {
+ y[i] = parseInt(obj.date[0]) + (i - 12);
+ }
+
+ // Assembling the year tables
+ var html = '<td colspan="7"><table width="100%"><tr align="center">';
+
+ for (i = 0; i < 25; i++) {
+ if ((i > 0) && (!(i % 5))) {
+ html += '</tr><tr align="center">';
+ }
+ html += '<td class="jcalendar-set-year">'+ y[i] +'</td>';
+ }
+
+ html += '</tr></table></td>';
+
+ calendarBody.innerHTML = html;
+ }
+
+ obj.setLabel = function(value, mixed) {
+ return jSuites.calendar.getDateString(value, mixed);
+ }
+
+ obj.fromFormatted = function (value, format) {
+ return jSuites.calendar.extractDateFromString(value, format);
+ }
+
+ var mouseUpControls = function(e) {
+ var action = e.target.className;
+
+ // Object id
+ if (action == 'jcalendar-prev') {
+ obj.prev();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-next') {
+ obj.next();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-month') {
+ obj.getMonths();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-year') {
+ obj.getYears();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-set-year') {
+ obj.date[0] = e.target.innerText;
+ if (obj.options.type == 'year-month-picker') {
+ obj.getMonths();
+ } else {
+ obj.getDays();
+ }
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-set-month') {
+ obj.date[1] = parseInt(e.target.getAttribute('data-value'));
+ if (obj.options.type == 'year-month-picker') {
+ obj.close();
+ } else {
+ obj.getDays();
+ }
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update') {
+ obj.close();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-close') {
+ obj.close();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-backdrop') {
+ obj.close(false, false);
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-reset') {
+ obj.reset();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (e.target.classList.contains('jcalendar-set-day')) {
+ if (e.target.innerText) {
+ obj.update(e.target);
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ }
+
+ var keyUpControls = function(e) {
+ if (e.target.value && e.target.value.length > 3) {
+ var test = jSuites.calendar.extractDateFromString(e.target.value, obj.options.format);
+ if (test) {
+ if (e.target.getAttribute('data-completed') == 'true') {
+ obj.setValue(test);
+ }
+ }
+ }
+ }
+
+ // Handle events
+ el.addEventListener("keyup", keyUpControls);
+
+ // Add global events
+ calendar.addEventListener("swipeleft", function(e) {
+ jSuites.animation.slideLeft(calendarTable, 0, function() {
+ obj.next();
+ jSuites.animation.slideRight(calendarTable, 1);
+ });
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ calendar.addEventListener("swiperight", function(e) {
+ jSuites.animation.slideRight(calendarTable, 0, function() {
+ obj.prev();
+ jSuites.animation.slideLeft(calendarTable, 1);
+ });
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ if ('ontouchend' in document.documentElement === true) {
+ calendar.addEventListener("touchend", mouseUpControls);
+
+ el.addEventListener("touchend", function(e) {
+ obj.open();
+ });
+ } else {
+ calendar.addEventListener("mouseup", mouseUpControls);
+
+ el.addEventListener("mouseup", function(e) {
+ obj.open();
+ });
+ }
+
+ if (! jSuites.calendar.hasEvents) {
+ if ('ontouchstart' in document.documentElement === true) {
+ document.addEventListener("touchstart", jSuites.calendar.isOpen);
+ } else {
+ document.addEventListener("mousedown", jSuites.calendar.isOpen);
+ }
+
+ document.addEventListener("keydown", function(e) {
+ if (e.which == 13) {
+ // ENTER
+ if (jSuites.calendar.current) {
+ jSuites.calendar.current.close(false, true);
+ }
+ } else if (e.which == 27) {
+ // ESC
+ if (jSuites.calendar.current) {
+ jSuites.calendar.current.close(false, false);
+ }
+ }
+ });
+
+ jSuites.calendar.hasEvents = true;
+ }
+
+ // Append element to the DOM
+ if (el.tagName == 'INPUT') {
+ el.parentNode.insertBefore(calendar, el.nextSibling);
+ // Add properties
+ el.setAttribute('autocomplete', 'off');
+ el.setAttribute('data-mask', obj.options.format.toLowerCase());
+
+ if (obj.options.readonly) {
+ el.setAttribute('readonly', 'readonly');
+ }
+ if (obj.options.placeholder) {
+ el.setAttribute('placeholder', obj.options.placeholder);
+ }
+ // Element
+ el.classList.add('jcalendar-input');
+ // Value
+ el.value = obj.setLabel(obj.getValue(), obj.options);
+ } else {
+ // Get days
+ obj.getDays();
+ // Hour
+ if (obj.options.time) {
+ calendarSelectHour.value = obj.date[3];
+ calendarSelectMin.value = obj.date[4];
+ }
+ }
+
+ // Keep object available from the node
+ el.calendar = obj;
+ el.change = obj.setValue;
+
+ if (obj.options.opened == true) {
+ obj.open();
+ }
+
+ return obj;
+});
+
+jSuites.calendar.prettify = function(d, texts) {
+ if (! texts) {
+ var texts = {
+ justNow: 'Just now',
+ xMinutesAgo: '{0}m ago',
+ xHoursAgo: '{0}h ago',
+ xDaysAgo: '{0}d ago',
+ xWeeksAgo: '{0}w ago',
+ xMonthsAgo: '{0} mon ago',
+ xYearsAgo: '{0}y ago',
+ }
+ }
+
+ var d1 = new Date();
+ var d2 = new Date(d);
+ var total = parseInt((d1 - d2) / 1000 / 60);
+
+ String.prototype.format = function(o) {
+ return this.replace('{0}', o);
+ }
+
+ if (total == 0) {
+ var text = texts.justNow;
+ } else if (total < 90) {
+ var text = texts.xMinutesAgo.format(total);
+ } else if (total < 1440) { // One day
+ var text = texts.xHoursAgo.format(Math.round(total/60));
+ } else if (total < 20160) { // 14 days
+ var text = texts.xDaysAgo.format(Math.round(total / 1440));
+ } else if (total < 43200) { // 30 days
+ var text = texts.xWeeksAgo.format(Math.round(total / 10080));
+ } else if (total < 1036800) { // 24 months
+ var text = texts.xMonthsAgo.format(Math.round(total / 43200));
+ } else { // 24 months+
+ var text = texts.xYearsAgo.format(Math.round(total / 525600));
+ }
+
+ return text;
+}
+
+jSuites.calendar.prettifyAll = function() {
+ var elements = document.querySelectorAll('.prettydate');
+ for (var i = 0; i < elements.length; i++) {
+ if (elements[i].getAttribute('data-date')) {
+ elements[i].innerHTML = jSuites.calendar.prettify(elements[i].getAttribute('data-date'));
+ } else {
+ elements[i].setAttribute('data-date', elements[i].innerHTML);
+ elements[i].innerHTML = jSuites.calendar.prettify(elements[i].innerHTML);
+ }
+ }
+}
+
+jSuites.calendar.now = function(date, dateOnly) {
+ if (! date) {
+ var date = new Date();
+ }
+ var y = date.getFullYear();
+ var m = date.getMonth() + 1;
+ var d = date.getDate();
+ var h = date.getHours();
+ var i = date.getMinutes();
+ var s = date.getSeconds();
+
+ if (dateOnly == true) {
+ return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d);
+ } else {
+ return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d) + ' ' + jSuites.two(h) + ':' + jSuites.two(i) + ':' + jSuites.two(s);
+ }
+}
+
+jSuites.calendar.toArray = function(value) {
+ var date = value.split(((value.indexOf('T') !== -1) ? 'T' : ' '));
+ var time = date[1];
+ var date = date[0].split('-');
+ var y = parseInt(date[0]);
+ var m = parseInt(date[1]);
+ var d = parseInt(date[2]);
+
+ if (time) {
+ var time = time.split(':');
+ var h = parseInt(time[0]);
+ var i = parseInt(time[1]);
+ } else {
+ var h = 0;
+ var i = 0;
+ }
+ return [ y, m, d, h, i, 0 ];
+}
+
+// Helper to extract date from a string
+jSuites.calendar.extractDateFromString = function(date, format) {
+ if (date > 0 && Number(date) == date) {
+ var d = new Date(Math.round((date - 25569)*86400*1000));
+ return d.getFullYear() + "-" + jSuites.two(d.getMonth()) + "-" + jSuites.two(d.getDate()) + ' 00:00:00';
+ }
+
+ var v1 = '' + date;
+ var v2 = format.replace(/[0-9]/g,'');
+
+ var test = 1;
+
+ // Get year
+ var y = v2.search("YYYY");
+ y = v1.substr(y,4);
+ if (parseInt(y) != y) {
+ test = 0;
+ }
+
+ // Get month
+ var m = v2.search("MM");
+ m = v1.substr(m,2);
+ if (parseInt(m) != m || m > 12) {
+ test = 0;
+ }
+
+ // Get day
+ var d = v2.search("DD");
+ d = v1.substr(d,2);
+ if (parseInt(d) != d || d > 31) {
+ test = 0;
+ }
+
+ // Get hour
+ var h = v2.search("HH");
+ if (h >= 0) {
+ h = v1.substr(h,2);
+ if (! parseInt(h) || h > 23) {
+ h = '00';
+ }
+ } else {
+ h = '00';
+ }
+
+ // Get minutes
+ var i = v2.search("MI");
+ if (i >= 0) {
+ i = v1.substr(i,2);
+ if (! parseInt(i) || i > 59) {
+ i = '00';
+ }
+ } else {
+ i = '00';
+ }
+
+ // Get seconds
+ var s = v2.search("SS");
+ if (s >= 0) {
+ s = v1.substr(s,2);
+ if (! parseInt(s) || s > 59) {
+ s = '00';
+ }
+ } else {
+ s = '00';
+ }
+
+ if (test == 1 && date.length == v2.length) {
+ // Update source
+ return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
+ }
+
+ return '';
+}
+
+// Helper to convert date into string
+jSuites.calendar.getDateString = function(value, options) {
+ if (! options) {
+ var options = {};
+ }
+
+ // Labels
+ if (typeof(options) == 'string') {
+ var format = options;
+ } else {
+ var format = options.format;
+ }
+
+ // Labels
+ if (options && options.weekdays) {
+ var weekdays = options.weekdays;
+ } else {
+ var weekdays = [ 'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday' ];
+ }
+
+ // Labels
+ if (options && options.months) {
+ var months = options.months;
+ } else {
+ var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
+ }
+
+ // Labels
+ if (options && options.months) {
+ var monthsFull = options.monthsFull;
+ } else {
+ var monthsFull = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+ }
+
+ // Default date format
+ if (! format) {
+ format = 'DD/MM/YYYY';
+ }
+
+ if (value) {
+ var d = ''+value;
+ var splitStr = (d.indexOf('T') !== -1) ? 'T' : ' ';
+ d = d.split(splitStr);
+
+ var h = '';
+ var m = '';
+ var s = '';
+
+ if (d[1]) {
+ h = d[1].split(':');
+ m = h[1] ? h[1] : '00';
+ s = h[2] ? h[2] : '00';
+ h = h[0] ? h[0] : '00';
+ } else {
+ h = '00';
+ m = '00';
+ s = '00';
+ }
+
+ d = d[0].split('-');
+
+ if (d[0] && d[1] && d[2] && d[0] > 0 && d[1] > 0 && d[1] < 13 && d[2] > 0 && d[2] < 32) {
+ var calendar = new Date(d[0], d[1]-1, d[2]);
+
+ d[1] = (d[1].length < 2 ? '0' : '') + d[1];
+ d[2] = (d[2].length < 2 ? '0' : '') + d[2];
+ h = (h.length < 2 ? '0' : '') + h;
+ m = (m.length < 2 ? '0' : '') + m;
+ s = (s.length < 2 ? '0' : '') + s;
+
+ // New value
+ value = format;
+ // Legacy
+ value = value.replace('MMM', 'MON');
+
+ // Extract tokens
+ var tokens = [ 'YYYY', 'YYY', 'YY', 'Y', 'MM', 'DD', 'DY', 'DAY', 'WD', 'D', 'Q', 'HH24', 'HH12', 'HH', 'PM', 'AM', 'MI', 'SS', 'MS', 'MONTH', 'MON'];
+ var pieces = [];
+ var tmp = value;
+
+ while (tmp) {
+ var t = 0;
+ for (var i = 0; i < tokens.length; i++) {
+ if (t == 0 && tmp.toUpperCase().indexOf(tokens[i]) === 0) {
+ t = tokens[i].length;
+ }
+ }
+ if (t == 0) {
+ pieces.push(tmp.substr(0, 1));
+ tmp = tmp.substr(1);
+ } else {
+ pieces.push(tmp.substr(0, t));
+ tmp = tmp.substr(t);
+ }
+ }
+
+ // Replace tokens per values
+ var replace = function(k, v, c) {
+ if (c == true) {
+ for (var i = 0; i < pieces.length; i++) {
+ if (pieces[i].toUpperCase() == k) {
+ pieces[i] = v;
+ }
+ }
+ } else {
+ for (var i = 0; i < pieces.length; i++) {
+ if (pieces[i] == k) {
+ pieces[i] = v;
+ }
+ }
+ }
+ }
+
+ replace('YYYY', d[0], true);
+ replace('YYY', d[0].substring(1,4), true);
+ replace('YY', d[0].substring(2,4), true);
+ replace('Y', d[0].substring(3,4), true);
+
+ replace('MM', d[1], true);
+ replace('DD', d[2], true);
+ replace('Q', Math.floor((calendar.getMonth() + 3) / 3), true);
+
+ if (h) {
+ replace('HH24', h);
+ }
+
+ if (h > 12) {
+ replace('HH12', h - 12, true);
+ replace('HH', h - 12, true);
+ replace('AM', 'pm', true);
+ replace('PM', 'pm', true);
+ } else {
+ replace('HH12', h, true);
+ replace('HH', h, true);
+ replace('AM', 'am', true);
+ replace('PM', 'am', true);
+ }
+
+ replace('MI', m, true);
+ replace('SS', s, true);
+ replace('MS', calendar.getMilliseconds(), true);
+
+ // Textual tokens
+ replace('MONTH', monthsFull[calendar.getMonth()].toUpperCase());
+ replace('Month', monthsFull[calendar.getMonth()]);
+ replace('month', monthsFull[calendar.getMonth()].toLowerCase());
+ replace('MON', months[calendar.getMonth()].toUpperCase());
+ replace('MMM', months[calendar.getMonth()].toUpperCase());
+ replace('Mon', months[calendar.getMonth()]);
+ replace('mon', months[calendar.getMonth()].toLowerCase());
+
+ replace('DAY', weekdays[calendar.getDay()].toUpperCase());
+ replace('Day', weekdays[calendar.getDay()]);
+ replace('day', weekdays[calendar.getDay()].toLowerCase());
+ replace('DY', weekdays[calendar.getDay()].substr(0,3).toUpperCase());
+ replace('Dy', weekdays[calendar.getDay()].substr(0,3));
+ replace('dy', weekdays[calendar.getDay()].substr(0,3).toLowerCase());
+ replace('D', weekdays[calendar.getDay()]);
+ replace('WD', weekdays[calendar.getDay()]);
+
+ // Put pieces together
+ value = pieces.join('');
+ } else {
+ value = '';
+ }
+ }
+
+ return value;
+}
+
+jSuites.calendar.isOpen = function(e) {
+ if (jSuites.calendar.current) {
+ if (e.target.className && e.target.className.indexOf('jcalendar') == -1) {
+ jSuites.calendar.current.close(false, false);
+ }
+ }
+}
+
+
+jSuites.color = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+ obj.values = [];
+
+ // Global container
+ if (! jSuites.color.current) {
+ jSuites.color.current = null;
+ }
+
+ /**
+ * @typedef {Object} defaults
+ * @property {(string|Array)} value - Initial value of the compontent
+ * @property {string} placeholder - The default instruction text on the element
+ * @property {requestCallback} onchange - Method to be execute after any changes on the element
+ * @property {requestCallback} onclose - Method to be execute when the element is closed
+ * @property {string} doneLabel - Label for button done
+ * @property {string} resetLabel - Label for button reset
+ * @property {string} resetValue - Value for button reset
+ * @property {Bool} showResetButton - Active or note for button reset - default false
+ */
+ var defaults = {
+ placeholder: '',
+ value: null,
+ onopen: null,
+ onclose: null,
+ onchange: null,
+ closeOnChange: true,
+ palette: null,
+ position: null,
+ doneLabel: 'Done',
+ resetLabel: 'Reset',
+ fullscreen: false,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ if (! obj.options.palette) {
+ // Default pallete
+ obj.options.palette = jSuites.palette();
+ }
+
+ // Value
+ if (obj.options.value) {
+ el.value = obj.options.value;
+ }
+
+ // Change
+ el.change = obj.setValue;
+
+ if (el.tagName == 'INPUT') {
+ el.classList.add('jcolor-input');
+ }
+
+ // Table container
+ var container = document.createElement('div');
+ container.className = 'jcolor';
+
+ // Table container
+ var backdrop = document.createElement('div');
+ backdrop.className = 'jcolor-backdrop';
+ container.appendChild(backdrop);
+
+ // Content
+ var content = document.createElement('div');
+ content.className = 'jcolor-content';
+
+ // Controls
+ var controls = document.createElement('div');
+ controls.className = 'jcolor-controls';
+ content.appendChild(controls);
+
+ // Reset button
+ var resetButton = document.createElement('div');
+ resetButton.className = 'jcolor-reset';
+ resetButton.innerHTML = obj.options.resetLabel;
+ resetButton.onclick = function() {
+ obj.setValue('');
+ obj.close();
+ }
+ controls.appendChild(resetButton);
+
+ // Close button
+ var closeButton = document.createElement('div');
+ closeButton.className = 'jcolor-close';
+ closeButton.innerHTML = obj.options.doneLabel;
+ closeButton.onclick = function() {
+ obj.close();
+ }
+ controls.appendChild(closeButton);
+
+ // Table pallete
+ var table = document.createElement('table');
+ table.setAttribute('cellpadding', '7');
+ table.setAttribute('cellspacing', '0');
+
+ for (var j = 0; j < obj.options.palette.length; j++) {
+ var tr = document.createElement('tr');
+ for (var i = 0; i < obj.options.palette[j].length; i++) {
+ var td = document.createElement('td');
+ var color = obj.options.palette[j][i];
+ if (color.substr(0,1) !== '#') {
+ color = '#' + color;
+ }
+ td.style.backgroundColor = color;
+ td.setAttribute('data-value', color);
+ td.innerHTML = '';
+ tr.appendChild(td);
+
+ // Selected color
+ if (obj.options.value == color) {
+ td.classList.add('jcolor-selected');
+ }
+
+ // Possible values
+ obj.values[color] = td;
+ }
+ table.appendChild(tr);
+ }
+
+ /**
+ * Open color pallete
+ */
+ obj.open = function() {
+ if (jSuites.color.current) {
+ if (jSuites.color.current != obj) {
+ jSuites.color.current.close();
+ }
+ }
+
+ if (! jSuites.color.current) {
+ // Persist element
+ jSuites.color.current = obj;
+ // Show colorpicker
+ container.classList.add('jcolor-focus');
+
+ var rectContent = content.getBoundingClientRect();
+
+ if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen == true) {
+ content.style.top = '';
+ content.classList.add('jcolor-fullscreen');
+ jSuites.animation.slideBottom(content, 1);
+ backdrop.style.display = 'block';
+ } else {
+ if (content.classList.contains('jcolor-fullscreen')) {
+ content.classList.remove('jcolor-fullscreen');
+ backdrop.style.display = '';
+ }
+
+ var rect = el.getBoundingClientRect();
+
+ if (obj.options.position) {
+ content.style.position = 'fixed';
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ content.style.top = (rect.top - (rectContent.height + 2)) + 'px';
+ } else {
+ content.style.top = (rect.top + rect.height + 2) + 'px';
+ }
+ content.style.left = rect.left + 'px';
+ } else {
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ content.style.top = -1 * (rectContent.height + rect.height + 2) + 'px';
+ } else {
+ content.style.top = '2px';
+ }
+ }
+ }
+
+ container.focus();
+
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el);
+ }
+ }
+ }
+
+ /**
+ * Close color pallete
+ */
+ obj.close = function(ignoreEvents) {
+ if (jSuites.color.current) {
+ el.focus();
+ jSuites.color.current = null;
+ if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el);
+ }
+ container.classList.remove('jcolor-focus');
+ }
+
+ // Make sure backdrop is hidden
+ backdrop.style.display = '';
+
+ return obj.options.value;
+ }
+
+ /**
+ * Set value
+ */
+ obj.setValue = function(color) {
+ if (! color) {
+ color = '';
+ }
+ if (color !== obj.options.value) {
+ el.value = color;
+ obj.options.value = color;
+
+ // Remove current selecded mark
+ var selected = container.querySelector('.jcolor-selected');
+ if (selected) {
+ selected.classList.remove('jcolor-selected');
+ }
+
+ // Mark cell as selected
+ if (obj.values[color]) {
+ obj.values[color].classList.add('jcolor-selected');
+ }
+
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: el });
+ }
+
+ // Onchange
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, color);
+ }
+ }
+
+ if (obj.options.closeOnChange == true) {
+ obj.close();
+ }
+ }
+
+ /**
+ * Get value
+ */
+ obj.getValue = function() {
+ return obj.options.value;
+ }
+
+ var backdropClickControl = false;
+
+ /**
+ * Focus
+ */
+ el.addEventListener("focus", function(e) {
+ if (! jSuites.color.current) {
+ obj.open();
+ }
+ });
+
+ /**
+ * If element is focus open the picker
+ */
+ el.addEventListener("mouseup", function(e) {
+ if (! jSuites.color.current) {
+ obj.open();
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ backdrop.addEventListener("mousedown", function(e) {
+ backdropClickControl = true;
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ backdrop.addEventListener("mouseup", function(e) {
+ if (backdropClickControl && jSuites.color.current) {
+ obj.close();
+ backdropClickControl = false;
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ // Select color
+ container.addEventListener("mouseup", function(e) {
+ if (e.target.tagName == 'TD') {
+ jSuites.color.current.setValue(e.target.getAttribute('data-value'));
+
+ if (jSuites.color.current) {
+ jSuites.color.current.close();
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+
+ // Close controller
+ document.addEventListener("mousedown", function(e) {
+ if (jSuites.color.current) {
+ var element = jSuites.findElement(e.target, 'jcolor');
+ if (! element) {
+ jSuites.color.current.close();
+ }
+ }
+ });
+
+ // Possible to focus the container
+ container.setAttribute('tabindex', '900');
+
+ // Placeholder
+ if (obj.options.placeholder) {
+ el.setAttribute('placeholder', obj.options.placeholder);
+ }
+
+ // Append to the table
+ content.appendChild(table);
+ container.appendChild(content);
+
+ // Insert picker after the element
+ if (el.tagName == 'INPUT') {
+ el.parentNode.insertBefore(container, el.nextSibling);
+ } else {
+ el.appendChild(container);
+ }
+
+ // Keep object available from the node
+ el.color = obj;
+ el.change = obj.setValue;
+
+ return obj;
+});
+
+
+
+jSuites.contextmenu = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ items: null,
+ onclick: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Class definition
+ el.classList.add('jcontextmenu');
+ // Focusable
+ el.setAttribute('tabindex', '900');
+
+ /**
+ * Open contextmenu
+ */
+ obj.open = function(e, items) {
+ if (items) {
+ // Update content
+ obj.options.items = items;
+ // Create items
+ obj.create(items);
+ }
+
+ // Coordinates
+ if ((obj.options.items && obj.options.items.length > 0) || el.children.length) {
+ if (e.target) {
+ var x = e.clientX;
+ var y = e.clientY;
+ } else {
+ var x = e.x;
+ var y = e.y;
+ }
+
+ el.classList.add('jcontextmenu-focus');
+ el.focus();
+
+ var rect = el.getBoundingClientRect();
+
+ if (window.innerHeight < y + rect.height) {
+ var h = y - rect.height;
+ if (h < 0) {
+ h = 0;
+ }
+ el.style.top = h + 'px';
+ } else {
+ el.style.top = y + 'px';
+ }
+
+ if (window.innerWidth < x + rect.width) {
+ if (x - rect.width > 0) {
+ el.style.left = (x - rect.width) + 'px';
+ } else {
+ el.style.left = '10px';
+ }
+ } else {
+ el.style.left = x + 'px';
+ }
+ }
+ }
+
+ /**
+ * Close menu
+ */
+ obj.close = function() {
+ if (el.classList.contains('jcontextmenu-focus')) {
+ el.classList.remove('jcontextmenu-focus');
+ }
+ }
+
+ /**
+ * Create items based on the declared objectd
+ * @param {object} items - List of object
+ */
+ obj.create = function(items) {
+ // Update content
+ el.innerHTML = '';
+
+ // Append items
+ for (var i = 0; i < items.length; i++) {
+ var itemContainer = createItemElement(items[i]);
+ el.appendChild(itemContainer);
+ }
+ }
+
+ /**
+ * Private function for create a new Item element
+ * @param {type} item
+ * @returns {jsuitesL#15.jSuites.contextmenu.createItemElement.itemContainer}
+ */
+ function createItemElement(item) {
+ if (item.type && (item.type == 'line' || item.type == 'divisor')) {
+ var itemContainer = document.createElement('hr');
+ } else {
+ var itemContainer = document.createElement('div');
+ var itemText = document.createElement('a');
+ itemText.innerHTML = item.title;
+
+ if (item.icon) {
+ itemContainer.setAttribute('data-icon', item.icon);
+ }
+
+ if (item.id) {
+ itemContainer.id = item.id;
+ }
+
+ if (item.disabled) {
+ itemContainer.className = 'jcontextmenu-disabled';
+ } else if (item.onclick) {
+ itemContainer.method = item.onclick;
+ itemContainer.addEventListener("mouseup", function() {
+ // Execute method
+ this.method(this);
+ });
+ }
+ itemContainer.appendChild(itemText);
+
+ if (item.submenu) {
+ var itemIconSubmenu = document.createElement('span');
+ itemIconSubmenu.innerHTML = "&#9658;";
+ itemContainer.appendChild(itemIconSubmenu);
+ itemContainer.classList.add('jcontexthassubmenu');
+ var el_submenu = document.createElement('div');
+ // Class definition
+ el_submenu.classList.add('jcontextmenu');
+ // Focusable
+ el_submenu.setAttribute('tabindex', '900');
+
+ // Append items
+ var submenu = item.submenu;
+ for (var i = 0; i < submenu.length; i++) {
+ var itemContainerSubMenu = createItemElement(submenu[i]);
+ el_submenu.appendChild(itemContainerSubMenu);
+ }
+
+ itemContainer.appendChild(el_submenu);
+ } else if (item.shortcut) {
+ var itemShortCut = document.createElement('span');
+ itemShortCut.innerHTML = item.shortcut;
+ itemContainer.appendChild(itemShortCut);
+ }
+ }
+ return itemContainer;
+ }
+
+ if (typeof(obj.options.onclick) == 'function') {
+ el.addEventListener('click', function(e) {
+ obj.options.onclick(obj, e);
+ });
+ }
+
+ // Create items
+ if (obj.options.items) {
+ obj.create(obj.options.items);
+ }
+
+ el.addEventListener('blur', function(e) {
+ setTimeout(function() {
+ obj.close();
+ }, 120);
+ });
+
+ if (! jSuites.contextmenu.hasEvents) {
+ window.addEventListener("mousewheel", function() {
+ obj.close();
+ });
+
+ document.addEventListener("contextmenu", function(e) {
+ var id = jSuites.contextmenu.getElement(e.target);
+ if (id) {
+ var element = document.querySelector('#' + id);
+ if (! element) {
+ console.error('JSUITES: Contextmenu id not found');
+ } else {
+ element.contextmenu.open(e);
+ e.preventDefault();
+ }
+ }
+ });
+
+ jSuites.contextmenu.hasEvents = true;
+ }
+
+ el.contextmenu = obj;
+
+ return obj;
+});
+
+jSuites.contextmenu.getElement = function(element) {
+ var foundId = 0;
+
+ function path (element) {
+ if (element.parentNode && element.getAttribute('aria-contextmenu-id')) {
+ foundId = element.getAttribute('aria-contextmenu-id')
+ } else {
+ if (element.parentNode) {
+ path(element.parentNode);
+ }
+ }
+ }
+
+ path(element);
+
+ return foundId;
+}
+
+jSuites.dropdown = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // If the element is a SELECT tag, create a configuration object
+ if (el.tagName == 'SELECT') {
+ var ret = jSuites.dropdown.extractFromDom(el, options);
+ el = ret.el;
+ options = ret.options;
+ }
+
+ // Default configuration
+ var defaults = {
+ url: null,
+ data: [],
+ multiple: false,
+ autocomplete: false,
+ remoteSearch: false,
+ lazyLoading: false,
+ type: null,
+ width: null,
+ maxWidth: null,
+ opened: false,
+ value: null,
+ placeholder: '',
+ newOptions: false,
+ position: false,
+ onchange: null,
+ onload: null,
+ onopen: null,
+ onclose: null,
+ onfocus: null,
+ onblur: null,
+ oninsert: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Global container
+ if (! jSuites.dropdown.current) {
+ jSuites.dropdown.current = null;
+ }
+
+ // Force autocomplete search
+ if (obj.options.remoteSearch == true) {
+ obj.options.autocomplete = true;
+ }
+
+ // Containers
+ obj.items = [];
+ obj.groups = [];
+ obj.value = [];
+
+ // Search options
+ obj.search = '';
+ obj.results = null;
+ obj.numOfItems = 0;
+
+ // Create dropdown
+ el.classList.add('jdropdown');
+
+ if (obj.options.type == 'searchbar') {
+ el.classList.add('jdropdown-searchbar');
+ } else if (obj.options.type == 'list') {
+ el.classList.add('jdropdown-list');
+ } else if (obj.options.type == 'picker') {
+ el.classList.add('jdropdown-picker');
+ } else {
+ if (jSuites.getWindowWidth() < 800) {
+ el.classList.add('jdropdown-picker');
+ obj.options.type = 'picker';
+ } else {
+ if (obj.options.width) {
+ el.style.width = obj.options.width;
+ el.style.minWidth = obj.options.width;
+ }
+ el.classList.add('jdropdown-default');
+ obj.options.type = 'default';
+ }
+ }
+
+ // Header container
+ var containerHeader = document.createElement('div');
+ containerHeader.className = 'jdropdown-container-header';
+
+ // Header
+ obj.header = document.createElement('input');
+ obj.header.className = 'jdropdown-header';
+ obj.header.setAttribute('autocomplete', 'off');
+ if (typeof(obj.options.onfocus) == 'function') {
+ obj.header.onfocus = function() {
+ obj.options.onfocus(el);
+ }
+ }
+ if (typeof(obj.options.onblur) == 'function') {
+ obj.header.onblur = function() {
+ obj.options.onblur(el);
+ }
+ }
+
+ if (obj.options.newOptions == true) {
+ obj.header.classList.add('jdropdown-add');
+ }
+
+ // Container
+ var container = document.createElement('div');
+ container.className = 'jdropdown-container';
+
+ // Dropdown content
+ var content = document.createElement('div');
+ content.className = 'jdropdown-content';
+
+ // Close button
+ var closeButton = document.createElement('div');
+ closeButton.className = 'jdropdown-close';
+ closeButton.innerHTML = 'Done';
+
+ // Reset button
+ var resetButton = document.createElement('div');
+ resetButton.className = 'jdropdown-reset';
+ resetButton.innerHTML = 'x';
+ resetButton.onclick = function() {
+ obj.reset();
+ obj.close();
+ }
+
+ // Create backdrop
+ var backdrop = document.createElement('div');
+ backdrop.className = 'jdropdown-backdrop';
+
+ // Autocomplete
+ if (obj.options.autocomplete == true) {
+ el.setAttribute('data-autocomplete', true);
+
+ // Handler
+ var keyTimer = null;
+ obj.header.addEventListener('keyup', function(e) {
+ if (! keyTimer) {
+ if (obj.search != obj.header.value.trim()) {
+ keyTimer = setTimeout(function() {
+ obj.find(obj.header.value.trim());
+ keyTimer = null;
+ }, 400);
+ }
+
+ if (! el.classList.contains('jdropdown-focus')) {
+ obj.open();
+ }
+ }
+ });
+ } else {
+ obj.header.setAttribute('readonly', 'readonly');
+ }
+
+ // Place holder
+ if (! obj.options.placeholder && el.getAttribute('placeholder')) {
+ obj.options.placeholder = el.getAttribute('placeholder');
+ }
+
+ if (obj.options.placeholder) {
+ obj.header.setAttribute('placeholder', obj.options.placeholder);
+ }
+
+ // Append elements
+ containerHeader.appendChild(obj.header);
+ if (obj.options.type == 'searchbar') {
+ containerHeader.appendChild(closeButton);
+ } else {
+ container.appendChild(closeButton);
+ }
+ if (! obj.options.type || obj.options.type == 'default') {
+ //containerHeader.appendChild(resetButton);
+ }
+ container.appendChild(content);
+ el.appendChild(containerHeader);
+ el.appendChild(container);
+ el.appendChild(backdrop);
+
+ var filter = function(a) {
+ return a.filter(function(v) {
+ return v;
+ });
+ }
+
+ /**
+ * Init dropdown
+ */
+ obj.init = function() {
+ if (obj.options.url && ! obj.options.data.length) {
+ jSuites.ajax({
+ url: obj.options.url,
+ method: 'GET',
+ dataType: 'json',
+ success: function(data) {
+ if (data) {
+ // Set data
+ obj.setData(data);
+ // Set value
+ if (obj.options.value != null) {
+ obj.setValue(obj.options.value);
+ }
+ // Onload method
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj, data);
+ }
+ }
+ }
+ });
+ } else {
+ var data = [];
+ if (obj.options.data.length) {
+ for (var j = 0; j < obj.options.data.length; j++) {
+ data.push(obj.options.data[j]);
+ }
+ }
+ // Set data
+ obj.setData(data);
+ // Set value
+ if (obj.options.value != null) {
+ obj.setValue(obj.options.value);
+ }
+ // Onload
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj, obj.options.data);
+ }
+ }
+
+ // Open dropdown
+ if (obj.options.opened == true) {
+ obj.open();
+ }
+ }
+
+ obj.getUrl = function() {
+ return obj.options.url;
+ }
+
+ obj.setUrl = function(url) {
+ obj.options.url = url;
+
+ jSuites.ajax({
+ url: obj.options.url,
+ method: 'GET',
+ dataType: 'json',
+ success: function(data) {
+ obj.setData(data);
+ }
+ });
+ }
+
+ /**
+ * Add a new item
+ */
+ obj.add = function(title) {
+ if (! title) {
+ var current = obj.options.autocomplete == true ? obj.header.value : '';
+ var title = prompt('Text', current);
+ if (! title) {
+ return false;
+ }
+ }
+
+ // Create new item
+ var item = {
+ value: jSuites.guid(),
+ text: title,
+ };
+
+ // Add item to the main list
+ obj.options.data.push(item);
+
+ var newItem = obj.createItem(item);
+
+ // Append DOM to the list
+ content.appendChild(newItem.element);
+
+ // Callback
+ if (typeof(obj.options.oninsert) == 'function') {
+ obj.options.oninsert(obj, newItem, item)
+ }
+
+ // Show content
+ if (content.style.display == 'none') {
+ content.style.display = '';
+ }
+
+ return item;
+ }
+
+ /**
+ * Create a new item
+ */
+ obj.createItem = function(data, group, groupName) {
+ if (typeof(data.text) == 'undefined' && data.name) {
+ data.text = data.name;
+ }
+ if (typeof(data.value) == 'undefined' && data.id) {
+ data.value = data.id;
+ }
+ // Create item
+ var item = {};
+ item.element = document.createElement('div');
+ item.element.className = 'jdropdown-item';
+ item.element.indexValue = obj.items.length;
+ item.value = data.value;
+ item.text = data.text;
+
+ // Id
+ if (data.id) {
+ item.element.setAttribute('id', data.id);
+ }
+
+ // Group reference
+ if (group) {
+ item.group = group;
+ item.groupName = groupName;
+ }
+
+ // Image
+ if (data.image) {
+ var image = document.createElement('img');
+ image.className = 'jdropdown-image';
+ image.src = data.image;
+ if (! data.title) {
+ image.classList.add('jdropdown-image-small');
+ }
+ item.element.appendChild(image);
+ } else if (data.color) {
+ var color = document.createElement('div');
+ color.className = 'jdropdown-color';
+ color.style.backgroundColor = data.color;
+ item.element.appendChild(color);
+ }
+
+ // Set content
+ var node = document.createElement('div');
+ node.className = 'jdropdown-description';
+ node.innerHTML = data.text || '&nbsp;';
+
+ // Title
+ if (data.title) {
+ var title = document.createElement('div');
+ title.className = 'jdropdown-title';
+ title.innerHTML = data.title;
+ node.appendChild(title);
+
+ // Keep text reference
+ item.title = data.title;
+ }
+
+ // Value
+ if (obj.value && obj.value[data.value]) {
+ item.element.classList.add('jdropdown-selected');
+ item.selected = true;
+ }
+
+ // Keep DOM accessible
+ obj.items.push(item);
+
+ // Add node to item
+ item.element.appendChild(node);
+
+ return item;
+ }
+
+ obj.appendData = function(data) {
+ // Create elements
+ if (data.length) {
+ // Reset counter
+ obj.numOfItems = 0;
+
+ // Helpers
+ var items = [];
+ var groups = [];
+
+ // Prepare data
+ for (var i = 0; i < data.length; i++) {
+ // Process groups
+ if (data[i].group) {
+ if (! groups[data[i].group]) {
+ groups[data[i].group] = [];
+ }
+ groups[data[i].group].push(i);
+ } else {
+ items.push(i);
+ }
+ }
+
+ // Groups
+ var groupNames = Object.keys(groups);
+
+ // Append groups in case exists
+ if (groupNames.length > 0) {
+ for (var i = 0; i < groupNames.length; i++) {
+ // Group container
+ var group = document.createElement('div');
+ group.className = 'jdropdown-group';
+ // Group name
+ var groupName = document.createElement('div');
+ groupName.className = 'jdropdown-group-name';
+ groupName.innerHTML = groupNames[i];
+ // Group arrow
+ var groupArrow = document.createElement('i');
+ groupArrow.className = 'jdropdown-group-arrow jdropdown-group-arrow-down';
+ groupName.appendChild(groupArrow);
+ // Group items
+ var groupContent = document.createElement('div');
+ groupContent.className = 'jdropdown-group-items';
+ for (var j = 0; j < groups[groupNames[i]].length; j++) {
+ var item = obj.createItem(data[groups[groupNames[i]][j]], group, groupNames[i]);
+
+ if (obj.options.lazyLoading == false || obj.numOfItems < 200) {
+ groupContent.appendChild(item.element);
+ obj.numOfItems++;
+ }
+ }
+ // Group itens
+ group.appendChild(groupName);
+ group.appendChild(groupContent);
+ // Keep group DOM
+ obj.groups.push(group);
+ // Only add to the screen if children on the group
+ if (groupContent.children.length > 0) {
+ // Add DOM to the content
+ content.appendChild(group);
+ }
+ }
+ }
+
+ if (items.length) {
+ for (var i = 0; i < items.length; i++) {
+ var item = obj.createItem(data[items[i]]);
+ if (obj.options.lazyLoading == false || obj.numOfItems < 200) {
+ content.appendChild(item.element);
+ obj.numOfItems++;
+ }
+ }
+ }
+ }
+ }
+
+ obj.setData = function(data) {
+ // Prepare data
+ if (data.length) {
+ for (var i = 0; i < data.length; i++) {
+ // Compatibility
+ if (typeof(data[i]) != 'object') {
+ // Correct format
+ data[i] = {
+ value: data[i],
+ text: data[i]
+ }
+ }
+ }
+
+ // Make sure the content container is blank
+ content.innerHTML = '';
+
+ // Reset
+ obj.reset();
+
+ // Reset items
+ obj.items = [];
+
+ // Append data
+ obj.appendData(data);
+ }
+
+ // Update data
+ obj.options.data = data;
+ }
+
+ /**
+ * Get position of the item
+ */
+ obj.getPosition = function(value) {
+ for (var i = 0; i < obj.items.length; i++) {
+ if (obj.items[i].value == value) {
+ return i;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Get dropdown current text
+ */
+ obj.getText = function(asArray) {
+ var v = [];
+ var k = Object.keys(obj.value);
+ for (var i = 0; i < k.length; i++) {
+ v.push(obj.value[k[i]]);
+ }
+ if (asArray) {
+ return v;
+ } else {
+ return v.join('; ');
+ }
+ }
+
+ /**
+ * Get dropdown current value
+ */
+ obj.getValue = function(asArray) {
+ if (asArray) {
+ return Object.keys(obj.value);
+ } else {
+ return Object.keys(obj.value).join(';');
+ }
+ }
+
+ obj.setValue = function(value) {
+ var setValue = function(item, value) {
+ if (obj.items[item].value == value) {
+ if (obj.items[item].element) {
+ obj.items[item].element.classList.add('jdropdown-selected');
+ }
+ obj.items[item].selected = true;
+
+ // Push to the values container
+ obj.value[value] = obj.items[item].text;
+ }
+ }
+
+ // Old value
+ var oldValue = obj.getValue();
+
+ // Remove selected
+ for (var i = 0; i < obj.items.length; i++) {
+ if (obj.items[i].selected == true) {
+ if (obj.items[i].element) {
+ obj.items[i].element.classList.remove('jdropdown-selected')
+ }
+ obj.items[i].selected = null;
+ }
+ }
+
+ // Reset
+ obj.value = [];
+
+ // Set values
+ if (value !== null) {
+ if (! Array.isArray(value)) {
+ for (var i = 0; i < obj.items.length; i++) {
+ setValue(i, value);
+ }
+ } else {
+ for (var i = 0; i < obj.items.length; i++) {
+ for (var j = 0; j < value.length; j++) {
+ setValue(i, value[j]);
+ }
+ }
+ }
+ }
+
+ // New value
+ var newValue = obj.getValue();
+
+ if (oldValue != newValue) {
+ // Label
+ obj.header.value = obj.getText();
+
+ // Value
+ obj.options.value = obj.getValue();
+
+ // Element value
+ el.value = obj.options.value;
+
+ // Events
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: this });
+ }
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, null, oldValue, obj.options.value);
+ }
+ }
+ }
+
+ obj.resetSelected = function() {
+ obj.setValue(null);
+ }
+
+ obj.selectIndex = function(index) {
+ // Make sure is a number
+ var index = parseInt(index);
+
+ // Only select those existing elements
+ if (obj.items && obj.items[index]) {
+ // Current selection
+ var oldValue = obj.getValue();
+
+ // Reset cursor to a new position
+ obj.setCursor(index, false);
+
+ // Behaviour
+ if (! obj.options.multiple) {
+ // Update value
+ if (! obj.value[obj.items[index].value]) {
+ obj.setValue(obj.items[index].value);
+ } else {
+ obj.setValue(null);
+ }
+ obj.close();
+ } else {
+ // Toggle option
+ if (obj.items[index].selected) {
+ obj.items[index].element.classList.remove('jdropdown-selected');
+ obj.items[index].selected = false;
+ // Remove from selected list
+ delete obj.value[obj.items[index].value];
+ } else {
+ // Select element
+ obj.items[index].element.classList.add('jdropdown-selected');
+ obj.items[index].selected = true;
+ // Add to the selected list
+ obj.value[obj.items[index].value] = obj.items[index].text;
+ }
+
+ // Update labels for multiple dropdown
+ if (! obj.options.autocomplete) {
+ obj.header.value = obj.getText();
+ }
+
+ // Events
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, index, oldValue, obj.getValue());
+ }
+ }
+ }
+ }
+
+ obj.selectItem = function(item) {
+ if (jSuites.dropdown.current) {
+ obj.selectIndex(item.indexValue);
+ }
+ }
+
+ obj.find = function(str) {
+ if (obj.search == str.trim()) {
+ return false;
+ }
+
+ // Search term
+ obj.search = str;
+
+ // Results
+ obj.numOfItems = 0;
+
+ // Remove current items in the remote search
+ if (obj.options.remoteSearch == true) {
+ obj.currentIndex = null;
+ obj.results = null;
+ jSuites.ajax({
+ url: obj.options.url + '?q=' + str,
+ method: 'GET',
+ dataType: 'json',
+ success: function(result) {
+ // Reset items
+ obj.items = [];
+ content.innerHTML = '';
+ obj.appendData(result);
+
+ if (! result.length) {
+ content.style.display = 'none';
+ } else {
+ content.style.display = '';
+ }
+ }
+ });
+ } else {
+ // Search terms
+ str = new RegExp(str, 'gi');
+
+ // Reset search
+ obj.results = [];
+
+ // Append options
+ for (var i = 0; i < obj.items.length; i++) {
+ // Item label
+ var label = obj.items[i].text;
+ // Item title
+ var title = obj.items[i].title || '';
+ // Group name
+ var groupName = obj.items[i].groupName || '';
+
+ if (str == null || obj.value[obj.items[i].value] != undefined || label.match(str) || title.match(str) || groupName.match(str)) {
+ obj.results.push(obj.items[i]);
+
+ if (obj.items[i].group && obj.items[i].group.children[1].children[0]) {
+ // Remove all nodes
+ while (obj.items[i].group.children[1].children[0]) {
+ obj.items[i].group.children[1].removeChild(obj.items[i].group.children[1].children[0]);
+ }
+ }
+ }
+ }
+
+ // Remove all nodes
+ while (content.children[0]) {
+ content.removeChild(content.children[0]);
+ }
+
+ // Show 200 items at once
+ var number = obj.results.length || 0;
+
+ // Lazyloading
+ if (obj.options.lazyLoading == true && number > 200) {
+ number = 200;
+ }
+
+ for (var i = 0; i < number; i++) {
+ if (obj.results[i].group) {
+ if (! obj.results[i].group.parentNode) {
+ content.appendChild(obj.results[i].group);
+ }
+ obj.results[i].group.children[1].appendChild(obj.results[i].element);
+ } else {
+ content.appendChild(obj.results[i].element);
+ }
+ obj.numOfItems++;
+ }
+
+ if (! obj.results.length) {
+ content.style.display = 'none';
+ } else {
+ content.style.display = '';
+ }
+ }
+ }
+
+ obj.open = function() {
+ if (jSuites.dropdown.current != el) {
+ if (jSuites.dropdown.current) {
+ jSuites.dropdown.current.dropdown.close();
+ }
+ jSuites.dropdown.current = el;
+ }
+
+ // Focus
+ if (! el.classList.contains('jdropdown-focus')) {
+ // Add focus
+ el.classList.add('jdropdown-focus');
+
+ // Animation
+ if (jSuites.getWindowWidth() < 800) {
+ if (obj.options.type == null || obj.options.type == 'picker') {
+ jSuites.animation.slideBottom(container, 1);
+ }
+ }
+
+ // Filter
+ if (obj.options.autocomplete == true) {
+ obj.header.value = obj.search;
+ obj.header.focus();
+ }
+
+ // Set cursor for the first or first selected element
+ var k = Object.keys(obj.value);
+ if (k[0]) {
+ var cursor = obj.getPosition(k[0]);
+ if (cursor) {
+ obj.setCursor(cursor);
+ }
+ }
+
+ // Container Size
+ if (! obj.options.type || obj.options.type == 'default') {
+ var rect = el.getBoundingClientRect();
+ var rectContainer = container.getBoundingClientRect();
+
+ if (obj.options.position) {
+ container.style.position = 'fixed';
+ if (window.innerHeight < rect.bottom + rectContainer.height) {
+ container.style.top = '';
+ container.style.bottom = (window.innerHeight - rect.top ) + 1 + 'px';
+ } else {
+ container.style.top = rect.bottom + 'px';
+ container.style.bottom = '';
+ }
+ container.style.left = rect.left + 'px';
+ } else {
+ if (window.innerHeight < rect.bottom + rectContainer.height) {
+ container.style.top = '';
+ container.style.bottom = rect.height + 1 + 'px';
+ } else {
+ container.style.top = '';
+ container.style.bottom = '';
+ }
+ }
+
+ container.style.minWidth = rect.width + 'px';
+
+ if (obj.options.maxWidth) {
+ container.style.maxWidth = obj.options.maxWidth;
+ }
+
+ if (! obj.items.length && obj.options.autocomplete == true) {
+ content.style.display = 'none';
+ } else {
+ content.style.display = '';
+ }
+ }
+ }
+
+ // Events
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el);
+ }
+ }
+
+ obj.close = function(ignoreEvents) {
+ if (jSuites.dropdown.current) {
+ // Remove controller
+ jSuites.dropdown.current = null
+ // Remove cursor
+ obj.setCursor();
+ // Update labels
+ obj.header.value = obj.getText();
+ // Events
+ if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el);
+ }
+ // Blur
+ if (obj.header.blur) {
+ obj.header.blur();
+ }
+ // Remove focus
+ el.classList.remove('jdropdown-focus');
+ }
+
+ return obj.getValue();
+ }
+
+ /**
+ * Set cursor
+ */
+ obj.setCursor = function(index, setPosition) {
+ // Remove current cursor
+ if (obj.currentIndex != null) {
+ // Remove visual cursor
+ if (obj.items && obj.items[obj.currentIndex]) {
+ obj.items[obj.currentIndex].element.classList.remove('jdropdown-cursor');
+ }
+ }
+
+ if (index == undefined) {
+ obj.currentIndex = null;
+ } else {
+ parseInt(index);
+
+ obj.items[index].element.classList.add('jdropdown-cursor');
+ obj.currentIndex = index;
+
+ // Update scroll to the cursor element
+ if (setPosition !== false && obj.items[obj.currentIndex].element) {
+ var container = content.scrollTop;
+ var element = obj.items[obj.currentIndex].element;
+ content.scrollTop = element.offsetTop - element.scrollTop + element.clientTop - 95;
+ }
+ }
+ }
+
+ // Compatibility
+ obj.resetCursor = obj.setCursor;
+ obj.updateCursor = obj.setCursor;
+
+ /**
+ * Reset cursor and selected items
+ */
+ obj.reset = function() {
+ // Reset cursor
+ obj.setCursor();
+
+ // Reset selected
+ obj.setValue(null);
+ }
+
+ /**
+ * First visible item
+ */
+ obj.firstVisible = function() {
+ var newIndex = null;
+ for (var i = 0; i < obj.items.length; i++) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') {
+ newIndex = i;
+ break;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ /**
+ * Navigation
+ */
+ obj.first = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex - 1; i >= 0; i--) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') {
+ newIndex = i;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.last = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex + 1; i < obj.items.length; i++) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') {
+ newIndex = i;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.next = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex + 1; i < obj.items.length; i++) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode) {
+ newIndex = i;
+ break;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.prev = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex - 1; i >= 0; i--) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode) {
+ newIndex = i;
+ break;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.loadUp = function() {
+ return false;
+ }
+
+ obj.loadDown = function() {
+ var test = false;
+
+ // Search
+ if (obj.results) {
+ var results = obj.results;
+ } else {
+ var results = obj.items;
+ }
+
+ if (results.length > obj.numOfItems) {
+ var numberOfItems = obj.numOfItems;
+ var number = results.length - numberOfItems;
+ if (number > 200) {
+ number = 200;
+ }
+
+ for (var i = numberOfItems; i < numberOfItems + number; i++) {
+ if (results[i].group) {
+ if (! results[i].group.parentNode) {
+ content.appendChild(results[i].group);
+ }
+ results[i].group.children[2].appendChild(results[i].element);
+ } else {
+ content.appendChild(results[i].element);
+ }
+
+ obj.numOfItems++;
+ }
+
+ // New item added
+ test = true;
+ }
+
+ return test;
+ }
+
+ if (! jSuites.dropdown.hasEvents) {
+ if ('ontouchsend' in document.documentElement === true) {
+ document.addEventListener('touchsend', jSuites.dropdown.mouseup);
+ } else {
+ document.addEventListener('mouseup', jSuites.dropdown.mouseup);
+ }
+ document.addEventListener('keydown', jSuites.dropdown.onkeydown);
+
+ jSuites.dropdown.hasEvents = true;
+ }
+
+ // Lazyloading
+ if (obj.options.lazyLoading == true) {
+ jSuites.lazyLoading(content, {
+ loadUp: obj.loadUp,
+ loadDown: obj.loadDown,
+ });
+ }
+
+ // Start dropdown
+ obj.init();
+
+ // Keep object available from the node
+ el.dropdown = obj;
+ el.change = obj.setValue;
+
+ return obj;
+});
+
+jSuites.dropdown.hasEvents = false;
+
+jSuites.dropdown.mouseup = function(e) {
+ var element = jSuites.findElement(e.target, 'jdropdown');
+ if (element) {
+ var dropdown = element.dropdown;
+ if (e.target.classList.contains('jdropdown-header')) {
+ if (element.classList.contains('jdropdown-focus') && element.classList.contains('jdropdown-default')) {
+ var rect = element.getBoundingClientRect();
+
+ if (e.changedTouches && e.changedTouches[0]) {
+ var x = e.changedTouches[0].clientX;
+ var y = e.changedTouches[0].clientY;
+ } else {
+ var x = e.clientX;
+ var y = e.clientY;
+ }
+
+ if (rect.width - (x - rect.left) < 30) {
+ if (e.target.classList.contains('jdropdown-add')) {
+ dropdown.add();
+ } else {
+ dropdown.close();
+ }
+ } else {
+ if (dropdown.options.autocomplete == false) {
+ dropdown.close();
+ }
+ }
+ } else {
+ dropdown.open();
+ }
+ } else if (e.target.classList.contains('jdropdown-group-name')) {
+ var items = e.target.nextSibling.children;
+ if (e.target.nextSibling.style.display != 'none') {
+ for (var i = 0; i < items.length; i++) {
+ if (items[i].style.display != 'none') {
+ dropdown.selectItem(items[i]);
+ }
+ }
+ }
+ } else if (e.target.classList.contains('jdropdown-group-arrow')) {
+ if (e.target.classList.contains('jdropdown-group-arrow-down')) {
+ e.target.classList.remove('jdropdown-group-arrow-down');
+ e.target.classList.add('jdropdown-group-arrow-up');
+ e.target.parentNode.nextSibling.style.display = 'none';
+ } else {
+ e.target.classList.remove('jdropdown-group-arrow-up');
+ e.target.classList.add('jdropdown-group-arrow-down');
+ e.target.parentNode.nextSibling.style.display = '';
+ }
+ } else if (e.target.classList.contains('jdropdown-item')) {
+ dropdown.selectItem(e.target);
+ } else if (e.target.classList.contains('jdropdown-image')) {
+ dropdown.selectItem(e.target.parentNode);
+ } else if (e.target.classList.contains('jdropdown-description')) {
+ dropdown.selectItem(e.target.parentNode);
+ } else if (e.target.classList.contains('jdropdown-title')) {
+ dropdown.selectItem(e.target.parentNode.parentNode);
+ } else if (e.target.classList.contains('jdropdown-close') || e.target.classList.contains('jdropdown-backdrop')) {
+ dropdown.close();
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+ } else {
+ if (jSuites.dropdown.current) {
+ jSuites.dropdown.current.dropdown.close();
+ }
+ }
+}
+
+// Keydown controls
+jSuites.dropdown.onkeydown = function(e) {
+ if (jSuites.dropdown.current) {
+ // Element
+ var element = jSuites.dropdown.current.dropdown;
+ // Index
+ var index = element.currentIndex;
+
+ if (! e.shiftKey) {
+ if (e.which == 13 || e.which == 27 || e.which == 35 || e.which == 36 || e.which == 38 || e.which == 40) {
+ // Move cursor
+ if (e.which == 13) {
+ element.selectIndex(index);
+ } else if (e.which == 38) {
+ if (index == null) {
+ element.firstVisible();
+ } else if (index > 0) {
+ element.prev();
+ }
+ } else if (e.which == 40) {
+ if (index == null) {
+ element.firstVisible();
+ } else if (index + 1 < element.items.length) {
+ element.next();
+ }
+ } else if (e.which == 36) {
+ element.first();
+ } else if (e.which == 35) {
+ element.last();
+ } else if (e.which == 27) {
+ element.close();
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ }
+}
+
+jSuites.dropdown.extractFromDom = function(el, options) {
+ // Keep reference
+ var select = el;
+ if (! options) {
+ options = {};
+ }
+ // Prepare configuration
+ if (el.getAttribute('multiple') && (! options || options.multiple == undefined)) {
+ options.multiple = true;
+ }
+ if (el.getAttribute('placeholder') && (! options || options.placeholder == undefined)) {
+ options.placeholder = el.getAttribute('placeholder');
+ }
+ if (el.getAttribute('data-autocomplete') && (! options || options.autocomplete == undefined)) {
+ options.autocomplete = true;
+ }
+ if (! options || options.width == undefined) {
+ options.width = el.offsetWidth;
+ }
+ if (el.value && (! options || options.value == undefined)) {
+ options.value = el.value;
+ }
+ if (! options || options.data == undefined) {
+ options.data = [];
+ for (var j = 0; j < el.children.length; j++) {
+ if (el.children[j].tagName == 'OPTGROUP') {
+ for (var i = 0; i < el.children[j].children.length; i++) {
+ options.data.push({
+ value: el.children[j].children[i].value,
+ text: el.children[j].children[i].innerHTML,
+ group: el.children[j].getAttribute('label'),
+ });
+ }
+ } else {
+ options.data.push({
+ value: el.children[j].value,
+ text: el.children[j].innerHTML,
+ });
+ }
+ }
+ }
+ if (! options || options.onchange == undefined) {
+ options.onchange = function(a,b,c,d) {
+ if (options.multiple == true) {
+ if (obj.items[b].classList.contains('jdropdown-selected')) {
+ select.options[b].setAttribute('selected', 'selected');
+ } else {
+ select.options[b].removeAttribute('selected');
+ }
+ } else {
+ select.value = d;
+ }
+ }
+ }
+ // Create DIV
+ var div = document.createElement('div');
+ el.parentNode.insertBefore(div, el);
+ el.style.display = 'none';
+ el = div;
+
+ return { el:el, options:options };
+}
+
+/**
+ * (c) HTML Editor
+ * https://github.com/paulhodel/jsuites
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Inline simple richtext editor
+ */
+
+jSuites.editor = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // If element is textarea, then replace by div editor
+ if (el.tagName == 'TEXTAREA' || el.tagName == 'INPUT') {
+ // Current element
+ var element = el;
+ element.style.display = 'none';
+ // New Element
+ el = document.createElement('div');
+ // Value
+ if (! options.value) {
+ options.value = element.value;
+ }
+ // Event to populate the textarea
+ options.onblur = function(a,b,c) {
+ element.value = b.getData()
+ }
+ element.insertBefore(el);
+ }
+
+ // Default configuration
+ var defaults = {
+ // Initial HTML content
+ value: null,
+ // Initial snippet
+ snippet: null,
+ // Add toolbar
+ toolbar: null,
+ // Website parser is to read websites and images from cross domain
+ remoteParser: null,
+ // Parse URL
+ parseURL: false,
+ // Accept drop files
+ dropZone: false,
+ dropAsAttachment: false,
+ acceptImages: false,
+ acceptFiles: false,
+ maxFileSize: 5000000,
+ allowImageResize: true,
+ // Style
+ border: true,
+ padding: true,
+ maxHeight: null,
+ focus: false,
+ // Events
+ onclick: null,
+ onfocus: null,
+ onblur: null,
+ onload: null,
+ onkeyup: null,
+ onkeydown: null,
+ onchange: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Private controllers
+ var imageResize = 0;
+ var editorTimer = null;
+ var editorAction = null;
+
+ // Make sure element is empty
+ el.innerHTML = '';
+
+ // Change method
+ el.change = obj.setValue;
+
+ if (typeof(obj.options.onclick) == 'function') {
+ el.onclick = function(e) {
+ obj.options.onclick(el, obj, e);
+ }
+ }
+
+ // Prepare container
+ el.classList.add('jeditor-container');
+
+ // Padding
+ if (obj.options.padding == true) {
+ el.classList.add('jeditor-padding');
+ }
+
+ // Border
+ if (obj.options.border == false) {
+ el.style.border = '0px';
+ }
+
+ // Snippet
+ var snippet = document.createElement('div');
+ snippet.className = 'jsnippet';
+ snippet.setAttribute('contenteditable', false);
+
+ // Toolbar
+ var toolbar = document.createElement('div');
+ toolbar.className = 'jeditor-toolbar';
+
+ // Create editor
+ var editor = document.createElement('div');
+ editor.setAttribute('contenteditable', true);
+ editor.setAttribute('spellcheck', false);
+ editor.className = 'jeditor';
+
+ // Max height
+ if (obj.options.maxHeight) {
+ editor.style.overflowY = 'auto';
+ editor.style.maxHeight = obj.options.maxHeight;
+ }
+
+ // Set editor initial value
+ if (obj.options.value) {
+ var value = obj.options.value;
+ } else {
+ var value = el.innerHTML ? el.innerHTML : '';
+ }
+
+ if (! value) {
+ var value = '<br>';
+ }
+
+ /**
+ * Onchange event controllers
+ */
+ var change = function() {
+ // Events
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: el });
+ }
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, obj, e);
+ }
+ }
+
+ /**
+ * Extract images from a HTML string
+ */
+ var extractImageFromHtml = function(html) {
+ // Create temp element
+ var div = document.createElement('div');
+ div.innerHTML = html;
+
+ // Extract images
+ var img = div.querySelectorAll('img');
+
+ if (img.length) {
+ for (var i = 0; i < img.length; i++) {
+ obj.addImage(img[i].src);
+ }
+ }
+ }
+
+ /**
+ * Insert node at caret
+ */
+ var insertNodeAtCaret = function(newNode) {
+ var sel, range;
+
+ if (window.getSelection) {
+ sel = window.getSelection();
+ if (sel.rangeCount) {
+ range = sel.getRangeAt(0);
+ var selectedText = range.toString();
+ range.deleteContents();
+ range.insertNode(newNode);
+ // move the cursor after element
+ range.setStartAfter(newNode);
+ range.setEndAfter(newNode);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+ }
+
+ /**
+ * Append snippet or thumbs in the editor
+ * @Param object data
+ */
+ var appendElement = function(data) {
+ // Reset snippet
+ snippet.innerHTML = '';
+
+ if (data.image) {
+ var div = document.createElement('div');
+ div.className = 'jsnippet-image';
+ div.setAttribute('data-k', 'image');
+ snippet.appendChild(div);
+
+ var image = document.createElement('img');
+ image.src = data.image;
+ div.appendChild(image);
+ }
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-title';
+ div.setAttribute('data-k', 'title');
+ div.innerHTML = data.title;
+ snippet.appendChild(div);
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-description';
+ div.setAttribute('data-k', 'description');
+ div.innerHTML = data.description;
+ snippet.appendChild(div);
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-host';
+ div.setAttribute('data-k', 'host');
+ div.innerHTML = data.host;
+ snippet.appendChild(div);
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-url';
+ div.setAttribute('data-k', 'url');
+ div.innerHTML = data.url;
+ snippet.appendChild(div);
+
+ editor.appendChild(snippet);
+ }
+
+ var verifyEditor = function() {
+ clearTimeout(editorTimer);
+ editorTimer = setTimeout(function() {
+ var snippet = editor.querySelector('.jsnippet');
+ var thumbsContainer = el.querySelector('.jeditor-thumbs-container');
+
+ if (! snippet && ! thumbsContainer) {
+ var html = editor.innerHTML.replace(/\n/g, ' ');
+ var container = document.createElement('div');
+ container.innerHTML = html;
+ var thumbsContainer = container.querySelector('.jeditor-thumbs-container');
+ if (thumbsContainer) {
+ thumbsContainer.remove();
+ }
+ var text = container.innerText;
+ var url = jSuites.editor.detectUrl(text);
+
+ if (url) {
+ if (url[0].substr(-3) == 'jpg' || url[0].substr(-3) == 'png' || url[0].substr(-3) == 'gif') {
+ if (jSuites.editor.getDomain(url[0]) == window.location.hostname) {
+ obj.importImage(url[0], '');
+ } else {
+ obj.importImage(obj.options.remoteParser + url[0], '');
+ }
+ } else {
+ var id = jSuites.editor.youtubeParser(url[0]);
+ obj.parseWebsite(url[0], id);
+ }
+ }
+ }
+ }, 1000);
+ }
+
+ obj.parseContent = function() {
+ verifyEditor();
+ }
+
+ obj.parseWebsite = function(url, youtubeId) {
+ if (! obj.options.remoteParser) {
+ console.log('The remoteParser is not defined');
+ } else {
+ // Youtube definitions
+ if (youtubeId) {
+ var url = 'https://www.youtube.com/watch?v=' + youtubeId;
+ }
+
+ var p = {
+ title: '',
+ description: '',
+ image: '',
+ host: url.split('/')[2],
+ url: url,
+ }
+
+ jSuites.ajax({
+ url: obj.options.remoteParser + encodeURI(url.trim()),
+ method: 'GET',
+ dataType: 'json',
+ success: function(result) {
+ // Get title
+ if (result.title) {
+ p.title = result.title;
+ }
+ // Description
+ if (result.description) {
+ p.description = result.description;
+ }
+ // Image
+ if (result.image) {
+ p.image = result.image;
+ } else if (result['og:image']) {
+ p.image = result['og:image'];
+ }
+ // Host
+ if (result.host) {
+ p.host = result.host;
+ }
+ // Url
+ if (result.url) {
+ p.url = result.url;
+ }
+
+ appendElement(p);
+ }
+ });
+ }
+ }
+
+ /**
+ * Set editor value
+ */
+ obj.setData = function(html) {
+ editor.innerHTML = html;
+ jSuites.editor.setCursor(editor, true);
+ }
+
+ obj.setValue = obj.setData;
+
+ obj.getText = function() {
+ return editor.innerText;
+ }
+
+ /**
+ * Get editor data
+ */
+ obj.getData = function(json) {
+ if (! json) {
+ var data = editor.innerHTML;
+ } else {
+ var data = {
+ content : '',
+ }
+
+ // Get tag users
+ var tagged = editor.querySelectorAll('.post-tag');
+ if (tagged.length) {
+ data.users = [];
+ for (var i = 0; i < tagged.length; i++) {
+ var userId = tagged[i].getAttribute('data-user');
+ if (userId) {
+ data.users.push(userId);
+ }
+ }
+ data.users = data.users.join(',');
+ }
+
+ if (snippet.innerHTML) {
+ var index = 0;
+ data.snippet = {};
+ for (var i = 0; i < snippet.children.length; i++) {
+ // Get key from element
+ var key = snippet.children[i].getAttribute('data-k');
+ if (key) {
+ if (key == 'image') {
+ data.snippet.image = snippet.children[i].children[0].getAttribute('src');
+ } else {
+ data.snippet[key] = snippet.children[i].innerHTML;
+ }
+ }
+ }
+
+ snippet.innerHTML = '';
+ snippet.remove();
+ }
+
+ var text = editor.innerHTML;
+ text = text.replace(/<br>/g, "\n");
+ text = text.replace(/<\/div>/g, "<\/div>\n");
+ text = text.replace(/<(?:.|\n)*?>/gm, "");
+ data.content = text.trim();
+ data = JSON.stringify(data);
+ }
+
+ return data;
+ }
+
+ // Reset
+ obj.reset = function() {
+ editor.innerHTML = '';
+ }
+
+ obj.addPdf = function(data) {
+ if (data.result.substr(0,4) != 'data') {
+ console.error('Invalid source');
+ } else {
+ var canvas = document.createElement('canvas');
+ canvas.width = 60;
+ canvas.height = 60;
+
+ var img = new Image();
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ canvas.toBlob(function(blob) {
+ var newImage = document.createElement('img');
+ newImage.src = window.URL.createObjectURL(blob);
+ newImage.setAttribute('data-extension', 'pdf');
+ if (data.name) {
+ newImage.setAttribute('data-name', data.name);
+ }
+ if (data.size) {
+ newImage.setAttribute('data-size', data.size);
+ }
+ if (data.date) {
+ newImage.setAttribute('data-date', data.date);
+ }
+ newImage.className = 'jfile pdf';
+
+ insertNodeAtCaret(newImage);
+
+ // Image content
+ newImage.content = data.result.substr(data.result.indexOf(',') + 1);
+ });
+ }
+ }
+
+ obj.getFiles = function() {
+ return jSuites.files(editor).get();
+ }
+
+ obj.addImage = function(src, name, size, date) {
+ if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
+ console.error('remoteParser not defined in your initialization');
+ } else {
+ // This is to process cross domain images
+ if (src.substr(0,4) == 'data') {
+ var extension = src.split(';')
+ extension = extension[0].split('/');
+ extension = extension[1];
+ } else {
+ var extension = src.substr(src.lastIndexOf('.') + 1);
+ // Work for cross browsers
+ src = obj.options.remoteParser + src;
+ }
+
+ var img = new Image();
+
+ img.onload = function onload() {
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ canvas.toBlob(function(blob) {
+ var newImage = document.createElement('img');
+ newImage.src = window.URL.createObjectURL(blob);
+ newImage.setAttribute('tabindex', '900');
+ newImage.setAttribute('data-extension', extension);
+ if (name) {
+ newImage.setAttribute('data-name', name);
+ }
+ if (size) {
+ newImage.setAttribute('data-size', size);
+ }
+ if (date) {
+ newImage.setAttribute('data-date', date);
+ }
+ newImage.className = 'jfile';
+ var content = canvas.toDataURL();
+ insertNodeAtCaret(newImage);
+
+ // Image content
+ newImage.content = content.substr(content.indexOf(',') + 1);
+
+ change();
+ });
+ };
+
+ img.src = src;
+ }
+ }
+
+ obj.addFile = function(files) {
+ var reader = [];
+
+ for (var i = 0; i < files.length; i++) {
+ if (files[i].size > obj.options.maxFileSize) {
+ alert('The file is too big');
+ } else {
+ // Only PDF or Images
+ var type = files[i].type.split('/');
+
+ if (type[0] == 'image') {
+ type = 1;
+ } else if (type[1] == 'pdf') {
+ type = 2;
+ } else {
+ type = 0;
+ }
+
+ if (type) {
+ // Create file
+ reader[i] = new FileReader();
+ reader[i].index = i;
+ reader[i].type = type;
+ reader[i].name = files[i].name;
+ reader[i].date = files[i].lastModified;
+ reader[i].size = files[i].size;
+ reader[i].addEventListener("load", function (data) {
+ // Get result
+ if (data.target.type == 2) {
+ if (obj.options.acceptFiles == true) {
+ obj.addPdf(data.target);
+ }
+ } else {
+ obj.addImage(data.target.result, data.target.name, data.total, data.target.lastModified);
+ }
+ }, false);
+
+ reader[i].readAsDataURL(files[i])
+ } else {
+ alert('The extension is not allowed');
+ }
+ }
+ }
+ }
+
+ // Destroy
+ obj.destroy = function() {
+ editor.removeEventListener('mouseup', editorMouseUp);
+ editor.removeEventListener('mousedown', editorMouseDown);
+ editor.removeEventListener('mousemove', editorMouseMove);
+ editor.removeEventListener('keyup', editorKeyUp);
+ editor.removeEventListener('keydown', editorKeyDown);
+ editor.removeEventListener('dragstart', editorDragStart);
+ editor.removeEventListener('dragenter', editorDragEnter);
+ editor.removeEventListener('dragover', editorDragOver);
+ editor.removeEventListener('drop', editorDrop);
+ editor.removeEventListener('paste', editorPaste);
+
+ if (typeof(obj.options.onblur) == 'function') {
+ editor.removeEventListener('blur', editorBlur);
+ }
+ if (typeof(obj.options.onfocus) == 'function') {
+ editor.removeEventListener('focus', editorFocus);
+ }
+
+ el.editor = null;
+ el.classList.remove('jeditor-container');
+
+ toolbar.remove();
+ snippet.remove();
+ editor.remove();
+ }
+
+ var isLetter = function (str) {
+ var regex = /([\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]+)/g;
+ return str.match(regex) ? 1 : 0;
+ }
+
+ // Event handlers
+ var editorMouseUp = function(e) {
+ editorAction = false;
+ }
+
+ var editorMouseDown = function(e) {
+ var close = function(snippet) {
+ var rect = snippet.getBoundingClientRect();
+ if (rect.width - (e.clientX - rect.left) < 40 && e.clientY - rect.top < 40) {
+ snippet.innerHTML = '';
+ snippet.remove();
+ }
+ }
+
+ if (e.target.tagName == 'IMG') {
+ if (e.target.style.cursor) {
+ var rect = e.target.getBoundingClientRect();
+ editorAction = {
+ e: e.target,
+ x: e.clientX,
+ y: e.clientY,
+ w: rect.width,
+ h: rect.height,
+ d: e.target.style.cursor,
+ }
+
+ if (! e.target.style.width) {
+ e.target.style.width = rect.width + 'px';
+ }
+
+ if (! e.target.style.height) {
+ e.target.style.height = rect.height + 'px';
+ }
+
+ var s = window.getSelection();
+ if (s.rangeCount) {
+ for (var i = 0; i < s.rangeCount; i++) {
+ s.removeRange(s.getRangeAt(i));
+ }
+ }
+ } else {
+ editorAction = true;
+ }
+ } else {
+ if (e.target.classList.contains('jsnippet')) {
+ close(e.target);
+ } else if (e.target.parentNode.classList.contains('jsnippet')) {
+ close(e.target.parentNode);
+ }
+
+ editorAction = true;
+ }
+ }
+
+ var editorMouseMove = function(e) {
+ if (e.target.tagName == 'IMG' && obj.options.allowImageResize == true) {
+ if (e.target.getAttribute('tabindex')) {
+ var rect = e.target.getBoundingClientRect();
+ if (e.clientY - rect.top < 5) {
+ if (rect.width - (e.clientX - rect.left) < 5) {
+ e.target.style.cursor = 'ne-resize';
+ } else if (e.clientX - rect.left < 5) {
+ e.target.style.cursor = 'nw-resize';
+ } else {
+ e.target.style.cursor = 'n-resize';
+ }
+ } else if (rect.height - (e.clientY - rect.top) < 5) {
+ if (rect.width - (e.clientX - rect.left) < 5) {
+ e.target.style.cursor = 'se-resize';
+ } else if (e.clientX - rect.left < 5) {
+ e.target.style.cursor = 'sw-resize';
+ } else {
+ e.target.style.cursor = 's-resize';
+ }
+ } else if (rect.width - (e.clientX - rect.left) < 5) {
+ e.target.style.cursor = 'e-resize';
+ } else if (e.clientX - rect.left < 5) {
+ e.target.style.cursor = 'w-resize';
+ } else {
+ e.target.style.cursor = '';
+ }
+ }
+ }
+
+ // Move
+ if (e.which == 1 && editorAction && editorAction.d) {
+ if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') {
+ editorAction.e.style.width = (editorAction.w + (e.clientX - editorAction.x)) + 'px';
+
+ if (e.shiftKey) {
+ var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w);
+ editorAction.e.style.height = editorAction.h + newHeight + 'px';
+ } else {
+ var newHeight = null;
+ }
+ }
+
+ if (! newHeight) {
+ if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') {
+ if (! e.shiftKey) {
+ editorAction.e.style.height = editorAction.h + (e.clientY - editorAction.y) + 'px';
+ }
+ }
+ }
+ }
+ }
+
+ var editorKeyUp = function(e) {
+ if (! editor.innerHTML) {
+ editor.innerHTML = '<div><br></div>';
+ }
+
+ if (typeof(obj.options.onkeyup) == 'function') {
+ obj.options.onkeyup(el, obj, e);
+ }
+
+ change(e);
+ }
+
+
+ var editorKeyDown = function(e) {
+ // Check for URL
+ if (obj.options.parseURL == true) {
+ verifyEditor();
+ }
+
+ if (typeof(obj.options.onkeydown) == 'function') {
+ obj.options.onkeydown(el, obj, e);
+ }
+ }
+
+ var editorPaste = function(e) {
+ if (e.clipboardData || e.originalEvent.clipboardData) {
+ var html = (e.originalEvent || e).clipboardData.getData('text/html');
+ var text = (e.originalEvent || e).clipboardData.getData('text/plain');
+ var file = (e.originalEvent || e).clipboardData.files
+ } else if (window.clipboardData) {
+ var html = window.clipboardData.getData('Html');
+ var text = window.clipboardData.getData('Text');
+ var file = window.clipboardData.files
+ }
+
+ if (file.length) {
+ // Paste a image from the clipboard
+ obj.addFile(file);
+ } else {
+ // Paste text
+ text = text.split('\r\n');
+ var str = '';
+ if (e.target.nodeName == 'DIV' && e.target.classList.contains('jeditor')) {
+ for (var i = 0; i < text.length; i++) {
+ var tmp = document.createElement('div');
+ if (text[i]) {
+ tmp.innerHTML = text[i];
+ } else {
+ tmp.innerHTML = '<br/>';
+ }
+ e.target.appendChild(tmp);
+ }
+ } else {
+ for (var i = 0; i < text.length; i++) {
+ if (text[i]) {
+ str += '<div>' + text[i] + "</div>\r\n";
+ }
+ }
+ // Insert text
+ document.execCommand('insertHtml', false, str);
+ }
+
+ // Extra images from the paste
+ if (obj.options.acceptImages == true) {
+ extractImageFromHtml(html);
+ }
+ }
+
+ e.preventDefault();
+ }
+
+ var editorDragStart = function(e) {
+ if (editorAction && editorAction.e) {
+ e.preventDefault();
+ }
+ }
+
+ var editorDragEnter = function(e) {
+ if (editorAction || obj.options.dropZone == false) {
+ // Do nothing
+ } else {
+ el.classList.add('jeditor-dragging');
+ }
+ }
+
+ var editorDragOver = function(e) {
+ if (editorAction || obj.options.dropZone == false) {
+ // Do nothing
+ } else {
+ if (editorTimer) {
+ clearTimeout(editorTimer);
+ }
+
+ editorTimer = setTimeout(function() {
+ el.classList.remove('jeditor-dragging');
+ }, 100);
+ }
+ }
+
+ var editorDrop = function(e) {
+ if (editorAction || obj.options.dropZone == false) {
+ // Do nothing
+ } else {
+ // Position caret on the drop
+ var range = null;
+ if (document.caretRangeFromPoint) {
+ range=document.caretRangeFromPoint(e.clientX, e.clientY);
+ } else if (e.rangeParent) {
+ range=document.createRange();
+ range.setStart(e.rangeParent,e.rangeOffset);
+ }
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ sel.anchorNode.parentNode.focus();
+
+ var html = (e.originalEvent || e).dataTransfer.getData('text/html');
+ var text = (e.originalEvent || e).dataTransfer.getData('text/plain');
+ var file = (e.originalEvent || e).dataTransfer.files;
+
+ if (file.length) {
+ obj.addFile(file);
+ } else if (text) {
+ extractImageFromHtml(html);
+ }
+
+ el.classList.remove('jeditor-dragging');
+ e.preventDefault();
+ }
+ }
+
+ var editorBlur = function(e) {
+ obj.options.onblur(el, obj, e);
+ }
+
+ var editorFocus = function(e) {
+ obj.options.onfocus(el, obj, e);
+ }
+
+ editor.addEventListener('mouseup', editorMouseUp);
+ editor.addEventListener('mousedown', editorMouseDown);
+ editor.addEventListener('mousemove', editorMouseMove);
+ editor.addEventListener('keyup', editorKeyUp);
+ editor.addEventListener('keydown', editorKeyDown);
+ editor.addEventListener('dragstart', editorDragStart);
+ editor.addEventListener('dragenter', editorDragEnter);
+ editor.addEventListener('dragover', editorDragOver);
+ editor.addEventListener('drop', editorDrop);
+ editor.addEventListener('paste', editorPaste);
+
+ // Blur
+ if (typeof(obj.options.onblur) == 'function') {
+ editor.addEventListener('blur', editorBlur);
+ }
+
+ // Focus
+ if (typeof(obj.options.onfocus) == 'function') {
+ editor.addEventListener('focus', editorFocus);
+ }
+
+ // Onload
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj, editor);
+ }
+
+ // Set value to the editor
+ editor.innerHTML = value;
+
+ // Append editor to the containre
+ el.appendChild(editor);
+
+ // Snippet
+ if (obj.options.snippet) {
+ appendElement(obj.options.snippet);
+ }
+
+ // Default toolbar
+ if (obj.options.toolbar == null) {
+ obj.options.toolbar = jSuites.editor.getDefaultToolbar();
+ }
+
+ // Add toolbar
+ if (obj.options.toolbar) {
+ // Create toolbar
+ jSuites.toolbar(toolbar, {
+ container: true,
+ items: obj.options.toolbar
+ });
+ // Append to the DOM
+ el.appendChild(toolbar);
+ }
+
+ // Focus to the editor
+ if (obj.options.focus) {
+ jSuites.editor.setCursor(editor, obj.options.focus == 'initial' ? true : false);
+ }
+
+ el.editor = obj;
+
+ return obj;
+});
+
+jSuites.editor.setCursor = function(element, first) {
+ element.focus();
+ document.execCommand('selectAll');
+ var sel = window.getSelection();
+ var range = sel.getRangeAt(0);
+ if (first == true) {
+ var node = range.startContainer;
+ var size = 0;
+ } else {
+ var node = range.endContainer;
+ var size = node.length;
+ }
+ range.setStart(node, size);
+ range.setEnd(node, size);
+ sel.removeAllRanges();
+ sel.addRange(range);
+}
+
+jSuites.editor.getDomain = function(url) {
+ return url.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0].split(/:/g)[0];
+}
+
+jSuites.editor.detectUrl = function(text) {
+ var expression = /(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig;
+ var links = text.match(expression);
+
+ if (links) {
+ if (links[0].substr(0,3) == 'www') {
+ links[0] = 'http://' + links[0];
+ }
+ }
+
+ return links;
+}
+
+jSuites.editor.youtubeParser = function(url) {
+ var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
+ var match = url.match(regExp);
+
+ return (match && match[7].length == 11) ? match[7] : false;
+}
+
+jSuites.editor.getDefaultToolbar = function() {
+ return [
+ {
+ content: 'undo',
+ onclick: function() {
+ document.execCommand('undo');
+ }
+ },
+ {
+ content: 'redo',
+ onclick: function() {
+ document.execCommand('redo');
+ }
+ },
+ {
+ type:'divisor'
+ },
+ {
+ content: 'format_bold',
+ onclick: function(a,b,c) {
+ document.execCommand('bold');
+
+ if (document.queryCommandState("bold")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_italic',
+ onclick: function(a,b,c) {
+ document.execCommand('italic');
+
+ if (document.queryCommandState("italic")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_underline',
+ onclick: function(a,b,c) {
+ document.execCommand('underline');
+
+ if (document.queryCommandState("underline")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ type:'divisor'
+ },
+ {
+ content: 'format_list_bulleted',
+ onclick: function(a,b,c) {
+ document.execCommand('insertUnorderedList');
+
+ if (document.queryCommandState("insertUnorderedList")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_list_numbered',
+ onclick: function(a,b,c) {
+ document.execCommand('insertOrderedList');
+
+ if (document.queryCommandState("insertOrderedList")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_indent_increase',
+ onclick: function(a,b,c) {
+ document.execCommand('indent', true, null);
+
+ if (document.queryCommandState("indent")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_indent_decrease',
+ onclick: function() {
+ document.execCommand('outdent');
+
+ if (document.queryCommandState("outdent")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ }/*,
+ {
+ icon: ['format_align_left', 'format_align_right', 'format_align_center'],
+ onclick: function() {
+ document.execCommand('justifyCenter');
+
+ if (document.queryCommandState("justifyCenter")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ }
+ {
+ type:'select',
+ items: ['Verdana','Arial','Courier New'],
+ onchange: function() {
+ }
+ },
+ {
+ type:'select',
+ items: ['10px','12px','14px','16px','18px','20px','22px'],
+ onchange: function() {
+ }
+ },
+ {
+ icon:'format_align_left',
+ onclick: function() {
+ document.execCommand('JustifyLeft');
+
+ if (document.queryCommandState("JustifyLeft")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_align_center',
+ onclick: function() {
+ document.execCommand('justifyCenter');
+
+ if (document.queryCommandState("justifyCenter")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_align_right',
+ onclick: function() {
+ document.execCommand('justifyRight');
+
+ if (document.queryCommandState("justifyRight")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_align_justify',
+ onclick: function() {
+ document.execCommand('justifyFull');
+
+ if (document.queryCommandState("justifyFull")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_list_bulleted',
+ onclick: function() {
+ document.execCommand('insertUnorderedList');
+
+ if (document.queryCommandState("insertUnorderedList")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ }*/
+ ];
+}
+
+
+jSuites.isNumeric = (function (num) {
+ return !isNaN(num) && num != null && num != '';
+});
+
+jSuites.guid = function() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+}
+
+jSuites.getWindowWidth = function() {
+ var w = window,
+ d = document,
+ e = d.documentElement,
+ g = d.getElementsByTagName('body')[0],
+ x = w.innerWidth || e.clientWidth || g.clientWidth;
+ return x;
+}
+
+jSuites.getWindowHeight = function() {
+ var w = window,
+ d = document,
+ e = d.documentElement,
+ g = d.getElementsByTagName('body')[0],
+ y = w.innerHeight|| e.clientHeight|| g.clientHeight;
+ return y;
+}
+
+jSuites.getPosition = function(e) {
+ if (e.changedTouches && e.changedTouches[0]) {
+ var x = e.changedTouches[0].pageX;
+ var y = e.changedTouches[0].pageY;
+ } else {
+ var x = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
+ var y = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
+ }
+
+ return [ x, y ];
+}
+
+jSuites.click = function(el) {
+ if (el.click) {
+ el.click();
+ } else {
+ var evt = new MouseEvent('click', {
+ bubbles: true,
+ cancelable: true,
+ view: window
+ });
+ el.dispatchEvent(evt);
+ }
+}
+
+jSuites.findElement = function(element, condition) {
+ var foundElement = false;
+
+ function path (element) {
+ if (element && ! foundElement) {
+ if (typeof(condition) == 'function') {
+ foundElement = condition(element)
+ } else if (typeof(condition) == 'string') {
+ if (element.classList && element.classList.contains(condition)) {
+ foundElement = element;
+ }
+ }
+ }
+
+ if (element.parentNode && ! foundElement) {
+ path(element.parentNode);
+ }
+ }
+
+ path(element);
+
+ return foundElement;
+}
+
+// Two digits
+jSuites.two = function(value) {
+ value = '' + value;
+ if (value.length == 1) {
+ value = '0' + value;
+ }
+ return value;
+}
+
+jSuites.sha512 = (function(str) {
+ function int64(msint_32, lsint_32) {
+ this.highOrder = msint_32;
+ this.lowOrder = lsint_32;
+ }
+
+ var H = [new int64(0x6a09e667, 0xf3bcc908), new int64(0xbb67ae85, 0x84caa73b),
+ new int64(0x3c6ef372, 0xfe94f82b), new int64(0xa54ff53a, 0x5f1d36f1),
+ new int64(0x510e527f, 0xade682d1), new int64(0x9b05688c, 0x2b3e6c1f),
+ new int64(0x1f83d9ab, 0xfb41bd6b), new int64(0x5be0cd19, 0x137e2179)];
+
+ var K = [new int64(0x428a2f98, 0xd728ae22), new int64(0x71374491, 0x23ef65cd),
+ new int64(0xb5c0fbcf, 0xec4d3b2f), new int64(0xe9b5dba5, 0x8189dbbc),
+ new int64(0x3956c25b, 0xf348b538), new int64(0x59f111f1, 0xb605d019),
+ new int64(0x923f82a4, 0xaf194f9b), new int64(0xab1c5ed5, 0xda6d8118),
+ new int64(0xd807aa98, 0xa3030242), new int64(0x12835b01, 0x45706fbe),
+ new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, 0xd5ffb4e2),
+ new int64(0x72be5d74, 0xf27b896f), new int64(0x80deb1fe, 0x3b1696b1),
+ new int64(0x9bdc06a7, 0x25c71235), new int64(0xc19bf174, 0xcf692694),
+ new int64(0xe49b69c1, 0x9ef14ad2), new int64(0xefbe4786, 0x384f25e3),
+ new int64(0x0fc19dc6, 0x8b8cd5b5), new int64(0x240ca1cc, 0x77ac9c65),
+ new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
+ new int64(0x5cb0a9dc, 0xbd41fbd4), new int64(0x76f988da, 0x831153b5),
+ new int64(0x983e5152, 0xee66dfab), new int64(0xa831c66d, 0x2db43210),
+ new int64(0xb00327c8, 0x98fb213f), new int64(0xbf597fc7, 0xbeef0ee4),
+ new int64(0xc6e00bf3, 0x3da88fc2), new int64(0xd5a79147, 0x930aa725),
+ new int64(0x06ca6351, 0xe003826f), new int64(0x14292967, 0x0a0e6e70),
+ new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
+ new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, 0x9d95b3df),
+ new int64(0x650a7354, 0x8baf63de), new int64(0x766a0abb, 0x3c77b2a8),
+ new int64(0x81c2c92e, 0x47edaee6), new int64(0x92722c85, 0x1482353b),
+ new int64(0xa2bfe8a1, 0x4cf10364), new int64(0xa81a664b, 0xbc423001),
+ new int64(0xc24b8b70, 0xd0f89791), new int64(0xc76c51a3, 0x0654be30),
+ new int64(0xd192e819, 0xd6ef5218), new int64(0xd6990624, 0x5565a910),
+ new int64(0xf40e3585, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
+ new int64(0x19a4c116, 0xb8d2d0c8), new int64(0x1e376c08, 0x5141ab53),
+ new int64(0x2748774c, 0xdf8eeb99), new int64(0x34b0bcb5, 0xe19b48a8),
+ new int64(0x391c0cb3, 0xc5c95a63), new int64(0x4ed8aa4a, 0xe3418acb),
+ new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, 0xd6b2b8a3),
+ new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
+ new int64(0x84c87814, 0xa1f0ab72), new int64(0x8cc70208, 0x1a6439ec),
+ new int64(0x90befffa, 0x23631e28), new int64(0xa4506ceb, 0xde82bde9),
+ new int64(0xbef9a3f7, 0xb2c67915), new int64(0xc67178f2, 0xe372532b),
+ new int64(0xca273ece, 0xea26619c), new int64(0xd186b8c7, 0x21c0c207),
+ new int64(0xeada7dd6, 0xcde0eb1e), new int64(0xf57d4f7f, 0xee6ed178),
+ new int64(0x06f067aa, 0x72176fba), new int64(0x0a637dc5, 0xa2c898a6),
+ new int64(0x113f9804, 0xbef90dae), new int64(0x1b710b35, 0x131c471b),
+ new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
+ new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, 0x9c100d4c),
+ new int64(0x4cc5d4be, 0xcb3e42b6), new int64(0x597f299c, 0xfc657e2a),
+ new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)];
+
+ var W = new Array(64);
+ var a, b, c, d, e, f, g, h, i, j;
+ var T1, T2;
+ var charsize = 8;
+
+ function utf8_encode(str) {
+ return unescape(encodeURIComponent(str));
+ }
+
+ function str2binb(str) {
+ var bin = [];
+ var mask = (1 << charsize) - 1;
+ var len = str.length * charsize;
+
+ for (var i = 0; i < len; i += charsize) {
+ bin[i >> 5] |= (str.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32));
+ }
+
+ return bin;
+ }
+
+ function binb2hex(binarray) {
+ var hex_tab = "0123456789abcdef";
+ var str = "";
+ var length = binarray.length * 4;
+ var srcByte;
+
+ for (var i = 0; i < length; i += 1) {
+ srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
+ str += hex_tab.charAt((srcByte >> 4) & 0xF) + hex_tab.charAt(srcByte & 0xF);
+ }
+
+ return str;
+ }
+
+ function safe_add_2(x, y) {
+ var lsw, msw, lowOrder, highOrder;
+
+ lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
+ msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
+ lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
+ msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
+ highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ return new int64(highOrder, lowOrder);
+ }
+
+ function safe_add_4(a, b, c, d) {
+ var lsw, msw, lowOrder, highOrder;
+
+ lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
+ msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
+ lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
+ msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
+ highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ return new int64(highOrder, lowOrder);
+ }
+
+ function safe_add_5(a, b, c, d, e) {
+ var lsw, msw, lowOrder, highOrder;
+
+ lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + (e.lowOrder & 0xFFFF);
+ msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + (lsw >>> 16);
+ lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (e.highOrder & 0xFFFF) + (msw >>> 16);
+ msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (e.highOrder >>> 16) + (lsw >>> 16);
+ highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ return new int64(highOrder, lowOrder);
+ }
+
+ function maj(x, y, z) {
+ return new int64(
+ (x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder),
+ (x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder)
+ );
+ }
+
+ function ch(x, y, z) {
+ return new int64(
+ (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
+ (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
+ );
+ }
+
+ function rotr(x, n) {
+ if (n <= 32) {
+ return new int64(
+ (x.highOrder >>> n) | (x.lowOrder << (32 - n)),
+ (x.lowOrder >>> n) | (x.highOrder << (32 - n))
+ );
+ } else {
+ return new int64(
+ (x.lowOrder >>> n) | (x.highOrder << (32 - n)),
+ (x.highOrder >>> n) | (x.lowOrder << (32 - n))
+ );
+ }
+ }
+
+ function sigma0(x) {
+ var rotr28 = rotr(x, 28);
+ var rotr34 = rotr(x, 34);
+ var rotr39 = rotr(x, 39);
+
+ return new int64(
+ rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
+ rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
+ );
+ }
+
+ function sigma1(x) {
+ var rotr14 = rotr(x, 14);
+ var rotr18 = rotr(x, 18);
+ var rotr41 = rotr(x, 41);
+
+ return new int64(
+ rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
+ rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
+ );
+ }
+
+ function gamma0(x) {
+ var rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7);
+
+ return new int64(
+ rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
+ rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
+ );
+ }
+
+ function gamma1(x) {
+ var rotr19 = rotr(x, 19);
+ var rotr61 = rotr(x, 61);
+ var shr6 = shr(x, 6);
+
+ return new int64(
+ rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
+ rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
+ );
+ }
+
+ function shr(x, n) {
+ if (n <= 32) {
+ return new int64(
+ x.highOrder >>> n,
+ x.lowOrder >>> n | (x.highOrder << (32 - n))
+ );
+ } else {
+ return new int64(
+ 0,
+ x.highOrder << (32 - n)
+ );
+ }
+ }
+
+ var str = utf8_encode(str);
+ var strlen = str.length*charsize;
+ str = str2binb(str);
+
+ str[strlen >> 5] |= 0x80 << (24 - strlen % 32);
+ str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
+
+ for (var i = 0; i < str.length; i += 32) {
+ a = H[0];
+ b = H[1];
+ c = H[2];
+ d = H[3];
+ e = H[4];
+ f = H[5];
+ g = H[6];
+ h = H[7];
+
+ for (var j = 0; j < 80; j++) {
+ if (j < 16) {
+ W[j] = new int64(str[j*2 + i], str[j*2 + i + 1]);
+ } else {
+ W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]);
+ }
+
+ T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]);
+ T2 = safe_add_2(sigma0(a), maj(a, b, c));
+ h = g;
+ g = f;
+ f = e;
+ e = safe_add_2(d, T1);
+ d = c;
+ c = b;
+ b = a;
+ a = safe_add_2(T1, T2);
+ }
+
+ H[0] = safe_add_2(a, H[0]);
+ H[1] = safe_add_2(b, H[1]);
+ H[2] = safe_add_2(c, H[2]);
+ H[3] = safe_add_2(d, H[3]);
+ H[4] = safe_add_2(e, H[4]);
+ H[5] = safe_add_2(f, H[5]);
+ H[6] = safe_add_2(g, H[6]);
+ H[7] = safe_add_2(h, H[7]);
+ }
+
+ var binarray = [];
+ for (var i = 0; i < H.length; i++) {
+ binarray.push(H[i].highOrder);
+ binarray.push(H[i].lowOrder);
+ }
+
+ return binb2hex(binarray);
+});
+
+if (! jSuites.login) {
+ jSuites.login = {};
+ jSuites.login.sha512 = jSuites.sha512;
+}
+
+jSuites.image = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ input: false,
+ minWidth: false,
+ maxWidth: null,
+ maxHeight: null,
+ maxJpegSizeBytes: null, // For example, 350Kb would be 350000
+ onchange: null,
+ singleFile: true,
+ remoteParser: null,
+ text:{
+ extensionNotAllowed:'The extension is not allowed',
+ imageTooSmall:'The resolution is too low, try a image with a better resolution. width > 800px',
+ }
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Upload icon
+ el.classList.add('jupload');
+
+ if (obj.options.input == true) {
+ el.classList.add('input');
+ }
+
+ // Add image
+ obj.addImage = function(file) {
+ if (! file.date) {
+ file.date = '';
+ }
+ var img = document.createElement('img');
+ img.setAttribute('data-date', file.lastmodified ? file.lastmodified : file.date);
+ img.setAttribute('data-name', file.name);
+ img.setAttribute('data-size', file.size);
+ img.setAttribute('data-small', file.small ? file.small : '');
+ img.setAttribute('data-cover', file.cover ? 1 : 0);
+ img.setAttribute('data-extension', file.extension);
+ img.setAttribute('src', file.file);
+ img.className = 'jfile';
+ img.style.width = '100%';
+
+ return img;
+ }
+
+ // Add image
+ obj.addImages = function(files) {
+ if (obj.options.singleFile == true) {
+ el.innerHTML = '';
+ }
+
+ for (var i = 0; i < files.length; i++) {
+ el.appendChild(obj.addImage(files[i]));
+ }
+ }
+
+ obj.addFromFile = function(file) {
+ var type = file.type.split('/');
+ if (type[0] == 'image') {
+ if (obj.options.singleFile == true) {
+ el.innerHTML = '';
+ }
+
+ var imageFile = new FileReader();
+ imageFile.addEventListener("load", function (v) {
+
+ var img = new Image();
+
+ img.onload = function onload() {
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ var data = {
+ file: obj.getDataURL(canvas, file.type),
+ extension: file.name.substr(file.name.lastIndexOf('.') + 1),
+ name: file.name,
+ size: file.size,
+ lastmodified: file.lastModified,
+ }
+ var newImage = obj.addImage(data);
+ el.appendChild(newImage);
+
+ // Onchange
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(newImage);
+ }
+ };
+
+ img.src = v.srcElement.result;
+ });
+
+ imageFile.readAsDataURL(file);
+ } else {
+ alert(text.extentionNotAllowed);
+ }
+ }
+
+ obj.addFromUrl = function(src) {
+ if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
+ console.error('remoteParser not defined in your initialization');
+ } else {
+ // This is to process cross domain images
+ if (src.substr(0,4) == 'data') {
+ var extension = src.split(';')
+ extension = extension[0].split('/');
+ extension = extension[1];
+ } else {
+ var extension = src.substr(src.lastIndexOf('.') + 1);
+ // Work for cross browsers
+ src = obj.options.remoteParser + src;
+ }
+
+ var img = new Image();
+
+ img.onload = function onload() {
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ canvas.toBlob(function(blob) {
+ var data = {
+ file: window.URL.createObjectURL(blob),
+ extension: extension
+ }
+ var newImage = obj.addImage(data);
+ el.appendChild(newImage);
+
+ // Keep base64 ready to go
+ var content = canvas.toDataURL();
+
+ // Onchange
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(newImage);
+ }
+ });
+ };
+
+ img.src = src;
+ }
+ }
+
+ obj.getCanvas = function(img) {
+ var canvas = document.createElement('canvas');
+ var r1 = (obj.options.maxWidth || img.width ) / img.width;
+ var r2 = (obj.options.maxHeight || img.height) / img.height;
+ var r = Math.min(r1, r2, 1);
+ canvas.width = img.width * r;
+ canvas.height = img.height * r;
+ return canvas;
+ }
+
+ obj.getDataURL = function(canvas, type) {
+ var compression = 0.92;
+ var lastContentLength = null;
+ var content = canvas.toDataURL(type, compression);
+ while (obj.options.maxJpegSizeBytes && type === 'image/jpeg' &&
+ content.length > obj.options.maxJpegSizeBytes && content.length !== lastContentLength) {
+ // Apply the compression
+ compression *= 0.9;
+ lastContentLength = content.length;
+ content = canvas.toDataURL(type, compression);
+ }
+ return content;
+ }
+
+ var attachmentInput = document.createElement('input');
+ attachmentInput.type = 'file';
+ attachmentInput.setAttribute('accept', 'image/*');
+ attachmentInput.onchange = function() {
+ for (var i = 0; i < this.files.length; i++) {
+ obj.addFromFile(this.files[i]);
+ }
+ }
+
+ el.addEventListener("click", function(e) {
+ jSuites.click(attachmentInput);
+ });
+
+ el.addEventListener('dragenter', function(e) {
+ el.style.border = '1px dashed #000';
+ });
+
+ el.addEventListener('dragleave', function(e) {
+ el.style.border = '1px solid #eee';
+ });
+
+ el.addEventListener('dragstop', function(e) {
+ el.style.border = '1px solid #eee';
+ });
+
+ el.addEventListener('dragover', function(e) {
+ e.preventDefault();
+ });
+
+ el.addEventListener('drop', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+
+ var html = (e.originalEvent || e).dataTransfer.getData('text/html');
+ var file = (e.originalEvent || e).dataTransfer.files;
+
+ if (file.length) {
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
+ obj.addFromFile(e.dataTransfer.files[i]);
+ }
+ } else if (html) {
+ if (obj.options.singleFile == true) {
+ el.innerHTML = '';
+ }
+
+ // Create temp element
+ var div = document.createElement('div');
+ div.innerHTML = html;
+
+ // Extract images
+ var img = div.querySelectorAll('img');
+
+ if (img.length) {
+ for (var i = 0; i < img.length; i++) {
+ obj.addFromUrl(img[i].src);
+ }
+ }
+ }
+
+ el.style.border = '1px solid #eee';
+
+ return false;
+ });
+
+ el.image = obj;
+
+ return obj;
+});
+
+
+jSuites.lazyLoading = (function(el, options) {
+ var obj = {}
+
+ // Mandatory options
+ if (! options.loadUp || typeof(options.loadUp) != 'function') {
+ options.loadUp = function() {
+ return false;
+ }
+ }
+ if (! options.loadDown || typeof(options.loadDown) != 'function') {
+ options.loadDown = function() {
+ return false;
+ }
+ }
+ // Timer ms
+ if (! options.timer) {
+ options.timer = 100;
+ }
+
+ // Timer
+ var timeControlLoading = null;
+
+ // Controls
+ var scrollControls = function(e) {
+ if (timeControlLoading == null) {
+ var scrollTop = el.scrollTop;
+ if (el.scrollTop + (el.clientHeight * 2) >= el.scrollHeight) {
+ if (options.loadDown()) {
+ if (scrollTop == el.scrollTop) {
+ el.scrollTop = el.scrollTop - (el.clientHeight);
+ }
+ }
+ } else if (el.scrollTop <= el.clientHeight) {
+ if (options.loadUp()) {
+ if (scrollTop == el.scrollTop) {
+ el.scrollTop = el.scrollTop + (el.clientHeight);
+ }
+ }
+ }
+
+ timeControlLoading = setTimeout(function() {
+ timeControlLoading = null;
+ }, options.timer);
+ }
+ }
+
+ // Onscroll
+ el.onscroll = function(e) {
+ scrollControls(e);
+ }
+
+ el.onwheel = function(e) {
+ scrollControls(e);
+ }
+
+ return obj;
+});
+
+jSuites.loading = (function() {
+ var obj = {};
+
+ var loading = null;
+
+ obj.show = function() {
+ if (! loading) {
+ loading = document.createElement('div');
+ loading.className = 'jloading';
+ }
+ document.body.appendChild(loading);
+ }
+
+ obj.hide = function() {
+ if (loading) {
+ document.body.removeChild(loading);
+ }
+ }
+
+ return obj;
+})();
+
+jSuites.mask = (function() {
+ var obj = {};
+ var index = 0;
+ var values = []
+ var pieces = [];
+
+ /**
+ * Apply a mask over a value considering a custom decimal representation. Default: '.'
+ */
+ obj.run = function(value, mask, decimal) {
+ if (value.toString().length && mask.toString().length) {
+ // Default decimal separator
+ if (typeof(decimal) == 'undefined') {
+ decimal = '.';
+ }
+
+ if (jSuites.isNumeric(value)) {
+ var number = (''+value).split(decimal);
+ var value = number[0];
+ var valueDecimal = number[1];
+ } else {
+ value = '' + value;
+ }
+
+ // Helpers
+ index = 0;
+ values = [];
+ // Create mask token
+ obj.prepare(mask);
+ // Current value
+ var currentValue = value;
+ if (currentValue) {
+ // Checking current value
+ for (var i = 0; i < currentValue.length; i++) {
+ if (currentValue[i] != null) {
+ obj.process(currentValue[i]);
+ }
+ }
+ }
+ if (valueDecimal) {
+ obj.process(decimal);
+ var currentValue = valueDecimal;
+ if (currentValue) {
+ // Checking current value
+ for (var i = 0; i < currentValue.length; i++) {
+ if (currentValue[i] != null) {
+ obj.process(currentValue[i]);
+ }
+ }
+ }
+ }
+ // Formatted value
+ return values.join('');
+ } else {
+ return '';
+ }
+ }
+
+ obj.apply = function(e) {
+ if (e.target && ! e.target.getAttribute('readonly')) {
+ var mask = e.target.getAttribute('data-mask');
+ if (mask) {
+ index = 0;
+ values = [];
+ // Create mask token
+ obj.prepare(mask);
+ // Current value
+ if (e.target.selectionStart < e.target.selectionEnd) {
+ var currentValue = e.target.value.substring(0, e.target.selectionStart);
+ } else {
+ var currentValue = e.target.value;
+ }
+ if (currentValue) {
+ // Checking current value
+ for (var i = 0; i < currentValue.length; i++) {
+ if (currentValue[i] != null) {
+ obj.process(currentValue[i]);
+ }
+ }
+ }
+ // New input
+ if (e.keyCode > 46) {
+ obj.process(obj.fromKeyCode(e));
+ // Prevent default
+ e.preventDefault();
+ }
+ // Update value to the element
+ e.target.value = values.join('');
+ if (pieces.length == values.length && pieces[pieces.length-1].length == values[values.length-1].length) {
+ e.target.setAttribute('data-completed', 'true');
+ } else {
+ e.target.setAttribute('data-completed', 'false');
+ }
+ }
+ }
+ }
+
+ /**
+ * Process inputs and save to values
+ */
+ obj.process = function(input) {
+ do {
+ if (pieces[index] == 'mm') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 1 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 1 && values[index] < 2 && parseInt(input) < 3) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] == 0 && values[index] < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'dd') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 3 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 3 && parseInt(input) < 2) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] < 3 && parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'hh24') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 2 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 2 && parseInt(input) < 4) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] < 2 && parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'hh') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 1 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 1 && parseInt(input) < 3) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] < 1 && parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'mi' || pieces[index] == 'ss') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 5 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'yy' || pieces[index] == 'yyyy') {
+ if (parseInt(input) < 10) {
+ if (values[index] == null || values[index] == '') {
+ values[index] = input;
+ } else {
+ values[index] += input;
+ }
+
+ if (values[index].length == pieces[index].length) {
+ index++;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ } else if (pieces[index] == '#' || pieces[index] == '#.##' || pieces[index] == '#,##' || pieces[index] == '# ##') {
+ if (input.match(/[0-9]/g)) {
+ if (pieces[index] == '#.##') {
+ var separator = '.';
+ } else if (pieces[index] == '#,##') {
+ var separator = ',';
+ } else if (pieces[index] == '# ##') {
+ var separator = ' ';
+ } else {
+ var separator = '';
+ }
+ if (values[index] == null || values[index] == '') {
+ values[index] = input;
+ } else {
+ values[index] += input;
+ if (separator) {
+ values[index] = values[index].match(/[0-9]/g).join('');
+ var t = [];
+ var s = 0;
+ for (var j = values[index].length - 1; j >= 0 ; j--) {
+ t.push(values[index][j]);
+ s++;
+ if (! (s % 3)) {
+ t.push(separator);
+ }
+ }
+ t = t.reverse();
+ values[index] = t.join('');
+ if (values[index].substr(0,1) == separator) {
+ values[index] = values[index].substr(1);
+ }
+ }
+ }
+ return true;
+ } else {
+ if (pieces[index] == '#.##' && input == '.') {
+ // Do nothing
+ } else if (pieces[index] == '#,##' && input == ',') {
+ // Do nothing
+ } else if (pieces[index] == '# ##' && input == ' ') {
+ // Do nothing
+ } else {
+ if (values[index]) {
+ index++;
+ if (pieces[index]) {
+ if (pieces[index] == input) {
+ values[index] = input;
+ return true;
+ } else {
+ if (pieces[index] == '0' && pieces[index+1] == input) {
+ index++;
+ values[index] = input;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ } else if (pieces[index] == '0') {
+ if (input.match(/[0-9]/g)) {
+ values[index] = input;
+ index++;
+ return true;
+ } else {
+ return false;
+ }
+ } else if (pieces[index] == 'a') {
+ if (input.match(/[a-zA-Z]/g)) {
+ values[index] = input;
+ index++;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (pieces[index] != null) {
+ if (pieces[index] == '\\a') {
+ var v = 'a';
+ } else if (pieces[index] == '\\0') {
+ var v = '0';
+ } else if (pieces[index] == '[-]') {
+ if (input == '-' || input == '+') {
+ var v = input;
+ } else {
+ var v = ' ';
+ }
+ } else {
+ var v = pieces[index];
+ }
+ values[index] = v;
+ if (input == v) {
+ index++;
+ return true;
+ }
+ }
+ }
+
+ index++;
+ } while (pieces[index]);
+ }
+
+ /**
+ * Create tokens for the mask
+ */
+ obj.prepare = function(mask) {
+ pieces = [];
+ for (var i = 0; i < mask.length; i++) {
+ if (mask[i].match(/[0-9]|[a-z]|\\/g)) {
+ if (mask[i] == 'y' && mask[i+1] == 'y' && mask[i+2] == 'y' && mask[i+3] == 'y') {
+ pieces.push('yyyy');
+ i += 3;
+ } else if (mask[i] == 'y' && mask[i+1] == 'y') {
+ pieces.push('yy');
+ i++;
+ } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm' && mask[i+3] == 'm') {
+ pieces.push('mmmm');
+ i += 3;
+ } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm') {
+ pieces.push('mmm');
+ i += 2;
+ } else if (mask[i] == 'm' && mask[i+1] == 'm') {
+ pieces.push('mm');
+ i++;
+ } else if (mask[i] == 'd' && mask[i+1] == 'd') {
+ pieces.push('dd');
+ i++;
+ } else if (mask[i] == 'h' && mask[i+1] == 'h' && mask[i+2] == '2' && mask[i+3] == '4') {
+ pieces.push('hh24');
+ i += 3;
+ } else if (mask[i] == 'h' && mask[i+1] == 'h') {
+ pieces.push('hh');
+ i++;
+ } else if (mask[i] == 'm' && mask[i+1] == 'i') {
+ pieces.push('mi');
+ i++;
+ } else if (mask[i] == 's' && mask[i+1] == 's') {
+ pieces.push('ss');
+ i++;
+ } else if (mask[i] == 'a' && mask[i+1] == 'm') {
+ pieces.push('am');
+ i++;
+ } else if (mask[i] == 'p' && mask[i+1] == 'm') {
+ pieces.push('pm');
+ i++;
+ } else if (mask[i] == '\\' && mask[i+1] == '0') {
+ pieces.push('\\0');
+ i++;
+ } else if (mask[i] == '\\' && mask[i+1] == 'a') {
+ pieces.push('\\a');
+ i++;
+ } else {
+ pieces.push(mask[i]);
+ }
+ } else {
+ if (mask[i] == '#' && mask[i+1] == '.' && mask[i+2] == '#' && mask[i+3] == '#') {
+ pieces.push('#.##');
+ i += 3;
+ } else if (mask[i] == '#' && mask[i+1] == ',' && mask[i+2] == '#' && mask[i+3] == '#') {
+ pieces.push('#,##');
+ i += 3;
+ } else if (mask[i] == '#' && mask[i+1] == ' ' && mask[i+2] == '#' && mask[i+3] == '#') {
+ pieces.push('# ##');
+ i += 3;
+ } else if (mask[i] == '[' && mask[i+1] == '-' && mask[i+2] == ']') {
+ pieces.push('[-]');
+ i += 2;
+ } else {
+ pieces.push(mask[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Thanks for the collaboration
+ */
+ obj.fromKeyCode = function(e) {
+ var _to_ascii = {
+ '188': '44',
+ '109': '45',
+ '190': '46',
+ '191': '47',
+ '192': '96',
+ '220': '92',
+ '222': '39',
+ '221': '93',
+ '219': '91',
+ '173': '45',
+ '187': '61', //IE Key codes
+ '186': '59', //IE Key codes
+ '189': '45' //IE Key codes
+ }
+
+ var shiftUps = {
+ "96": "~",
+ "49": "!",
+ "50": "@",
+ "51": "#",
+ "52": "$",
+ "53": "%",
+ "54": "^",
+ "55": "&",
+ "56": "*",
+ "57": "(",
+ "48": ")",
+ "45": "_",
+ "61": "+",
+ "91": "{",
+ "93": "}",
+ "92": "|",
+ "59": ":",
+ "39": "\"",
+ "44": "<",
+ "46": ">",
+ "47": "?"
+ };
+
+ var c = e.which;
+
+ if (_to_ascii.hasOwnProperty(c)) {
+ c = _to_ascii[c];
+ }
+
+ if (!e.shiftKey && (c >= 65 && c <= 90)) {
+ c = String.fromCharCode(c + 32);
+ } else if (e.shiftKey && shiftUps.hasOwnProperty(c)) {
+ c = shiftUps[c];
+ } else if (96 <= c && c <= 105) {
+ c = String.fromCharCode(c - 48);
+ } else {
+ c = String.fromCharCode(c);
+ }
+
+ return c;
+ }
+
+ if (typeof document !== 'undefined') {
+ document.addEventListener('keydown', function(e) {
+ if (jSuites.mask) {
+ jSuites.mask.apply(e);
+ }
+ });
+ }
+
+ return obj;
+})();
+
+
+jSuites.notification = (function(options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ icon: null,
+ name: 'Notification',
+ date: null,
+ error: null,
+ title: null,
+ message: null,
+ timeout: 4000,
+ autoHide: true,
+ closeable: true,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ var notification = document.createElement('div');
+ notification.className = 'jnotification';
+
+ if (obj.options.error) {
+ notification.classList.add('jnotification-error');
+ }
+
+ var notificationContainer = document.createElement('div');
+ notificationContainer.className = 'jnotification-container';
+ notification.appendChild(notificationContainer);
+
+ var notificationHeader = document.createElement('div');
+ notificationHeader.className = 'jnotification-header';
+ notificationContainer.appendChild(notificationHeader);
+
+ var notificationImage = document.createElement('div');
+ notificationImage.className = 'jnotification-image';
+ notificationHeader.appendChild(notificationImage);
+
+ if (obj.options.icon) {
+ var notificationIcon = document.createElement('img');
+ notificationIcon.src = obj.options.icon;
+ notificationImage.appendChild(notificationIcon);
+ }
+
+ var notificationName = document.createElement('div');
+ notificationName.className = 'jnotification-name';
+ notificationName.innerHTML = obj.options.name;
+ notificationHeader.appendChild(notificationName);
+
+ if (obj.options.closeable == true) {
+ var notificationClose = document.createElement('div');
+ notificationClose.className = 'jnotification-close';
+ notificationClose.onclick = function() {
+ obj.hide();
+ }
+ notificationHeader.appendChild(notificationClose);
+ }
+
+ var notificationDate = document.createElement('div');
+ notificationDate.className = 'jnotification-date';
+ notificationHeader.appendChild(notificationDate);
+
+ var notificationContent = document.createElement('div');
+ notificationContent.className = 'jnotification-content';
+ notificationContainer.appendChild(notificationContent);
+
+ if (obj.options.title) {
+ var notificationTitle = document.createElement('div');
+ notificationTitle.className = 'jnotification-title';
+ notificationTitle.innerHTML = obj.options.title;
+ notificationContent.appendChild(notificationTitle);
+ }
+
+ var notificationMessage = document.createElement('div');
+ notificationMessage.className = 'jnotification-message';
+ notificationMessage.innerHTML = obj.options.message;
+ notificationContent.appendChild(notificationMessage);
+
+ obj.show = function() {
+ document.body.appendChild(notification);
+ if (jSuites.getWindowWidth() > 800) {
+ jSuites.animation.fadeIn(notification);
+ } else {
+ jSuites.animation.slideTop(notification, 1);
+ }
+ }
+
+ obj.hide = function() {
+ if (jSuites.getWindowWidth() > 800) {
+ jSuites.animation.fadeOut(notification, function() {
+ if (notification.parentNode) {
+ notification.parentNode.removeChild(notification);
+ if (notificationTimeout) {
+ clearTimeout(notificationTimeout);
+ }
+ }
+ });
+ } else {
+ jSuites.animation.slideTop(notification, 0, function() {
+ if (notification.parentNode) {
+ notification.parentNode.removeChild(notification);
+ if (notificationTimeout) {
+ clearTimeout(notificationTimeout);
+ }
+ }
+ });
+ }
+ };
+
+ obj.show();
+
+ if (obj.options.autoHide == true) {
+ var notificationTimeout = setTimeout(function() {
+ obj.hide();
+ }, obj.options.timeout);
+ }
+
+ if (jSuites.getWindowWidth() < 800) {
+ notification.addEventListener("swipeup", function(e) {
+ obj.hide();
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ }
+
+ return obj;
+});
+
+jSuites.notification.isVisible = function() {
+ var j = document.querySelector('.jnotification');
+ return j && j.parentNode ? true : false;
+}
+
+jSuites.picker = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ value: null,
+ data: null,
+ render: null,
+ onchange: null,
+ width: null,
+ header: true,
+ right: false,
+ content: false,
+ };
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Legacy purpose only
+ if (options.options) {
+ obj.options.data = options.options;
+ }
+
+ // Default value
+ if (obj.options.value === null) {
+ obj.options.value = Object.keys(obj.options.data)[0];
+ }
+
+ var dropdownHeader = null;
+ var dropdownContent = null;
+
+ // Class
+ el.classList.add('jpicker');
+ el.setAttribute('tabindex', '900');
+
+ /**
+ * Create floating picker
+ */
+ obj.init = function() {
+ // Dropdown Header
+ dropdownHeader = document.createElement('div');
+ dropdownHeader.classList.add('jpicker-header');
+
+ if (obj.options.header === false) {
+ dropdownHeader.style.display = 'none';
+ }
+
+ // Width
+ if (obj.options.width) {
+ dropdownHeader.style.width = parseInt(obj.options.width) + 'px';
+ }
+
+ // Start value
+ dropdownHeader.innerHTML = obj.options.value && obj.options.data[obj.options.value] ? obj.options.data[obj.options.value] : '<div><br/></div>';
+
+ // Dropdown content
+ dropdownContent = document.createElement('div');
+ dropdownContent.classList.add('jpicker-content');
+ el.appendChild(dropdownHeader);
+ el.appendChild(dropdownContent);
+
+ // Create items
+ var keys = Object.keys(obj.options.data);
+
+ // Go though all options
+ for (var i = 0; i < keys.length; i++) {
+ // Item
+ var dropdownItem = document.createElement('div');
+ dropdownItem.k = keys[i];
+ dropdownItem.v = obj.options.data[keys[i]];
+ // Label
+ dropdownItem.innerHTML = obj.getLabel(keys[i]);
+ // Onchange
+ dropdownItem.onclick = function() {
+ // Update label
+ obj.setValue(this.k);
+
+ // Call method
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, obj, this.v, this.k);
+ }
+ }
+
+ // Append
+ dropdownContent.appendChild(dropdownItem);
+ }
+
+ // Initial value
+ obj.setValue(obj.options.value);
+ }
+
+ obj.setValue = function(v) {
+ if (obj.options.content) {
+ var label = '<i class="material-icons">' + obj.options.content + '</i>';
+ } else {
+ var label = obj.getLabel(v);
+ }
+ dropdownHeader.innerHTML = label;
+ }
+
+ obj.getLabel = function(v) {
+ var label = obj.options.data[v];
+ if (typeof(obj.options.render) == 'function') {
+ label = obj.options.render(label);
+ }
+ return label;
+ }
+
+ obj.open = function() {
+ // Open picker
+ el.classList.add('jpicker-focus');
+ el.focus();
+
+ var rectHeader = dropdownHeader.getBoundingClientRect();
+ var rectContent = dropdownContent.getBoundingClientRect();
+
+ if (window.innerHeight < rectHeader.bottom + rectContent.height) {
+ dropdownContent.style.marginTop = -1 * (rectContent.height + 4) + 'px';
+ } else {
+ dropdownContent.style.marginTop = rectHeader.height + 2 + 'px';
+ }
+
+ if (obj.options.right === true) {
+ dropdownContent.style.marginLeft = -1 * rectContent.width + 24 + 'px';
+ }
+ }
+
+ el.onclick = function() {
+ if (! el.classList.contains('jpicker-focus')) {
+ obj.open();
+ } else {
+ el.classList.remove('jpicker-focus')
+ }
+ }
+
+ el.onblur = function() {
+ setTimeout(function() {
+ el.classList.remove('jpicker-focus');
+ }, 250);
+ }
+
+ obj.init();
+
+ el.picker = obj;
+
+ return obj;
+});
+
+jSuites.rating = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ number: 5,
+ value: 0,
+ tooltip: [ 'Very bad', 'Bad', 'Average', 'Good', 'Very good' ],
+ onchange: null,
+ };
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Class
+ el.classList.add('jrating');
+
+ // Add elements
+ for (var i = 0; i < obj.options.number; i++) {
+ var div = document.createElement('div');
+ div.setAttribute('data-index', (i + 1))
+ div.setAttribute('title', obj.options.tooltip[i])
+ el.appendChild(div);
+ }
+
+ // Set value
+ obj.setValue = function(index) {
+ for (var i = 0; i < obj.options.number; i++) {
+ if (i < index) {
+ el.children[i].classList.add('jrating-selected');
+ } else {
+ el.children[i].classList.remove('jrating-over');
+ el.children[i].classList.remove('jrating-selected');
+ }
+ }
+
+ obj.options.value = index;
+
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, index);
+ }
+ }
+
+ obj.getValue = function() {
+ return obj.options.value;
+ }
+
+ if (obj.options.value) {
+ for (var i = 0; i < obj.options.number; i++) {
+ if (i < obj.options.value) {
+ el.children[i].classList.add('jrating-selected');
+ }
+ }
+ }
+
+ // Events
+ el.addEventListener("click", function(e) {
+ var index = e.target.getAttribute('data-index');
+ if (index != undefined) {
+ if (index == obj.options.value) {
+ obj.setValue(0);
+ } else {
+ obj.setValue(index);
+ }
+ }
+ });
+
+ el.addEventListener("mouseover", function(e) {
+ var index = e.target.getAttribute('data-index');
+ for (var i = 0; i < obj.options.number; i++) {
+ if (i < index) {
+ el.children[i].classList.add('jrating-over');
+ } else {
+ el.children[i].classList.remove('jrating-over');
+ }
+ }
+ });
+
+ el.addEventListener("mouseout", function(e) {
+ for (var i = 0; i < obj.options.number; i++) {
+ el.children[i].classList.remove('jrating-over');
+ }
+ });
+
+ el.rating = obj;
+
+ return obj;
+});
+
+
+/**
+ * (c) jTools v1.0.1 - Element sorting
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Element drag and drop sorting
+ */
+
+jSuites.sorting = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ var defaults = {
+ pointer: null,
+ direction: null,
+ ondragstart: null,
+ ondragend: null,
+ ondrop: null,
+ }
+
+ var dragElement = null;
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ el.classList.add('jsorting');
+
+ el.addEventListener('dragstart', function(e) {
+ var position = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
+ dragElement = {
+ element: e.target,
+ o: position,
+ d: position
+ }
+ e.target.style.opacity = '0.25';
+
+ if (typeof(obj.options.ondragstart) == 'function') {
+ obj.options.ondragstart(el, e.target, e);
+ }
+ });
+
+ el.addEventListener('dragover', function(e) {
+ e.preventDefault();
+
+ if (getElement(e.target) && dragElement) {
+ if (e.target.getAttribute('draggable') == 'true' && dragElement.element != e.target) {
+ if (! obj.options.direction) {
+ var condition = e.target.clientHeight / 2 > e.offsetY;
+ } else {
+ var condition = e.target.clientWidth / 2 > e.offsetX;
+ }
+
+ if (condition) {
+ e.target.parentNode.insertBefore(dragElement.element, e.target);
+ } else {
+ e.target.parentNode.insertBefore(dragElement.element, e.target.nextSibling);
+ }
+
+ dragElement.d = Array.prototype.indexOf.call(e.target.parentNode.children, dragElement.element);
+ }
+ }
+ });
+
+ el.addEventListener('dragleave', function(e) {
+ e.preventDefault();
+ });
+
+ el.addEventListener('dragend', function(e) {
+ e.preventDefault();
+
+ if (dragElement) {
+ if (typeof(obj.options.ondragend) == 'function') {
+ obj.options.ondragend(el, dragElement.element, e);
+ }
+
+ // Cancelled put element to the original position
+ if (dragElement.o < dragElement.d) {
+ e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o]);
+ } else {
+ e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o].nextSibling);
+ }
+
+ dragElement.element.style.opacity = '';
+ dragElement = null;
+ }
+ });
+
+ el.addEventListener('drop', function(e) {
+ e.preventDefault();
+
+ if (dragElement && (dragElement.o != dragElement.d)) {
+ if (typeof(obj.options.ondrop) == 'function') {
+ obj.options.ondrop(el, dragElement.o, dragElement.d, dragElement.element, e.target, e);
+ }
+ }
+
+ dragElement.element.style.opacity = '';
+ dragElement = null;
+ });
+
+ var getElement = function(element) {
+ var sorting = false;
+
+ function path (element) {
+ if (element.className) {
+ if (element.classList.contains('jsorting')) {
+ sorting = true;
+ }
+ }
+
+ if (! sorting) {
+ path(element.parentNode);
+ }
+ }
+
+ path(element);
+
+ return sorting;
+ }
+
+ for (var i = 0; i < el.children.length; i++) {
+ if (! el.children[i].hasAttribute('draggable')) {
+ el.children[i].setAttribute('draggable', 'true');
+ }
+ }
+
+ return el;
+});
+
+jSuites.tabs = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ data: [],
+ position: null,
+ allowCreate: false,
+ allowChangePosition: false,
+ onclick: null,
+ onload: null,
+ onchange: null,
+ oncreate: null,
+ ondelete: null,
+ onbeforecreate: null,
+ onchangeposition: null,
+ animation: false,
+ hideHeaders: false,
+ padding: null,
+ }
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Class
+ el.classList.add('jtabs');
+
+ var prev = null;
+ var next = null;
+ var border = null;
+
+ // Helpers
+ var setBorder = function(index) {
+ var rect = obj.headers.children[index].getBoundingClientRect();
+ border.style.width = rect.width + 'px';
+ border.style.left = (obj.headers.children[index].offsetLeft) + 'px';
+ border.style.bottom = '0px';
+ }
+
+ var updateControls = function(x) {
+ if (typeof(obj.headers.scrollTo) == 'function') {
+ obj.headers.scrollTo({
+ left: x,
+ behavior: 'smooth',
+ });
+ } else {
+ obj.headers.scrollLeft = x;
+ }
+
+ if (x <= 1) {
+ prev.classList.add('disabled');
+ } else {
+ prev.classList.remove('disabled');
+ }
+
+ if (x >= obj.headers.scrollWidth - obj.headers.offsetWidth) {
+ next.classList.add('disabled');
+ } else {
+ next.classList.remove('disabled');
+ }
+
+ if (obj.headers.scrollWidth <= obj.headers.offsetWidth) {
+ prev.style.display = 'none';
+ next.style.display = 'none';
+ } else {
+ prev.style.display = '';
+ next.style.display = '';
+ }
+ }
+
+ // Set value
+ obj.open = function(index) {
+ var previous = null;
+ for (var i = 0; i < obj.headers.children.length; i++) {
+ if (obj.headers.children[i].classList.contains('jtabs-selected')) {
+ // Current one
+ previous = i;
+ // Remote selected
+ obj.headers.children[i].classList.remove('jtabs-selected');
+ if (obj.content.children[i]) {
+ obj.content.children[i].classList.remove('jtabs-selected');
+ }
+ }
+ }
+
+ obj.headers.children[index].classList.add('jtabs-selected');
+ if (obj.content.children[index]) {
+ obj.content.children[index].classList.add('jtabs-selected');
+ }
+
+ if (previous != index && typeof(obj.options.onchange) == 'function') {
+ if (obj.content.children[index]) {
+ obj.options.onchange(el, obj, index, obj.headers.children[index], obj.content.children[index]);
+ }
+ }
+
+ // Hide
+ if (obj.options.hideHeaders == true && (obj.headers.children.length < 3 && obj.options.allowCreate == false)) {
+ obj.headers.parentNode.style.display = 'none';
+ } else {
+ obj.headers.parentNode.style.display = '';
+ // Set border
+ if (obj.options.animation == true) {
+ setBorder(index);
+ }
+
+ var x1 = obj.headers.children[index].offsetLeft;
+ var x2 = x1 + obj.headers.children[index].offsetWidth;
+ var r1 = obj.headers.scrollLeft;
+ var r2 = r1 + obj.headers.offsetWidth;
+
+ if (! (r1 <= x1 && r2 >= x2)) {
+ // Out of the viewport
+ updateControls(x1 - 1);
+ }
+ }
+ }
+
+ obj.selectIndex = function(a) {
+ var index = Array.prototype.indexOf.call(obj.headers.children, a);
+ if (index >= 0) {
+ obj.open(index);
+ }
+
+ return index;
+ }
+
+ obj.rename = function(i, title) {
+ if (! title) {
+ title = prompt('New title', obj.headers.children[i].innerText);
+ }
+ obj.headers.children[i].innerText = title;
+ obj.open(i);
+ }
+
+ obj.create = function(title, url) {
+ if (typeof(obj.options.onbeforecreate) == 'function') {
+ var ret = obj.options.onbeforecreate(el);
+ if (ret === false) {
+ return false;
+ } else {
+ title = ret;
+ }
+ }
+
+ var div = obj.appendElement(title);
+
+ if (typeof(obj.options.oncreate) == 'function') {
+ obj.options.oncreate(el, div)
+ }
+
+ return div;
+ }
+
+ obj.remote = function(index) {
+ return obj.deleteElement(index);
+ }
+
+ obj.nextNumber = function() {
+ var num = 0;
+ for (var i = 0; i < obj.headers.children.length; i++) {
+ var tmp = obj.headers.children[i].innerText.match(/[0-9].*/);
+ if (tmp > num) {
+ num = parseInt(tmp);
+ }
+ }
+ if (! num) {
+ num = 1;
+ } else {
+ num++;
+ }
+
+ return num;
+ }
+
+ obj.deleteElement = function(index) {
+ if (! obj.headers.children[index]) {
+ return false;
+ } else {
+ obj.headers.removeChild(obj.headers.children[index]);
+ obj.content.removeChild(obj.content.children[index]);
+ }
+
+ obj.open(0);
+
+ if (typeof(obj.options.ondelete) == 'function') {
+ obj.options.ondelete(el, index)
+ }
+ }
+
+ obj.appendElement = function(title) {
+ if (! title) {
+ var title = prompt('Title?', '');
+ }
+
+ if (title) {
+ // Add content
+ var div = document.createElement('div');
+ obj.content.appendChild(div);
+
+ // Add headers
+ var h = document.createElement('div');
+ h.innerHTML = title;
+ h.content = div;
+ obj.headers.insertBefore(h, obj.headers.lastChild);
+
+ // Sortable
+ if (obj.options.allowChangePosition) {
+ h.setAttribute('draggable', 'true');
+ }
+ // Open new tab
+ obj.selectIndex(h);
+
+ // Return element
+ return div;
+ }
+ }
+
+ obj.init = function() {
+ el.innerHTML = '';
+
+ // Make sure the component is blank
+ obj.headers = document.createElement('div');
+ obj.content = document.createElement('div');
+ obj.headers.classList.add('jtabs-headers');
+ obj.content.classList.add('jtabs-content');
+
+ // Padding
+ if (obj.options.padding) {
+ obj.content.style.padding = parseInt(obj.options.padding) + 'px';
+ }
+
+ // Header
+ var header = document.createElement('div');
+ header.className = 'jtabs-headers-container';
+ header.appendChild(obj.headers);
+
+ // Controls
+ var controls = document.createElement('div');
+ controls.className = 'jtabs-controls';
+ controls.setAttribute('draggable', 'false');
+ header.appendChild(controls);
+
+ // Append DOM elements
+ el.appendChild(header);
+ el.appendChild(obj.content);
+
+ // New button
+ if (obj.options.allowCreate == true) {
+ var add = document.createElement('div');
+ add.className = 'jtabs-add';
+ add.onclick = function() {
+ obj.create();
+ }
+ controls.appendChild(add);
+ }
+
+ prev = document.createElement('div');
+ prev.className = 'jtabs-prev';
+ prev.onclick = function() {
+ updateControls(obj.headers.scrollLeft - obj.headers.offsetWidth);
+ }
+ controls.appendChild(prev);
+
+ next = document.createElement('div');
+ next.className = 'jtabs-next';
+ next.onclick = function() {
+ updateControls(obj.headers.scrollLeft + obj.headers.offsetWidth);
+ }
+ controls.appendChild(next);
+
+ // Data
+ for (var i = 0; i < obj.options.data.length; i++) {
+ var headerItem = document.createElement('div');
+ var contentItem = document.createElement('div');
+ headerItem.innerText = obj.options.data[i].title;
+ contentItem.innerHTML = obj.options.data[i].content;
+ obj.headers.appendChild(headerItem);
+ obj.content.appendChild(contentItem);
+ }
+
+ // Animation
+ border = document.createElement('div');
+ border.className = 'jtabs-border';
+ obj.headers.appendChild(border);
+
+ if (obj.options.animation) {
+ el.classList.add('jtabs-animation');
+ }
+
+ // Events
+ obj.headers.addEventListener("click", function(e) {
+ var index = obj.selectIndex(e.target);
+
+ if (typeof(obj.options.onclick) == 'function') {
+ obj.options.onclick(el, obj, index, obj.headers.children[index], obj.content.children[index]);
+ }
+ });
+
+ obj.headers.addEventListener("contextmenu", function(e) {
+ obj.selectIndex(e.target);
+ });
+
+ if (obj.headers.children.length) {
+ // Open first tab
+ obj.open(0);
+ }
+
+ // Update controls
+ updateControls(0);
+
+ if (obj.options.allowChangePosition == true) {
+ jSuites.sorting(obj.headers, {
+ direction: 1,
+ ondrop: function(a,b,c,d,e,f) {
+ // Ondrop update position of content
+ if (b > c) {
+ obj.content.insertBefore(obj.content.children[b], obj.content.children[c]);
+ } else {
+ obj.content.insertBefore(obj.content.children[b], obj.content.children[c].nextSibling);
+ }
+ // Open destination tab
+ obj.open(c);
+ // Call event
+ if (typeof(obj.options.onchangeposition) == 'function') {
+ obj.options.onchangeposition(a,b,c,d,e,f);
+ }
+ },
+ });
+ }
+
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj);
+ }
+ }
+
+ // Loading existing nodes as the data
+ if (el.children[0] && el.children[1]) {
+ // Create from existing elements
+ for (var i = 0; i < el.children[0].children.length; i++) {
+ if (el.children[1].children[i] && el.children[0].children[i].innerHTML) {
+ var title = el.children[0].children[i].innerText;
+ var content = el.children[1].children[i].innerHTML;
+ } else {
+ var title = 'Tab ' + (i + 1);
+ var content = el.children[0].children[i].innerHTML;
+ }
+
+ obj.options.data.push({ title: title, content: content });
+ }
+ }
+
+ // Remote controller flag
+ var loadingRemoteData = false;
+
+ // Create from data
+ if (obj.options.data) {
+ // Append children
+ for (var i = 0; i < obj.options.data.length; i++) {
+ if (obj.options.data[i].url) {
+ jSuites.ajax({
+ url: obj.options.data[i].url,
+ type: 'GET',
+ dataType: 'text/html',
+ index: i,
+ success: function(result) {
+ obj.options.data[this.index].content = result;
+ },
+ complete: function() {
+ obj.init();
+ }
+ });
+
+ // Flag loading
+ loadingRemoteData = true;
+ }
+ }
+ }
+
+ if (! loadingRemoteData) {
+ obj.init();
+ }
+
+ el.tabs = obj;
+
+ return obj;
+});
+
+jSuites.toolbar = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ app: null,
+ container: false,
+ badge: false,
+ title: false,
+ items: [],
+ }
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ if (! el && options.app && options.app.el) {
+ el = document.createElement('div');
+ options.app.el.appendChild(el);
+ }
+
+ obj.selectItem = function(element) {
+ var elements = toolbarContent.children;
+ for (var i = 0; i < elements.length; i++) {
+ if (element != elements[i]) {
+ elements[i].classList.remove('jtoolbar-selected');
+ }
+ }
+ element.classList.add('jtoolbar-selected');
+ }
+
+ obj.hide = function() {
+ jSuites.animation.slideBottom(el, 0, function() {
+ el.style.display = 'none';
+ });
+ }
+
+ obj.show = function() {
+ el.style.display = '';
+ jSuites.animation.slideBottom(el, 1);
+ }
+
+ obj.get = function() {
+ return el;
+ }
+
+ obj.setBadge = function(index, value) {
+ toolbarContent.children[index].children[1].firstChild.innerHTML = value;
+ }
+
+ obj.destroy = function() {
+ toolbar.remove();
+ el.innerHTML = '';
+ }
+
+ var toggleState = function() {
+ if (this.classList.contains('jtoolbar-active')) {
+ this.classList.remove('jtoolbar-active');
+ } else {
+ this.classList.add('jtoolbar-active');
+ }
+ }
+
+ obj.create = function(items) {
+ // Reset anything in the toolbar
+ toolbarContent.innerHTML = '';
+ // Create elements in the toolbar
+ for (var i = 0; i < items.length; i++) {
+ var toolbarItem = document.createElement('div');
+ toolbarItem.classList.add('jtoolbar-item');
+
+ if (items[i].width) {
+ toolbarItem.style.width = parseInt(items[i].width) + 'px';
+ }
+
+ if (items[i].k) {
+ toolbarItem.k = items[i].k;
+ }
+
+ if (items[i].tooltip) {
+ toolbarItem.setAttribute('title', items[i].tooltip);
+ }
+
+ // Id
+ if (items[i].id) {
+ toolbarItem.setAttribute('id', items[i].id);
+ }
+
+ // Selected
+ if (items[i].state) {
+ toolbarItem.toggleState = toggleState;
+ }
+
+ if (items[i].active) {
+ toolbarItem.classList.add('jtoolbar-active');
+ }
+
+ if (items[i].type == 'select' || items[i].type == 'dropdown') {
+ if (typeof(items[i].onchange) == 'function') {
+ // Event for picker has different arguments
+ items[i].onchange = (function(o) {
+ return function(a,b,c,d) {
+ o(el, obj, a, c, d);
+ }
+ })(items[i].onchange);
+ }
+ jSuites.picker(toolbarItem, items[i]);
+ } else if (items[i].type == 'divisor') {
+ toolbarItem.classList.add('jtoolbar-divisor');
+ } else if (items[i].type == 'label') {
+ toolbarItem.classList.add('jtoolbar-label');
+ toolbarItem.innerHTML = items[i].content;
+ } else {
+ // Material icons
+ var toolbarIcon = document.createElement('i');
+ if (typeof(items[i].class) === 'undefined') {
+ toolbarIcon.classList.add('material-icons');
+ } else {
+ var c = items[i].class.split(' ');
+ for (var j = 0; j < c.length; j++) {
+ toolbarIcon.classList.add(c[j]);
+ }
+ }
+ toolbarIcon.innerHTML = items[i].content ? items[i].content : '';
+ toolbarItem.appendChild(toolbarIcon);
+
+ // Badge options
+ if (obj.options.badge == true) {
+ var toolbarBadge = document.createElement('div');
+ toolbarBadge.classList.add('jbadge');
+ var toolbarBadgeContent = document.createElement('div');
+ toolbarBadgeContent.innerHTML = items[i].badge ? items[i].badge : '';
+ toolbarBadge.appendChild(toolbarBadgeContent);
+ toolbarItem.appendChild(toolbarBadge);
+ }
+
+ // Title
+ if (items[i].title) {
+ if (obj.options.title == true) {
+ var toolbarTitle = document.createElement('span');
+ toolbarTitle.innerHTML = items[i].title;
+ toolbarItem.appendChild(toolbarTitle);
+ } else {
+ toolbarItem.setAttribute('title', items[i].title);
+ }
+ }
+
+ if (obj.options.app && items[i].route) {
+ // Route
+ toolbarItem.route = items[i].route;
+ // Onclick for route
+ toolbarItem.onclick = function() {
+ obj.options.app.pages(this.route);
+ }
+ // Create pages
+ obj.options.app.pages(items[i].route, {
+ toolbarItem: toolbarItem,
+ closed: true
+ });
+ }
+ }
+
+ if (items[i].onclick) {
+ toolbarItem.onclick = (function (a) {
+ return function () {
+ items[a].onclick(el, obj, this);
+ };
+ })(i);
+ }
+
+ toolbarContent.appendChild(toolbarItem);
+ }
+ }
+
+ el.classList.add('jtoolbar');
+
+ if (obj.options.container == true) {
+ el.classList.add('jtoolbar-container');
+ }
+
+ el.innerHTML = '';
+ el.onclick = function(e) {
+ var element = jSuites.findElement(e.target, 'jtoolbar-item');
+ if (element) {
+ obj.selectItem(element);
+ }
+ }
+
+ var toolbarContent = document.createElement('div');
+ el.appendChild(toolbarContent);
+
+ if (obj.options.app) {
+ el.classList.add('jtoolbar-mobile');
+ }
+
+ obj.create(obj.options.items);
+
+ el.toolbar = obj;
+
+ return obj;
+});
+
+
+
+ return jSuites;
+
+}))); \ No newline at end of file
diff --git a/web-tools/web/_static/jsuites/jsuites.css b/web-tools/web/_static/jsuites/jsuites.css
new file mode 100644
index 0000000..968ed3d
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.css
@@ -0,0 +1,2208 @@
+
+/**
+ * (c) jSuites Javascript Web Components
+ *
+ * Author: Paul Hodel <paul.hodel@gmail.com>
+ * Website: https://bossanova.uk/jsuites/
+ * Description: Create amazing web based applications.
+ *
+ * MIT License
+ *
+ */
+
+:root {
+ --button-color: #298BA8;
+ --active-color: #007aff;
+}
+
+.unselectable {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.jdragging {
+ opacity:0.2;
+ filter: alpha(opacity=20);
+}
+
+.jupload.input {
+ padding-right:18px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z'/%3E%3C/svg%3E");
+ background-position:top 50% right 5px;
+ background-repeat:no-repeat;
+ box-sizing: border-box;
+ background-size: initial;
+ height: 33px;
+ min-height: initial;
+}
+
+.jupload.input img {
+ width: initial !important;
+ max-width: 100%;
+ height: 100%;
+}
+
+.jupload {
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAACXBIWXMAAAsTAAALEwEAmpwYAAA7emlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNyAoV2luZG93cyk8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhtcDpDcmVhdGVEYXRlPjIwMTctMTItMzFUMjI6NDM6MzBaPC94bXA6Q3JlYXRlRGF0ZT4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMTgtMDEtMDFUMjA6MDM6MjNaPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0wMS0wMVQyMDowMzoyM1o8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDxwaG90b3Nob3A6Q29sb3JNb2RlPjM8L3Bob3Rvc2hvcDpDb2xvck1vZGU+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6ZDE3NGVkY2UtNWZkNC0wODRkLTkzNzAtZDRhODVmMzdkNjdiPC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06RG9jdW1lbnRJRD54bXAuZGlkOjBmYzcxZDEyLTg1MGUtY2E0NS05MzE4LWRhYjI5YWZhMmQ4MjwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD54bXAuZGlkOjBmYzcxZDEyLTg1MGUtY2E0NS05MzE4LWRhYjI5YWZhMmQ4MjwveG1wTU06T3JpZ2luYWxEb2N1bWVudElEPgogICAgICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgICAgICAgPHJkZjpTZXE+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNyZWF0ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDowZmM3MWQxMi04NTBlLWNhNDUtOTMxOC1kYWIyOWFmYTJkODI8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTctMTItMzFUMjI6NDM6MzBaPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNyAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjk2MTA5Y2Y0LTEwM2ItNTc0Ny1hZWE3LWI5NDMxOWY0NWFkZjwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0wMS0wMVQyMDowMjoyMFo8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE3IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZDE3NGVkY2UtNWZkNC0wODRkLTkzNzAtZDRhODVmMzdkNjdiPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTAxLTAxVDIwOjAzOjIzWjwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjY1NTM1PC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj44MDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj44MDwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+tc8AsgAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAGjUlEQVR42uycW2xURRjHf91SoEIBUQpYI8VSVBDExniLERNUJBpQVEDFqE1AEYkX0JCC0YjgBdEYDOIFeVEEFRBilKBogg+KiQoV5Q6Khla8lrZRBLo+zLdazs7ZM2d3zsJu55/sy3dmz5797Vy+y8wWxONxnNJXzCFwAB1AB9ABdHIAHUAH0AF0Cq929fX1ufbMA4HLgSqgHOgPdJJrfwPbgb3AJuBD4KsoH6agrq4uF6CVAncC4wVYGP0ALAVeAva0NYDFwOPARKBzhvc6ArwG1AC/toU5cDSwFXjAAjyAQmACsAOozneATwLLgdMM2/8jLxN1AxYBC/J1CL8F3BjQZhOwCqgFvgd+AuJAT6ACOBMYCVwUcJ91siDlDcC3gRtSXF8IzAe+M7xfOXC3TAOFPm3WA0NzAeDp8oUGASeKrUF60R6Zn6an6CnTgI1pfnYFMAcY43N9GTDueAR4sQylK8RvS0dzgYcsPc9U4Bmfa9XA4uMF4GXypUdkeJ8Z0nNs6hbgdZ9rPcK6OLZX4XbisH5iAd68COABvAHc63NtwbHsgf2B94BKC/faAFwY8Zy8ErhWYx8EbM42wAuAj4ETAtptllh1N9AiC0t/YLCnXV9xT6JUJ6AOKPHYX5HIJ2sAK4BvgQ4+17fJ5LxKIgudzgBGySS/3sAPtKWZwCyPrQk4ydQxtwFwH9BbY4/LIvBEyF5RIF8iG+oC/K7xEUfLEI98EVnsA28/MCQkPIDmLMIDOCDOu1fXZGMVrgJu19gbZCKuJTek62mV2QD4XIoFZT+5o10a2ylRA6wCLtXYp8uikUv6Webr1uoOdIwS4HiNbS/wFLmnZuCgx9Y+hVdhBeBwjW1+BF9uFvBqFiDGDW3a0Cus+gADPLYWVB7PpiaJn5YYZjMigles6W2NskJH0gN1RZ1EJcyWJnvi0hpUbSQK9dRwaDGIqtIGeLbG9o3lnveCT2YmCogVPqvwdpOIKB2A7TU2W+XCiQEZkSggTvGxl8m0NNc2wDKNrcXCF5mASoUFaQYw2xK8Iv4vyvtpmsTxGQHsLPPQLp9frI+FYftyiPY1liAeBs5DZYNS/XgjgTXpApwq4Gaj0k86DbK4YISBmOlwjreaw+8CzvEDJa7bojAATwU+QtUQSg0Wlr4WFwxT2Z4Ta1GZ9Md8rlcDY00ADpFfZViID7/D8oJxrCACPCIjQ6elqOK8ryM9GPg64AM+B1YAW1BJ0r9M/aaQC0YYiAWWne0FQFf0dZnngdsgOaHaXVySLj43XSY3zCRVNclSz9NpTgQRywfAVRr7WcDWmKaxDl4TKuU+LkN4kyOEF1XEMk5GmFf3eOfAKcD5moY/ypy4OsMHeTjDBSPMcF5o8X4NPs70eKAoMYSLJIDuoOl5AwRiJroJWIIq1BwM8DcLDFyPpoAESTEqN/m0aVYlQF1RtRPviB2ZWEQeRJ//Gm0BHqhttieTutJVgkrGBu0FbEbtvmoMgNjLErxEL3yH5L01oxIA79O8aTVqj7ENmWSpGw1DwhZUJTBIf1ieGlZoAFbGxG3pESLIjkolBsMXaVNC9qWrnZTFZJh69SV283v5oHrNlNA9JvGfV0scL+3cm1Q7iaFPKNY6XimTD0fFwuWaRrscqyR11Hgqh2IkZ5gPy7LtdLRKNX7gnzHgkMdYGDIx0FZUrrHVxVBHBLzDup/jlaSrNbbdMWCn5sIAxyspsrlZY18TQ3/mYoxjdpQmkFx8OgKsjAHvat4wlFZZVyce1diWA80x4DOf7Ma8LD+kaYhmGvLZ0ovoa0LP0mpZ1qXXq4Fzs/igiSRBY8BrH3bq0Ca6HlWt82od6iTBfyn9Lj6+Xx2q2nYwSz3Q9FhrE/ZSVX66BPjU51q/RLCR6IEH0KfCe8sQL85SmNRo+Ioa3tgU8Ga2jtS8RaUdPj7gTtQRqS/yfLHogErf+6Xykk52ekOTESm67AbUrvuyPARXAtyPSvz6wduK5myx7pzIcPy3N4D6Z4w3pc0O1IbybAwrWyqSubZUOsYw4DrU4Ro/bUEd3m4wAZjoie8bPtARVNkvVwAWypxu6gqtRW0u0i6kqU4qDUEVUirasANdQ8BhoVSbizai/uRmbhsEtxp1lCPwpJXpWbmBqD++uTWPQ7xm1NaVJeIomzmvIQ8bdpO0zpWozea9Aibf41WHgd9QhaJtqAPia4FfQnv/7l98M5P79zYH0AF0AB1AJwfQAXQAHUCnNPTvAKemiFU6nb96AAAAAElFTkSuQmCC);
+ background-repeat: no-repeat;
+ background-size: 100px;
+ background-position: center;
+ background-color: rgba(230, 230, 230, 0.1);
+ border: 1px dotted #eee;
+ cursor: pointer;
+ box-sizing: border-box;
+ width:100%;
+ min-height:180px;
+}
+
+.jremove {
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+
+
+/** Animations **/
+.fade-in {
+ animation: fade-in 2s forwards;
+}
+
+.fade-out {
+ animation: fade-out 1s forwards;
+}
+
+.slide-left-in {
+ animation: slide-left-in 0.4s forwards;
+}
+
+.slide-left-out {
+ animation: slide-left-out 0.4s forwards;
+}
+
+.slide-right-in {
+ animation: slide-right-in 0.4s forwards;
+}
+
+.slide-right-out {
+ animation: slide-right-out 0.4s forwards;
+}
+
+.slide-top-in {
+ animation: slide-top-in 0.4s forwards;
+}
+
+.slide-top-out {
+ animation: slide-top-out 0.2s forwards;
+}
+
+.slide-bottom-in {
+ animation: slide-bottom-in 0.4s forwards;
+}
+
+.slide-bottom-out {
+ animation: slide-bottom-out 0.1s forwards;
+}
+
+/** Fadein and Fadeout **/
+@keyframes fade-in {
+ 0% { opacity: 0; }
+ 100% { opacity: 100; }
+}
+
+@-webkit-keyframes fade-in {
+ 0% { opacity: 0; }
+ 100% { opacity: 100; }
+}
+
+@keyframes fade-out {
+ 0% { opacity: 100; }
+ 100% { opacity: 0; }
+}
+
+@-webkit-keyframes fade-out {
+ 0% { opacity: 100; }
+ 100% { opacity: 0; }
+}
+
+/** Keyframes Left to Right **/
+@keyframes slide-left-in {
+ 0% { transform: translateX(-100%); }
+ 100% { transform: translateX(0%); }
+}
+
+@-webkit-keyframes slide-left-in {
+ 0% { transform: translateX(-100%); }
+ 100% { -webkit-transform: translateX(0%); }
+}
+
+@keyframes slide-left-out {
+ 0% { transform: translateX(0%); }
+ 100% { transform: translateX(-100%); }
+}
+
+@-webkit-keyframes slide-left-out {
+ 0% { -webkit-transform: translateX(0%); }
+ 100% { -webkit-transform: translateX(-100%); }
+}
+
+/** Keyframes Right to Left **/
+@keyframes slide-right-in {
+ 0% { transform: translateX(100%); }
+ 100% { transform: translateX(0%); }
+}
+
+@-webkit-keyframes slide-right-in
+{
+ 0% { transform: translateX(100%); }
+ 100% { -webkit-transform: translateX(0%); }
+}
+
+@keyframes slide-right-out {
+ 0% { transform: translateX(0%); }
+ 100% { transform: translateX(100%); }
+}
+
+@-webkit-keyframes slide-right-out {
+ 0% { -webkit-transform: translateX(0%); }
+ 100% { -webkit-transform: translateX(100%); }
+}
+
+/** Keyframes Top to Bottom **/
+@keyframes slide-top-in {
+ 0% { transform: translateY(-100%); }
+ 100% { transform: translateY(0%); }
+}
+
+@-webkit-keyframes slide-top-in {
+ 0% { transform: translateY(-100%); }
+ 100% { -webkit-transform: translateY(0%); }
+}
+
+@keyframes slide-top-out {
+ 0% { transform: translateY(0%); }
+ 100% { transform: translateY(-100%); }
+}
+
+@-webkit-keyframes slide-top-out {
+ 0% { -webkit-transform: translateY(0%); }
+ 100% { -webkit-transform: translateY(-100%); }
+}
+
+/** Keyframes Bottom to Top **/
+@keyframes slide-bottom-in {
+ 0% { transform: translateY(100%); }
+ 100% { transform: translateY(0%); }
+}
+
+@-webkit-keyframes slide-bottom-in {
+ 0% { transform: translateY(100%); }
+ 100% { -webkit-transform: translateY(0%); }
+}
+
+@keyframes slide-bottom-out {
+ 0% { transform: translateY(0%); }
+ 100% { transform: translateY(100%); }
+}
+
+@-webkit-keyframes slide-bottom-out {
+ 0% { -webkit-transform: translateY(0%); }
+ 100% { -webkit-transform: translateY(100%); }
+}
+
+@-webkit-keyframes spin {
+ from {
+ -webkit-transform:rotate(0deg);
+ }
+ to {
+ -webkit-transform:rotate(360deg);
+ }
+}
+
+@keyframes spin {
+ from {
+ transform:rotate(0deg);
+ }
+ to {
+ transform:rotate(360deg);
+ }
+}
+
+/**
+ * Date & Datetime picker v1.0.1
+ * Author: paul.hodel@gmail.com
+ * https://github.com/paulhodel/jtools
+ */
+
+.jcalendar {
+ position:absolute;
+ z-index:9000;
+ display:none;
+ box-sizing:border-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ -webkit-tap-highlight-color: transparent;
+ min-width:280px;
+}
+
+.jcalendar.jcalendar-focus {
+ display:block;
+}
+
+.jcalendar .jcalendar-backdrop {
+ position:fixed;
+ top:0px;
+ left:0px;
+ z-index:9000;
+ min-width:100%;
+ min-height:100%;
+ background-color:rgba(0,0,0,0.5);
+ border:0px;
+ padding:0px;
+ display:none;
+}
+
+.jcalendar .jcalendar-container {
+ position:relative;
+ box-sizing:border-box;
+}
+
+.jcalendar .jcalendar-content {
+ position:absolute;
+ z-index:9001;
+ -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ background-color:#fff;
+}
+
+.jcalendar-header {
+ text-align:center;
+}
+
+.jcalendar-header span {
+ margin-right:4px;
+ font-size:1.1em;
+ font-weight:bold;
+}
+
+.jcalendar-prev {
+ cursor:pointer;
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z' fill='%23000' /%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3C/svg%3E");
+ background-position:center;
+ background-repeat:no-repeat;
+}
+
+.jcalendar-next {
+ cursor:pointer;
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z' fill='%23000' /%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3C/svg%3E");
+ background-position:center;
+ background-repeat:no-repeat;
+}
+
+.jcalendar-weekday {
+ font-weight: 600;
+ background-color: #fcfcfc;
+ padding: 14px;
+}
+
+.jcalendar-table > table {
+ width:100%;
+ background-color:#fff;
+}
+
+.jcalendar-table > table > thead {
+ cursor:pointer;
+}
+
+.jcalendar-table thead td {
+ padding:10px;
+ height:40px;
+}
+
+.jcalendar-table > table > tbody td {
+ box-sizing:border-box;
+ cursor:pointer;
+ padding:9px;
+ font-size:0.9em;
+}
+
+
+.jcalendar-table tfoot td {
+ padding:10px;
+}
+
+.jcalendar-months td, .jcalendar-years td {
+ height:24px;
+}
+
+.jcalendar-input {
+ padding-right:18px;
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='gray'%3E%3Cpath d='M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V8h16v13z'/%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3C/svg%3E");
+ background-position:top 50% right 5px;
+ background-repeat:no-repeat;
+ box-sizing: border-box;
+}
+
+.jcalendar-done {
+ -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
+ background-color:#fff;
+}
+
+.jcalendar-update {
+ border:1px solid #ccc;
+ background-color:#fff;
+ border-radius:4px;
+ padding:5px;
+ width:100%;
+}
+
+.jcalendar-container select {
+ width:55px;
+ display:inline-block;
+ border:0px;
+ padding:4px;
+ text-align:center;
+ font-size:1.1em;
+ user-select:none;
+ margin-right:10px;
+}
+
+.jcalendar-container select:first-child {
+ margin-right:2px;
+}
+
+.jcalendar-selected {
+ background-color:#eee;
+}
+
+.jcalendar-reset, .jcalendar-confirm {
+ text-transform:uppercase;
+ cursor:pointer;
+ color: var(--active-color);
+}
+
+.jcalendar-controls {
+ padding:15px;
+
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align:middle;
+
+ display: -webkit-box;
+ display: -moz-box;
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+
+ -webkit-flex-flow: row wrap;
+ justify-content: space-between;
+ align-items:center;
+}
+
+.jcalendar-controls div {
+ font-weight:bold;
+}
+
+.jcalendar-fullsize {
+ position:fixed;
+ width:100%;
+ top:0px;
+ left:0px;
+}
+
+.jcalendar-fullsize .jcalendar-content
+{
+ position:fixed;
+ width:100%;
+ left:0px;
+ bottom:0px;
+}
+
+.jcalendar-focus.jcalendar-fullsize .jcalendar-backdrop {
+ display:block;
+}
+
+.jcalendar-sunday {
+ color: red;
+}
+.jcalendar-disabled {
+ color: #ccc;
+}
+
+.jcalendar-time {
+ display:flex;
+}
+
+
+.jcolor {
+ position: absolute;
+ display: none;
+ outline: none;
+}
+
+.jcolor-input {
+ padding-right:18px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z'/%3E%3C/svg%3E");
+ background-position:top 50% right 5px;
+ background-repeat:no-repeat;
+ box-sizing: border-box;
+}
+
+.jcolor-content {
+ position: absolute;
+ left: 0px;
+ z-index: 9000;
+ user-select: none;
+ -webkit-font-smoothing: antialiased;
+ font-size: .875rem;
+ letter-spacing: .2px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
+ box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
+ background-color:#fff;
+ box-sizing: border-box;
+}
+
+.jcolor-controls {
+ display: flex;
+ padding: 10px;
+ padding-bottom: 0px;
+}
+
+.jcolor-controls div {
+ flex: 1;
+ font-size: 1em;
+ color: var(--active-color);
+ text-transform: uppercase;
+ font-weight: bold;
+ box-sizing: border-box;
+}
+
+.jcolor-content table {
+ border-collapse: initial;
+ padding: 7px !important;
+ box-sizing: border-box;
+}
+
+.jcolor-focus {
+ display:block;
+}
+
+.jcolor table {
+ width:100%;
+ height:100%;
+}
+
+.jcolor td {
+ padding: 7px;
+ border:2px solid #fff;
+}
+
+.jcolor-selected {
+ border:2px solid #000 !important;
+ background-repeat:no-repeat;
+ background-size: 16px;
+ background-position: center;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z' fill='white'/%3E%3C/svg%3E");
+}
+
+.jcolor-fullscreen {
+ position: fixed;
+ bottom: 0px;
+ width:100%;
+ max-height:250px;
+ border-radius: 0px;
+ box-sizing: border-box;
+}
+
+.jcolor-fullscreen .jcolor-controls {
+ padding: 15px;
+ -webkit-box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
+ box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
+}
+
+.jcolor-reset {
+ text-align: left;
+}
+
+.jcolor-close {
+ text-align: right;
+}
+
+.jcolor-backdrop {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ min-width: 100%;
+ min-height: 100%;
+ background-color: rgba(0,0,0,0.5);
+ border: 0px;
+ padding: 0px;
+ z-index: 8000;
+ display: none;
+
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ -khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none; /* Non-prefixed version, currently
+ supported by Chrome and Opera */
+}
+
+/**
+ * Contextmenu v1.0.1
+ * Author: paul.hodel@gmail.com
+ * https://github.com/paulhodel/jsuites
+ */
+
+.jcontextmenu {
+ position:fixed;
+ z-index:10000;
+ background:#fff;
+ color: #555;
+ font-size: 11px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ -webkit-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
+ -moz-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
+ box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
+ border: 1px solid #C6C6C6;
+ padding: 0px;
+ padding-top:4px;
+ padding-bottom:4px;
+ margin:0px;
+ outline:none;
+ display:none;
+}
+
+.jcontextmenu.jcontextmenu-focus {
+ display:inline-block;
+}
+
+.jcontextmenu > div {
+ box-sizing: border-box;
+ display: flex;
+ padding: 8px 8px 8px 32px;
+ width: 250px;
+ position: relative;
+ cursor: default;
+ font-size: 11px;
+ font-family:sans-serif;
+}
+
+.jcontextmenu > div::before {
+ content: attr(data-icon);
+ font-family: 'Material Icons';
+ font-weight: normal;
+ font-style: normal;
+ font-size: 16px;
+ line-height: 1;
+ letter-spacing: normal;
+ text-transform: none;
+ display: inline-block;
+ white-space: nowrap;
+ word-wrap: normal;
+ direction: ltr;
+ -webkit-font-feature-settings: 'liga';
+ -webkit-font-smoothing: antialiased;
+ position: absolute;
+ left: 9px;
+}
+
+.jcontextmenu > div a {
+ color: #555;
+ text-decoration: none;
+ flex: 1;
+}
+
+.jcontextmenu > div span {
+ margin-right:10px;
+}
+
+.jcontextmenu .jcontextmenu-disabled a {
+ color: #ccc;
+}
+
+.jcontextmenu > div:hover {
+ background: #ebebeb;
+}
+
+.jcontextmenu hr {
+ border: 1px solid #e9e9e9;
+ border-bottom: 0;
+ margin-top:5px;
+ margin-bottom:5px;
+}
+
+.jcontextmenu > hr:hover {
+ background: transparent;
+}
+
+.jcontextmenu .jcontextmenu {
+ top: 4px;
+ left: 99%;
+ opacity: 0;
+ position: absolute;
+}
+
+.jcontextmenu > div:hover > .jcontextmenu {
+ display: block;
+ opacity: 1;
+ -webkit-transform: translate(0, 0) scale(1);
+ transform: translate(0, 0) scale(1);
+ pointer-events: auto;
+}
+
+/**
+ * (c) 2013 jDropdown
+ * http://www.github.com/paulhodel/jdropdown
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Custom dropdowns
+ */
+
+.jdropdown {
+ cursor:pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ box-sizing: border-box;
+ background:#fff;
+ -webkit-tap-highlight-color: transparent;
+ display: inline-block;
+}
+
+.jdropdown-header::placeholder {
+ color:#000;
+}
+
+.jdropdown-backdrop {
+ position:fixed;
+ top:0px;
+ left:0px;
+ min-width:100%;
+ min-height:100%;
+ background-color:rgba(0,0,0,0.5);
+ border:0px;
+ padding:0px;
+ z-index:8000;
+ display:none;
+}
+
+.jdropdown-focus {
+ position:relative;
+}
+
+.jdropdown-focus .jdropdown-container {
+ transform: translate3d(0,0,0);
+}
+
+.jdropdown-default.jdropdown-focus .jdropdown-header {
+ outline:auto 5px -webkit-focus-ring-color;
+}
+
+.jdropdown-default.jdropdown-focus .jdropdown-header.jdropdown-add {
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='gray' width='24px' height='24px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z'/%3E%3C/svg%3E");
+}
+
+.jdropdown-container-header
+{
+ padding:0px;
+ margin:0px;
+ position:relative;
+}
+
+.jdropdown-header
+{
+ width:100%;
+ appearance: none;
+ background-repeat: no-repeat;
+ background-position:top 50% right 5px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 10l5 5 5-5H7z' fill='gray'/%3E%3C/svg%3E");
+ text-overflow: ellipsis;
+ cursor:pointer;
+ box-sizing: border-box;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ padding-right:30px !important;
+}
+
+.jdropdown-insert-button
+{
+ font-size: 1.4em;
+ text-transform: uppercase;
+ position:absolute;
+ right: 30px;
+ top: 4px;
+ display:none;
+}
+
+.jdropdown-container
+{
+ min-width: inherit;
+ transform: translate3d(-10000px,0,0);
+ position:absolute;
+ z-index:9001;
+}
+
+.jdropdown-close
+{
+ display:none;
+ font-size:1em;
+ color: var(--active-color);
+ text-transform:uppercase;
+ text-align:right;
+ padding:15px;
+ font-weight:bold;
+}
+
+.jdropdown-content
+{
+ min-width:inherit;
+ margin:0px;
+ box-sizing:border-box;
+}
+
+.jdropdown-content:empty
+{
+}
+
+.jdropdown-item
+{
+ white-space: nowrap;
+ text-align: left;
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ color: #000;
+ display: flex;
+ align-items: center;
+}
+
+.jdropdown-description
+{
+ text-overflow: ellipsis;
+ overflow: hidden;
+ line-height: 1.5em;
+}
+
+.jdropdown-image
+{
+ margin-right:10px;
+ width: 32px;
+ height: 32px;
+ border-radius:20px;
+}
+
+.jdropdown-image-small
+{
+ width:24px;
+ height:24px;
+}
+
+.jdropdown-title
+{
+ font-size: 0.7em;
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ display: block;
+}
+
+/** Default visual **/
+
+.jdropdown-default .jdropdown-header
+{
+ border:1px solid #ccc;
+ padding:5px;
+ padding-left:10px;
+ padding-right:16px;
+}
+
+.jdropdown-default .jdropdown-container
+{
+ background-color:#fff;
+}
+
+.jdropdown-default.jdropdown-focus.jdropdown-insert .jdropdown-header {
+ padding-right:50px;
+}
+
+.jdropdown-default.jdropdown-focus.jdropdown-insert .jdropdown-insert-button {
+ display:block;
+}
+
+.jdropdown-default .jdropdown-content
+{
+ min-width:inherit;
+ border:1px solid #8fb1e3;
+ margin:0px;
+ background-color:#fff;
+ box-sizing:border-box;
+ min-height:10px;
+ max-height:215px;
+ overflow-y:auto;
+}
+
+.jdropdown-default .jdropdown-item
+{
+ padding:4px;
+ padding-left:8px;
+ padding-right:40px;
+}
+
+.jdropdown-default .jdropdown-item:hover
+{
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+.jdropdown-default .jdropdown-cursor
+{
+ background-color:#eee;
+}
+
+.jdropdown-default .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiIGZpbGw9IndoaXRlIiAvPjwvc3ZnPgo=');
+ background-repeat:no-repeat;
+ background-position:top 50% right 5px;
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+.jdropdown-default .jdropdown-group
+{
+ margin-top:5px;
+}
+
+.jdropdown-default .jdropdown-group .jdropdown-item
+{
+ padding-left:16px;
+}
+
+.jdropdown-default .jdropdown-group-name
+{
+ padding-left:8px;
+ font-weight:bold;
+}
+
+.jdropdown-default .jdropdown-reset_ {
+ content:'x';
+ position:absolute;
+ top:0;
+ right:0;
+ margin:5px;
+ margin-right:10px;
+ font-size:12px;
+ width:12px;
+ cursor:pointer;
+ text-shadow: 0px 0px 5px #fff;
+ display:none;
+ line-height: 1.8em;
+}
+
+.jdropdown-default.jdropdown-focus .jdropdown-reset_ {
+ display:block;
+}
+
+/** Default render for mobile **/
+
+.jdropdown-picker.jdropdown-focus .jdropdown-backdrop {
+ display:block;
+}
+
+.jdropdown-picker .jdropdown-header {
+ outline: none;
+}
+
+.jdropdown-picker .jdropdown-container
+{
+ position:fixed;
+ bottom:0px;
+ left:0px;
+ border-bottom:1px solid #e6e6e8;
+ width:100%;
+ background-color:#fff;
+ box-sizing: border-box;
+}
+
+.jdropdown-picker .jdropdown-close
+{
+ -webkit-box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
+ -moz-box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
+ box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
+ background-color:#fff;
+ display:block;
+}
+
+.jdropdown-picker .jdropdown-content
+{
+ overflow-y:scroll;
+ height:280px;
+ background-color:#fafafa;
+ border-top:1px solid #e6e6e8;
+}
+
+.jdropdown-picker .jdropdown-group-name
+{
+ font-size: 1em;
+ text-transform: uppercase;
+ padding-top:10px;
+ padding-bottom:10px;
+ display: block;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:20px;
+ padding-right:20px;
+ text-align:center;
+ font-weight:bold;
+}
+
+.jdropdown-picker .jdropdown-item
+{
+ font-size: 1em;
+ text-transform: uppercase;
+ padding-top:10px;
+ padding-bottom:10px;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:20px;
+ padding-right:20px;
+}
+
+.jdropdown-picker .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiIGZpbGw9IndoaXRlIiAvPjwvc3ZnPgo=');
+ background-repeat:no-repeat;
+ background-position:top 50% right 15px;
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+.jdropdown-picker .jdropdown-cursor
+{
+ background-color:#1f93ff;
+ color:#fff;
+}
+
+/** Default render for mobile searchbar **/
+
+.jdropdown-searchbar.jdropdown-focus
+{
+ position:fixed;
+ top:0px;
+ left:0px;
+ width:100%;
+ height:100%;
+ background-color:#fafafa;
+ padding:0px;
+ z-index:9001;
+ overflow-y:scroll;
+}
+
+.jdropdown-searchbar.jdropdown-focus .jdropdown-container-header
+{
+ padding:10px;
+ background-color:#fff;
+ box-shadow: 0 1px 2px rgba(0,0,0,.1);
+}
+
+.jdropdown-searchbar.jdropdown-focus .jdropdown-header
+{
+ border: 0px;
+ background-repeat: no-repeat;
+ background-position-x: 0%;
+ background-position-y: 40%;
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTUuNSAxNGgtLjc5bC0uMjgtLjI3QzE1LjQxIDEyLjU5IDE2IDExLjExIDE2IDkuNSAxNiA1LjkxIDEzLjA5IDMgOS41IDNTMyA1LjkxIDMgOS41IDUuOTEgMTYgOS41IDE2YzEuNjEgMCAzLjA5LS41OSA0LjIzLTEuNTdsLjI3LjI4di43OWw1IDQuOTlMMjAuNDkgMTlsLTQuOTktNXptLTYgMEM3LjAxIDE0IDUgMTEuOTkgNSA5LjVTNy4wMSA1IDkuNSA1IDE0IDcuMDEgMTQgOS41IDExLjk5IDE0IDkuNSAxNHoiIGZpbGw9IiNlNmU2ZTgiLz48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PC9zdmc+);
+ padding-left: 30px !important;
+ padding-right: 60px !important;
+}
+
+.jdropdown-searchbar.jdropdown-focus .jdropdown-close
+{
+ display:block;
+}
+
+.jdropdown-searchbar .jdropdown-header {
+ outline: none;
+}
+
+.jdropdown-searchbar .jdropdown-container
+{
+ width:100%;
+}
+
+.jdropdown-searchbar .jdropdown-close
+{
+ position:fixed;
+ top:0px;
+ right:0px;
+}
+
+.jdropdown-searchbar .jdropdown-content
+{
+ margin-top:10px;
+}
+
+.jdropdown-searchbar .jdropdown-group
+{
+ margin-top:10px;
+ margin-bottom:15px;
+ background-color:#fff;
+}
+
+.jdropdown-searchbar .jdropdown-group-name
+{
+ border-top: 1px solid #e6e6e8;
+ border-bottom: 1px solid #e6e6e8;
+ padding:10px;
+ padding-left:12px;
+ font-weight:bold;
+}
+
+.jdropdown-searchbar .jdropdown-group-arrow
+{
+ float:right;
+ width:24px;
+ height:24px;
+ background-repeat:no-repeat;
+}
+
+.jdropdown-searchbar .jdropdown-group-arrow-down
+{
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNy40MSA4LjU5TDEyIDEzLjE3bDQuNTktNC41OEwxOCAxMGwtNiA2LTYtNiAxLjQxLTEuNDF6Ii8+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgyNHYyNEgwVjB6Ii8+PC9zdmc+);
+}
+
+.jdropdown-searchbar .jdropdown-group-arrow-up
+{
+ background-image: url(data:image/svg+xml;base64,CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTcuNDEgMTUuNDFMMTIgMTAuODNsNC41OSA0LjU4TDE4IDE0bC02LTYtNiA2eiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=);
+}
+
+.jdropdown-searchbar .jdropdown-item
+{
+ padding-top:10px;
+ padding-bottom:10px;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:15px;
+ padding-right:40px;
+ background-color:#fff;
+ font-size:0.9em;
+}
+
+.jdropdown-searchbar .jdropdown-description {
+ text-overflow: ellipsis;
+ overflow: hidden;
+ max-width: calc(100% - 20px);
+}
+
+.jdropdown-searchbar .jdropdown-content > .jdropdown-item:first-child
+{
+ border-top: 1px solid #e6e6e8;
+}
+
+.jdropdown-searchbar .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxeiIgZmlsbD0iIzAwN2FmZiIvPjwvc3ZnPg==');
+ background-repeat:no-repeat;
+ background-position:top 50% right 15px;
+}
+
+/** List render **/
+
+.jdropdown-list
+{
+}
+
+.jdropdown-list .jdropdown-container
+{
+ display:block;
+}
+
+.jdropdown-list .jdropdown-header
+{
+ display:none;
+}
+
+.jdropdown-list .jdropdown-group
+{
+ background-color:#fff;
+}
+
+.jdropdown-list .jdropdown-group-name
+{
+ border-bottom: 1px solid #e6e6e8;
+ padding-top:10px;
+ padding-bottom:10px;
+ font-weight:bold;
+}
+
+.jdropdown-list .jdropdown-item
+{
+ padding-top:10px;
+ padding-bottom:10px;
+ border-bottom: 1px solid #e6e6e8;
+ padding-left:10px;
+ padding-right:40px;
+ background-color:#fff;
+}
+
+.jdropdown-list .jdropdown-selected
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxeiIgZmlsbD0iIzAwN2FmZiIvPjwvc3ZnPg==');
+ background-repeat:no-repeat;
+ background-position:top 50% right 10px;
+}
+
+@media only screen and (max-device-width : 800px)
+{
+ .jdropdown-list
+ {
+ width:100% !important;
+ border:0px;
+ padding:0px;
+ }
+
+ .jdropdown-list .jdropdown-container
+ {
+ min-width:100%;
+ }
+}
+
+.app .jdropdown-item {
+ text-transform:uppercase;
+}
+
+.jdropdown-create-container {
+ margin: 10px;
+ border: 1px solid #ccc;
+ border-radius: 2px;
+ padding: 6px;
+}
+
+.jdropdown-color {
+ background-color: #fff;
+ border: 1px solid transparent;
+ border-radius: 12px;
+ width: 12px;
+ height: 12px;
+ margin-right: 6px;
+}
+
+/**
+ * (c) jTools Text Editor
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Inline richtext editor
+ */
+
+ .jeditor-container {
+ border:1px solid #ccc;
+}
+
+.jeditor-dragging {
+ border:1px dashed #000;
+}
+
+.jeditor-container.jeditor-padding {
+ padding:10px;
+}
+
+.jeditor {
+ outline:none;
+ word-break: break-word;
+
+}
+
+.jeditor-container.jeditor-padding .jeditor {
+ min-height:160px;
+ margin-bottom:10px;
+ padding:10px;
+}
+
+.jeditor-thumbs {
+ display:inline-block;
+ margin-right:5px;
+}
+
+.jeditor-thumbs-container {
+ margin-top:15px;
+}
+
+.jeditor-thumbs .close {
+ position:absolute;
+ height:1px;
+}
+
+.jeditor-thumbs .close i {
+ color:#fff;
+ text-shadow: 0px 0px 2px #000;
+ position:relative;
+ top:5px;
+ left:72px;
+}
+
+.jeditor-thumbs img {
+ border:1px solid #eee;
+ width:100px;
+ height:100px;
+}
+
+.jeditor-users {
+ position:absolute;
+ border:1px solid #ccc;
+ background-color:#fff;
+ padding-top:5px;
+ padding-bottom:5px;
+ max-height:220px;
+ overflow-y:scroll;
+}
+
+.jeditor-users > div
+{
+ display:flex;
+ align-items:center;
+ min-width:220px;
+ padding:10px;
+ padding-top:5px;
+ padding-bottom:5px;
+}
+
+.jeditor-users > div:hover
+{
+ background-color:#efefef;
+}
+
+.jeditor-users > div img
+{
+ width:24px;
+ height:24px;
+ border-radius:12px;
+ margin-right:5px;
+}
+
+/** Snippet **/
+
+.jsnippet {
+ margin-top:15px;
+ cursor:pointer;
+ border: 1px solid #eee;
+ position:relative;
+}
+
+.jsnippet:focus {
+ outline: none;
+}
+
+.jsnippet img {
+ width:100%;
+}
+
+.jsnippet .jsnippet-title {
+ padding:15px;
+ font-size:1.4em;
+}
+
+.jsnippet .jsnippet-description {
+ padding-left:15px;
+ padding-right:15px;
+ font-size:1em;
+}
+
+.jsnippet .jsnippet-host {
+ padding:15px;
+ text-transform:uppercase;
+ font-size:0.8em;
+ color:#777;
+ text-align:right;
+}
+
+.jsnippet .jsnippet-url {
+ display:none;
+}
+
+.jeditor .jsnippet:after {
+ content:'';
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ position:absolute;
+ top:0;
+ right:0;
+ margin:14px;
+ font-size:24px;
+ width:24px;
+ height:24px;
+ cursor:pointer;
+ text-shadow: 0px 0px 5px #fff;
+}
+
+.jsnippet * {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+
+ -webkit-user-drag: none;
+ -khtml-user-drag: none;
+ -moz-user-drag: none;
+ -o-user-drag: none;
+}
+
+.jeditor img {
+ border:2px solid transparent;
+ box-sizing: border-box;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+
+ -webkit-user-drag: none;
+ -khtml-user-drag: none;
+ -moz-user-drag: none;
+ -o-user-drag: none;
+}
+
+.jeditor img:focus {
+ border:2px solid #0096FD;
+}
+
+.jeditor .pdf {
+ background-image: url("data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 512 512' style='enable-background:new 0 0 512 512;' xml:space='preserve'%3E%3Cpath style='fill:%23C30B15;' d='M511.344,274.266C511.77,268.231,512,262.143,512,256C512,114.615,397.385,0,256,0S0,114.615,0,256 c0,117.769,79.53,216.949,187.809,246.801L511.344,274.266z'/%3E%3Cpath style='fill:%2385080E;' d='M511.344,274.266L314.991,77.913L119.096,434.087l68.714,68.714C209.522,508.787,232.385,512,256,512 C391.243,512,501.976,407.125,511.344,274.266z'/%3E%3Cpolygon style='fill:%23FFFFFF;' points='278.328,333.913 255.711,77.913 119.096,77.913 119.096,311.652 '/%3E%3Cpolygon style='fill:%23E8E6E6;' points='392.904,311.652 392.904,155.826 337.252,133.565 314.991,77.913 255.711,77.913 256.067,333.913 '/%3E%3Cpolygon style='fill:%23FFFFFF;' points='314.991,155.826 314.991,77.913 392.904,155.826 '/%3E%3Crect x='119.096' y='311.652' style='fill:%23FC0F1A;' width='273.809' height='122.435'/%3E%3Cg%3E%3Cpath style='fill:%23FFFFFF;' d='M204.871,346.387c13.547,0,21.341,6.659,21.341,18.465c0,12.412-7.795,19.601-21.341,19.601h-9.611 v14.909h-13.471v-52.975L204.871,346.387L204.871,346.387z M195.26,373.858h8.93c5.904,0,9.308-2.952,9.308-8.552 c0-5.525-3.406-8.324-9.308-8.324h-8.93V373.858z'/%3E%3Cpath style='fill:%23FFFFFF;' d='M257.928,346.387c16.649,0,28.152,10.746,28.152,26.487c0,15.666-11.655,26.488-28.683,26.488 h-22.25v-52.975H257.928z M248.619,388.615h9.611c8.249,0,14.151-6.357,14.151-15.665c0-9.384-6.205-15.817-14.757-15.817h-9.006 V388.615z'/%3E%3Cpath style='fill:%23FFFFFF;' d='M308.563,356.982v12.26h23.763v10.596h-23.763v19.525h-13.471v-52.975h39.277v10.595h-25.806 V356.982z'/%3E%3C/g%3E%3C/svg%3E%0A");
+ background-repeat: no-repeat;
+ background-size: cover;
+ width:60px;
+ height:60px;
+}
+
+
+/**
+ * (c) jLoading
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Page loading spin
+ */
+
+.jloading {
+ position:fixed;
+ z-index:10001;
+ width:100%;
+ left:0;
+ right:0;
+ top:0;
+ bottom:0;
+ background-color: rgba(0,0,0,0.7);
+}
+
+.jloading::after {
+ content:'';
+ display:block;
+ margin:0 auto;
+ margin-top:50vh;
+ width:40px;
+ height:40px;
+ border-style:solid;
+ border-color:white;
+ border-top-color:transparent;
+ border-width:4px;
+ border-radius:50%;
+ -webkit-animation: spin .8s linear infinite;
+ animation: spin .8s linear infinite;
+}
+
+.jloading.spin {
+ background-color:transparent;
+}
+
+.jloading.spin::after {
+ margin:0 auto;
+ margin-top:80px;
+ border-color:#aaa;
+ border-top-color:transparent;
+}
+
+
+.jmodal {
+ position:fixed;
+ top:50%;
+ left:50%;
+ width:60%;
+ height:60%;
+ -webkit-box-shadow: 0 2px 10px rgba(0,0,0,.2);
+ -moz-box-shadow: 0 2px 10px rgba(0,0,0,.2);
+ border:1px solid #ccc;
+ background-color:#fff;
+ transform: translate(-50%, -50%);
+ box-sizing: border-box;
+ padding-top:50px;
+ z-index:9002;
+ border-radius:5px;
+}
+
+.jmodal:before {
+ position:absolute;
+ top:0;
+ left:0;
+ width:100%;
+ content:attr(title);
+ padding:15px;
+ box-sizing: border-box;
+ background: #e3e3e3;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#e3e3e3');
+ background: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#e3e3e3));
+ background: -moz-linear-gradient(top, #ededed, #e3e3e3);
+ font-size:1.2em;
+}
+
+.jmodal_content {
+ padding:20px;
+ overflow-y:auto;
+ max-height:100%;
+ box-sizing: border-box;
+ height: -webkit-fill-available;
+}
+.jmodal.no-title {
+ padding-top:0px;
+}
+
+.jmodal.no-title:before {
+ display:none;
+}
+
+.jmodal:after {
+ content:'';
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ position:absolute;
+ top:0;
+ right:0;
+ margin:14px;
+ font-size:24px;
+ width:24px;
+ height:24px;
+ cursor:pointer;
+ text-shadow: 0px 0px 5px #fff;
+}
+
+.jmodal_fullscreen {
+ width: 100% !important;
+ height: 100% !important;
+ top: 0px;
+ left: 0px;
+ transform: none;
+ border-radius: 0px;
+}
+
+
+.jmodal_backdrop {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ min-width: 100%;
+ min-height: 100%;
+ background-color: rgba(0,0,0,0.5);
+ border: 0px;
+ padding: 0px;
+ z-index: 8000;
+ display: none;
+
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ -khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none; /* Non-prefixed version, currently
+ supported by Chrome and Opera */
+}
+
+
+.jnotification {
+ position: fixed;
+ z-index: 10000;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 10px;
+}
+
+.jnotification-container {
+ -webkit-box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
+ box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
+ padding: 12px;
+ border-radius: 8px;
+}
+
+.jnotification-close {
+ content: '';
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ font-size: 20px;
+ width: 20px;
+ height: 20px;
+ cursor: pointer;
+}
+
+.jnotification-title {
+ font-weight: bold;
+}
+
+.jnotification-header {
+ display: flex;
+ padding-bottom: 5px;
+}
+
+.jnotification-header:empty {
+ display: none;
+}
+
+.jnotification-image {
+ margin-right: 5px;
+}
+
+.jnotification-image:empty {
+ display: none;
+}
+
+.jnotification-image img {
+ width: 24px;
+}
+
+.jnotification-name {
+ text-transform: uppercase;
+ font-size: 0.9em;
+ flex: 1;
+ letter-spacing: 0.1em;
+}
+
+.jnotification {
+ bottom: 0px;
+}
+.jnotification-container {
+ background-color: #000;
+ background: rgba(92,92,92,1);
+ background: linear-gradient(0deg, rgba(92,92,92,1) 0%, rgba(77,77,77,1) 100%);
+ color: #fff;
+ width: 320px;
+ margin: 30px;
+ padding: 20px;
+}
+
+.jnotification-error .jnotification-container {
+ background: rgb(182,38,6);
+ background: linear-gradient(0deg, rgba(170,41,13,1) 0%, rgba(149,11,11,1) 100%);
+}
+
+@media (max-width: 800px) {
+ .jnotification {
+ top: 0px;
+ width: 100%;
+ }
+ .jnotification-container {
+ background: rgba(255,255,255,0.95);
+ border: 1px solid #eee;
+ color: #444;
+ }
+ .jnotification-error .jnotification-container {
+ background: rgba(255,255,255,0.95);
+ color: #790909;
+ }
+ .jnotification-close {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ }
+}
+
+.jnotification-header {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ -ms-flex-align: center;
+ align-items: center;
+}
+
+.jpicker {
+ cursor: pointer;
+ white-space: nowrap;
+ display: inline-flex;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ outline: none;
+}
+
+.jpicker-header {
+ background-repeat: no-repeat;
+ background-position: top 50% right 5px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 10l5 5 5-5H7z' fill='gray'/%3E%3C/svg%3E");
+ text-overflow: ellipsis;
+ cursor: pointer;
+ box-sizing: border-box;
+ text-align: left;
+ outline: none;
+
+ line-height: 24px;
+ padding: 2px;
+ padding-left: 12px;
+ padding-right: 35px;
+ outline: none;
+ border-radius: 4px;
+}
+
+.jpicker-header:hover {
+ background-color: #eee;
+}
+
+.jpicker-content {
+ position: absolute;
+ display: none;
+ box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
+ border-radius: 4px;
+ background-color: #fff;
+ padding: 4px;
+ z-index: 50;
+ text-align: left;
+}
+
+.jpicker-content div {
+ padding: 6px;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+.jpicker-focus .jpicker-content {
+ display: block;
+}
+
+.jpicker-content div:hover {
+ background-color:#efefef;
+}
+
+
+
+
+.jprogressbar
+{
+ cursor:pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ box-sizing: border-box;
+ background:#fff;
+ -webkit-tap-highlight-color: transparent;
+ display: inline-block;
+ box-sizing: border-box;
+ cursor:pointer;
+ border:1px solid #ccc;
+ position:relative;
+}
+
+.jprogressbar::before {
+ content:attr(data-value);
+ position:absolute;
+ margin:5px;
+ margin-left:10px;
+}
+
+.jprogressbar-header::placeholder
+{
+ color:#000;
+}
+
+.jprogressbar::focus {
+ outline: auto 5px -webkit-focus-ring-color;
+}
+
+.jprogressbar > div {
+ background-color: #eee;
+ background-color: red;
+ box-sizing: border-box;
+ height:31px;
+}
+
+.jrating {
+ display:flex;
+}
+.jrating > div {
+ width:24px;
+ height:24px;
+ line-height:24px;
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z' fill='gray'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+}
+
+.jrating .jrating-over {
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ opacity: 0.7;
+}
+
+.jrating .jrating-selected {
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='red'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+}
+
+
+/**
+ * (c) Image slider
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Image Slider
+ */
+
+.jslider {
+ margin-top:10px;
+ margin-bottom:10px;
+}
+
+.jslider-container img {
+ width:60px;
+ margin-right:5px;
+ margin-bottom:5px;
+}
+
+.jslider-attach {
+ cursor:pointer;
+}
+
+.jslider-left::before {
+ position: fixed;
+ left: 10px;
+ content:'arrow_back_ios';
+ color: #fff;
+ width: 30px;
+ height: 30px;
+ font-family: 'Material Icons';
+ font-size: 30px;
+ text-shadow: 0px 0px 0px #000;
+ text-align: center;
+}
+
+.jslider-right::after {
+ position: fixed;
+ right: 5px;
+ content: 'arrow_forward_ios';
+ color: #fff;
+ width: 30px;
+ height: 30px;
+ font-family: 'Material Icons';
+ font-size: 30px;
+ text-shadow: 0px 0px 0px #000;
+ text-align: center;
+}
+
+.jslider-close {
+ width:24px;
+ height:24px;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ position:fixed;
+ top:15px;
+ right:15px;
+ display:none;
+ cursor:pointer;
+ z-index:3000;
+}
+
+.jslider-preview {
+ position:fixed;
+ left:0;
+ top:0;
+ width: 100%;
+ min-height:100%;
+ z-index:2000;
+ margin:0px;
+ box-sizing:border-box;
+
+ background-color:rgba(0,0,0,0.9);
+ -webkit-transition-duration: .4s;
+ transition-duration: .4s;
+ display: flex;
+ -ms-flex-align: center;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+
+ align-items: center;
+}
+
+.jslider-preview img {
+ min-width:70%;
+ max-width:100%;
+ height:auto;
+ box-sizing: border-box;
+ margin:0 auto;
+ vertical-align:middle;
+ display:none;
+}
+
+
+.jtabs {
+ max-width: 100vw;
+ position: relative;
+}
+
+.jtabs .jtabs-headers-container {
+ display: flex;
+ align-items: center;
+}
+
+.jtabs .jtabs-headers {
+ display: flex;
+ align-items: center;
+ overflow: hidden;
+ position: relative;
+}
+
+.jtabs .jtabs-headers > div:not(.jtabs-border) {
+ padding: 6px;
+ padding-left: 20px;
+ padding-right: 20px;
+ margin-left: 1px;
+ margin-right: 1px;
+ margin-bottom: 1px;
+ background-color: #f1f1f1;
+ cursor: pointer;
+ white-space: nowrap;
+}
+
+.jtabs .jtabs-headers > div.jtabs-selected {
+ background-color: #e8e8e8;
+ color: #000;
+}
+
+.jtabs .jtabs-content {
+ box-sizing: border-box;
+}
+
+.jtabs .jtabs-content > div {
+ display: none;
+ box-sizing: border-box;
+}
+
+.jtabs .jtabs-content > div.jtabs-selected {
+ display: block;
+}
+
+.jtabs .jtabs-border {
+ position: absolute;
+ height: 2px;
+ background-color: #888;
+ transform-origin: left;
+ transition: all .2s cubic-bezier(0.4,0,0.2,1);
+ transition-property: color,left,transform;
+ display: none;
+}
+
+.jtabs-animation .jtabs-border {
+ display: initial;
+}
+
+.jtabs .jtabs-controls {
+ margin: 3px;
+ margin-left: 10px;
+ display: flex;
+ min-width: 82px;
+}
+
+.jtabs .jtabs-controls > div {
+ cursor: pointer;
+ background-position: center;
+ background-repeat: no-repeat;
+ width: 24px;
+ height: 24px;
+ line-height: 24px;
+}
+
+.jtabs .jtabs-prev {
+ margin-left: 10px;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='gray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-prev.disabled {
+ margin-left: 10px;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='lightgray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-next {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='gray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-next.disabled {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='lightgray' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E");
+}
+
+.jtabs .jtabs-add {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24' viewBox='0 0 24 24' width='24'%3E%3Cpath d='M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z' fill='%23bbbbbb'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+}
+
+.jtags {
+ display: flex;
+ flex-wrap: wrap;
+ -ms-flex-direction: row;
+ -webkit-flex-direction: row;
+ flex-direction: row;
+ -ms-flex-pack: flex-start;
+ -webkit-justify-content: space-between;
+ justify-content: flex-start;
+ padding: 2px;
+ border: 1px solid #ccc;
+}
+
+.jtags > div {
+ padding: 3px;
+ padding-left: 10px;
+ padding-right: 22px;
+ position: relative;
+ border-radius: 1px;
+ margin: 2px;
+ display: block;
+ outline: none;
+}
+
+.jtags > div::after {
+ content: 'x';
+ position: absolute;
+ top: 4px;
+ right: 4px;
+ width: 12px;
+ height: 12px;
+ cursor: pointer;
+ font-size: 11px;
+ display: none;
+}
+
+.jtags_label {
+ background-color: #eeeeee !important;
+}
+
+.jtags_label::after {
+ display: inline-block !important;
+}
+
+.jtags_error::after {
+ color: #fff !important;
+}
+
+.jtags_error {
+ background-color: #d93025 !important;
+ color: #fff;
+}
+
+
+.jtags_search {
+ position: absolute;
+ display: none;
+ box-shadow: 0 1px 2px 0 rgba(60,64,67,0.302), 0 2px 6px 2px rgba(60,64,67,0.149);
+ border: none;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ width: 280px;
+ padding: 8px 0;
+
+ -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.2);
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2);
+ -webkit-transition: opacity .218s;
+ transition: opacity .218s;
+ background: #fff;
+ border: 1px solid rgba(0,0,0,.2);
+ cursor: pointer;
+ margin: 0;
+ min-width: 300px;
+ outline: none;
+ width: auto;
+ user-select: none;
+}
+
+.jtags_search > div {
+ color: #333;
+ cursor: pointer;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ padding: 5px 10px;
+ user-select: none;
+ -webkit-align-items: center;
+ align-items: center;
+}
+
+.jtags_search > div:hover {
+ background-color: #e8eaed;
+}
+
+.jtags_search > div > img {
+ width: 32px;
+ height: 32px;
+ user-select: none;
+ border-radius: 16px;
+ margin-right: 2px;
+}
+
+.jtags_search > div > div {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-left: 2px;
+ max-width: 300px;
+ white-space: nowrap;
+ user-select: none;
+}
+
+.jtags_search .selected {
+ background-color: #e8eaed;
+}
+
+.jtoolbar-container {
+ border-radius: 2px;
+ margin-bottom: 5px;
+ box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
+ display: inline-flex !important;
+}
+
+.jtoolbar {
+ cursor: pointer;
+ white-space: nowrap;
+ display: flex;
+ padding:4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.jtoolbar-mobile {
+ display: flex;
+ position:fixed;
+ bottom: 0;
+ margin: 0;
+ left: 0;
+ width: 100%;
+ background: #f7f7f8;
+ z-index: 1;
+ box-sizing: border-box;
+ box-shadow: 0 -1px 2px rgba(0,0,0,.1);
+ border-radius: 0px;
+}
+
+.jtoolbar > div {
+ display: inline-flex;
+ align-items: center;
+ box-sizing: border-box;
+ vertical-align:middle;
+ justify-content: space-evenly;
+}
+
+.jtoolbar-mobile > div {
+ display: flex;
+ width: 100%;
+}
+
+.jtoolbar .jtoolbar-item {
+ position: relative;
+ text-align: center;
+ margin: auto;
+ padding: 2px;
+ padding-left:4px;
+ padding-right:4px;
+}
+
+.jtoolbar-mobile .jtoolbar-item {
+ flex:1;
+}
+
+.jtoolbar .jtoolbar-divisor {
+ width: 2px;
+ height: 24px;
+ padding: 0px;
+ margin-left: 4px;
+ margin-right: 4px;
+ background-color: #f2f2f2;
+}
+
+
+.jtoolbar-mobile a
+{
+ text-decoration:none;
+ display:inline-block;
+}
+
+.jtoolbar-mobile i {
+ display: inline-flex !important;
+ color:#929292;
+}
+
+.jtoolbar-mobile span {
+ font-size:0.7em;
+ display:block;
+ color:#929292;
+}
+
+.jtoolbar-mobile .jtoolbar-selected a, .jtoolbar-mobile .jtoolbar-selected i, .jtoolbar-mobile .jtoolbar-selected span {
+ color:var(--active-color) !important;
+ background-color:transparent;
+}
+
+.jtoolbar-item {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.jtoolbar-item i {
+ display: block;
+ color:#333;
+}
+
+.jtoolbar-item:hover {
+ background-color:#f2f2f2;
+}
+
+
+.jtoolbar .jpicker {
+ padding-left:0px;
+ padding-right:0px;
+}
+
+.jtoolbar .jpicker-header {
+ height: 24px;
+ line-height: 24px;
+ padding: 0px;
+ padding-right: 20px;
+ padding-left: 4px;
+ background-position: top 50% right 0px;
+}
+
+.jtoolbar .jpicker-content div {
+ padding: 6px;
+}
+
+.jtoolbar-active {
+ background-color:#eee;
+}
+
+.jtoolbar .fa {
+ width: 24px;
+ height: 24px;
+ display: block;
+ line-height: 24px;
+}
+
+
+
diff --git a/web-tools/web/_static/jsuites/jsuites.js b/web-tools/web/_static/jsuites/jsuites.js
new file mode 100644
index 0000000..2a1cdeb
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.js
@@ -0,0 +1,8470 @@
+/**
+ * (c) jSuites Javascript Web Components (v3.7.0)
+ *
+ * Author: Paul Hodel <paul.hodel@gmail.com>
+ * Website: https://bossanova.uk/jsuites/
+ * Description: Create amazing web based applications.
+ *
+ * MIT License
+ *
+ */
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ global.jSuites = factory();
+}(this, (function () {
+
+ 'use strict';
+
+var jSuites = function(options) {
+ var obj = {}
+
+ obj.init = function() {
+ }
+
+ return obj;
+}
+
+jSuites.ajax = (function(options, complete) {
+ if (Array.isArray(options)) {
+ // Create multiple request controller
+ var multiple = {
+ instance: [],
+ complete: complete,
+ }
+
+ if (options.length > 0) {
+ for (var i = 0; i < options.length; i++) {
+ options[i].multiple = multiple;
+ multiple.instance.push(jSuites.ajax(options[i]));
+ }
+ }
+
+ return multiple;
+ }
+
+ if (! options.data) {
+ options.data = {};
+ }
+
+ if (options.type) {
+ options.method = options.type;
+ }
+
+ // Default method
+ if (! options.method) {
+ options.method = 'GET';
+ }
+
+ // Default type
+ if (! options.dataType) {
+ options.dataType = 'json';
+ }
+
+ if (options.data) {
+ // Parse object to variables format
+ var parseData = function(value, key) {
+ var vars = [];
+ var keys = Object.keys(value);
+ if (keys.length) {
+ for (var i = 0; i < keys.length; i++) {
+ if (key) {
+ var k = key + '[' + keys[i] + ']';
+ } else {
+ var k = keys[i];
+ }
+
+ if (typeof(value[keys[i]]) == 'object') {
+ var r = parseData(value[keys[i]], k);
+ var o = Object.keys(r);
+ for (var j = 0; j < o.length; j++) {
+ vars[o[j]] = r[o[j]];
+ }
+ } else {
+ vars[k] = value[keys[i]];
+ }
+ }
+ }
+
+ return vars;
+ }
+
+ var data = [];
+ var d = parseData(options.data);
+ var k = Object.keys(d);
+ for (var i = 0; i < k.length; i++) {
+ data.push(k[i] + '=' + encodeURIComponent(d[k[i]]));
+ }
+
+ if (options.method == 'GET' && data.length > 0) {
+ if (options.url.indexOf('?') < 0) {
+ options.url += '?';
+ }
+ options.url += data.join('&');
+ }
+ }
+
+ var httpRequest = new XMLHttpRequest();
+ httpRequest.open(options.method, options.url, true);
+ httpRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+
+ if (options.method == 'POST') {
+ httpRequest.setRequestHeader('Accept', 'application/json');
+ httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ } else {
+ if (options.dataType == 'json') {
+ httpRequest.setRequestHeader('Content-Type', 'text/json');
+ }
+ }
+
+ // No cache
+ if (options.cache != true) {
+ httpRequest.setRequestHeader('pragma', 'no-cache');
+ httpRequest.setRequestHeader('cache-control', 'no-cache');
+ }
+
+ // Authentication
+ if (options.withCredentials == true) {
+ httpRequest.withCredentials = true
+ }
+
+ // Before send
+ if (typeof(options.beforeSend) == 'function') {
+ options.beforeSend(httpRequest);
+ }
+
+ httpRequest.onload = function() {
+ if (httpRequest.status === 200) {
+ if (options.dataType == 'json') {
+ try {
+ var result = JSON.parse(httpRequest.responseText);
+
+ if (options.success && typeof(options.success) == 'function') {
+ options.success(result);
+ }
+ } catch(err) {
+ if (options.error && typeof(options.error) == 'function') {
+ options.error(err, result);
+ }
+ }
+ } else {
+ var result = httpRequest.responseText;
+
+ if (options.success && typeof(options.success) == 'function') {
+ options.success(result);
+ }
+ }
+ } else {
+ if (options.error && typeof(options.error) == 'function') {
+ options.error(httpRequest.responseText);
+ }
+ }
+
+ // Global queue
+ if (jSuites.ajax.queue && jSuites.ajax.queue.length > 0) {
+ jSuites.ajax.send(jSuites.ajax.queue.shift());
+ }
+
+ // Global complete method
+ if (jSuites.ajax.requests && jSuites.ajax.requests.length) {
+ // Get index of this request in the container
+ var index = jSuites.ajax.requests.indexOf(httpRequest);
+ // Remove from the ajax requests container
+ jSuites.ajax.requests.splice(index, 1);
+ // Last one?
+ if (! jSuites.ajax.requests.length) {
+ if (options.complete && typeof(options.complete) == 'function') {
+ options.complete(result);
+ }
+ }
+ // Controllers
+ if (options.multiple && options.multiple.instance) {
+ // Get index of this request in the container
+ var index = options.multiple.instance.indexOf(httpRequest);
+ // Remove from the ajax requests container
+ options.multiple.instance.splice(index, 1);
+ // If this is the last one call method complete
+ if (! options.multiple.instance.length) {
+ if (options.multiple.complete && typeof(options.multiple.complete) == 'function') {
+ options.multiple.complete(result);
+ }
+ }
+ }
+ }
+ }
+
+ // Data
+ httpRequest.data = data;
+
+ // Queue
+ if (options.queue == true && jSuites.ajax.requests.length > 0) {
+ jSuites.ajax.queue.push(httpRequest);
+ } else {
+ jSuites.ajax.send(httpRequest)
+ }
+
+ return httpRequest;
+});
+
+jSuites.ajax.send = function(httpRequest) {
+ if (httpRequest.data) {
+ httpRequest.send(httpRequest.data.join('&'));
+ } else {
+ httpRequest.send();
+ }
+
+ jSuites.ajax.requests.push(httpRequest);
+}
+
+jSuites.ajax.exists = function(url, __callback) {
+ var http = new XMLHttpRequest();
+ http.open('HEAD', url, false);
+ http.send();
+ if (http.status) {
+ __callback(http.status);
+ }
+}
+
+jSuites.ajax.requests = [];
+
+jSuites.ajax.queue = [];
+
+jSuites.alert = function(message) {
+ if (jSuites.getWindowWidth() < 800 && jSuites.dialog) {
+ jSuites.dialog.open({
+ title:'Alert',
+ message:message,
+ });
+ } else {
+ alert(message);
+ }
+}
+
+jSuites.animation = {};
+
+jSuites.animation.slideLeft = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-left-in');
+ setTimeout(function() {
+ element.classList.remove('slide-left-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-left-out');
+ setTimeout(function() {
+ element.classList.remove('slide-left-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ }
+}
+
+jSuites.animation.slideRight = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-right-in');
+ setTimeout(function() {
+ element.classList.remove('slide-right-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-right-out');
+ setTimeout(function() {
+ element.classList.remove('slide-right-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ }
+}
+
+jSuites.animation.slideTop = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-top-in');
+ setTimeout(function() {
+ element.classList.remove('slide-top-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-top-out');
+ setTimeout(function() {
+ element.classList.remove('slide-top-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ }
+}
+
+jSuites.animation.slideBottom = function(element, direction, done) {
+ if (direction == true) {
+ element.classList.add('slide-bottom-in');
+ setTimeout(function() {
+ element.classList.remove('slide-bottom-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 400);
+ } else {
+ element.classList.add('slide-bottom-out');
+ setTimeout(function() {
+ element.classList.remove('slide-bottom-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 100);
+ }
+}
+
+jSuites.animation.fadeIn = function(element, done) {
+ element.classList.add('fade-in');
+ setTimeout(function() {
+ element.classList.remove('fade-in');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 2000);
+}
+
+jSuites.animation.fadeOut = function(element, done) {
+ element.classList.add('fade-out');
+ setTimeout(function() {
+ element.classList.remove('fade-out');
+ if (typeof(done) == 'function') {
+ done();
+ }
+ }, 1000);
+}
+
+jSuites.calendar = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Global container
+ if (! jSuites.calendar.current) {
+ jSuites.calendar.current = null;
+ }
+
+ // Default configuration
+ var defaults = {
+ // Render type: [ default | year-month-picker ]
+ type: 'default',
+ // Restrictions
+ validRange: null,
+ // Starting weekday - 0 for sunday, 6 for saturday
+ startingDay: null,
+ // Date format
+ format: 'DD/MM/YYYY',
+ // Allow keyboard date entry
+ readonly: true,
+ // Today is default
+ today: false,
+ // Show timepicker
+ time: false,
+ // Show the reset button
+ resetButton: true,
+ // Placeholder
+ placeholder: '',
+ // Translations can be done here
+ months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ monthsFull: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ weekdays: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
+ weekdays_short: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
+ textDone: 'Done',
+ textReset: 'Reset',
+ textUpdate: 'Update',
+ // Value
+ value: null,
+ // Fullscreen (this is automatic set for screensize < 800)
+ fullscreen: false,
+ // Create the calendar closed as default
+ opened: false,
+ // Events
+ onopen: null,
+ onclose: null,
+ onchange: null,
+ onupdate: null,
+ // Internal mode controller
+ mode: null,
+ position: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Value
+ if (! obj.options.value) {
+ if (el.tagName == 'INPUT' && el.value) {
+ obj.options.value = el.value;
+ }
+ }
+
+ // Date
+ obj.date = null;
+
+ if (obj.options.value) {
+ obj.date = jSuites.calendar.toArray(obj.options.value);
+ } else {
+ if (obj.options.today) {
+ var date = new Date();
+ var y = date.getFullYear();
+ var m = date.getMonth() + 1;
+ var d = date.getDate();
+ var h = date.getHours();
+ var i = date.getMinutes();
+
+ obj.date = [ y, m, d, h, i, 0 ];
+ }
+ }
+
+ // Calendar elements
+ var calendarReset = document.createElement('div');
+ calendarReset.className = 'jcalendar-reset';
+ calendarReset.innerHTML = obj.options.textReset;
+
+ var calendarConfirm = document.createElement('div');
+ calendarConfirm.className = 'jcalendar-confirm';
+ calendarConfirm.innerHTML = obj.options.textDone;
+
+ var calendarControls = document.createElement('div');
+ calendarControls.className = 'jcalendar-controls'
+ calendarControls.style.borderBottom = '1px solid #ddd';
+
+ if (obj.options.resetButton) {
+ calendarControls.appendChild(calendarReset);
+ }
+ calendarControls.appendChild(calendarConfirm);
+
+ var calendarContainer = document.createElement('div');
+ calendarContainer.className = 'jcalendar-container';
+
+ var calendarContent = document.createElement('div');
+ calendarContent.className = 'jcalendar-content';
+ calendarContainer.appendChild(calendarContent);
+
+ // Main element
+ if (el.tagName == 'DIV') {
+ var calendar = el;
+ calendar.className = 'jcalendar-inline';
+ } else {
+ // Add controls to the screen
+ calendarContent.appendChild(calendarControls);
+
+ var calendar = document.createElement('div');
+ calendar.className = 'jcalendar';
+ }
+ calendar.appendChild(calendarContainer);
+
+ // Table container
+ var calendarTableContainer = document.createElement('div');
+ calendarTableContainer.className = 'jcalendar-table';
+ calendarContent.appendChild(calendarTableContainer);
+
+ // Previous button
+ var calendarHeaderPrev = document.createElement('td');
+ calendarHeaderPrev.setAttribute('colspan', '2');
+ calendarHeaderPrev.className = 'jcalendar-prev';
+
+ // Header with year and month
+ var calendarLabelYear = document.createElement('span');
+ calendarLabelYear.className = 'jcalendar-year';
+
+ var calendarLabelMonth = document.createElement('span');
+ calendarLabelMonth.className = 'jcalendar-month';
+
+ var calendarHeaderTitle = document.createElement('td');
+ calendarHeaderTitle.className = 'jcalendar-header';
+ calendarHeaderTitle.setAttribute('colspan', '3');
+ calendarHeaderTitle.appendChild(calendarLabelMonth);
+ calendarHeaderTitle.appendChild(calendarLabelYear);
+
+ var calendarHeaderNext = document.createElement('td');
+ calendarHeaderNext.setAttribute('colspan', '2');
+ calendarHeaderNext.className = 'jcalendar-next';
+
+ var calendarHeaderRow = document.createElement('tr');
+ calendarHeaderRow.appendChild(calendarHeaderPrev);
+ calendarHeaderRow.appendChild(calendarHeaderTitle);
+ calendarHeaderRow.appendChild(calendarHeaderNext);
+
+ var calendarHeader = document.createElement('thead');
+ calendarHeader.appendChild(calendarHeaderRow);
+
+ var calendarBody = document.createElement('tbody');
+ var calendarFooter = document.createElement('tfoot');
+
+ // Calendar table
+ var calendarTable = document.createElement('table');
+ calendarTable.setAttribute('cellpadding', '0');
+ calendarTable.setAttribute('cellspacing', '0');
+ calendarTable.appendChild(calendarHeader);
+ calendarTable.appendChild(calendarBody);
+ calendarTable.appendChild(calendarFooter);
+ calendarTableContainer.appendChild(calendarTable);
+
+ var calendarSelectHour = document.createElement('select');
+ calendarSelectHour.className = 'jcalendar-select';
+ calendarSelectHour.onchange = function() {
+ obj.date[3] = this.value;
+
+ // Event
+ if (typeof(obj.options.onupdate) == 'function') {
+ obj.options.onupdate(el, obj.getValue());
+ }
+ }
+
+ for (var i = 0; i < 24; i++) {
+ var element = document.createElement('option');
+ element.value = i;
+ element.innerHTML = jSuites.two(i);
+ calendarSelectHour.appendChild(element);
+ }
+
+ var calendarSelectMin = document.createElement('select');
+ calendarSelectMin.className = 'jcalendar-select';
+ calendarSelectMin.onchange = function() {
+ obj.date[4] = this.value;
+
+ // Event
+ if (typeof(obj.options.onupdate) == 'function') {
+ obj.options.onupdate(el, obj.getValue());
+ }
+ }
+
+ for (var i = 0; i < 60; i++) {
+ var element = document.createElement('option');
+ element.value = i;
+ element.innerHTML = jSuites.two(i);
+ calendarSelectMin.appendChild(element);
+ }
+
+ // Footer controls
+ var calendarControlsFooter = document.createElement('div');
+ calendarControlsFooter.className = 'jcalendar-controls';
+
+ var calendarControlsTime = document.createElement('div');
+ calendarControlsTime.className = 'jcalendar-time';
+ calendarControlsTime.style.maxWidth = '140px';
+ calendarControlsTime.appendChild(calendarSelectHour);
+ calendarControlsTime.appendChild(calendarSelectMin);
+
+ var calendarControlsUpdateButton = document.createElement('input');
+ calendarControlsUpdateButton.setAttribute('type', 'button');
+ calendarControlsUpdateButton.className = 'jcalendar-update';
+ calendarControlsUpdateButton.value = obj.options.textUpdate;
+
+ var calendarControlsUpdate = document.createElement('div');
+ calendarControlsUpdate.style.flexGrow = '10';
+ calendarControlsUpdate.appendChild(calendarControlsUpdateButton);
+ calendarControlsFooter.appendChild(calendarControlsTime);
+
+ // Only show the update button for input elements
+ if (el.tagName == 'INPUT') {
+ calendarControlsFooter.appendChild(calendarControlsUpdate);
+ }
+
+ calendarContent.appendChild(calendarControlsFooter);
+
+ var calendarBackdrop = document.createElement('div');
+ calendarBackdrop.className = 'jcalendar-backdrop';
+ calendar.appendChild(calendarBackdrop);
+
+ // Update actions button
+ var updateActions = function() {
+ var currentDay = calendar.querySelector('.jcalendar-selected');
+
+ if (currentDay && currentDay.classList.contains('jcalendar-disabled')) {
+ calendarControlsUpdateButton.setAttribute('disabled', 'disabled');
+ calendarSelectHour.setAttribute('disabled', 'disabled');
+ calendarSelectMin.setAttribute('disabled', 'disabled');
+ } else {
+ calendarControlsUpdateButton.removeAttribute('disabled');
+ calendarSelectHour.removeAttribute('disabled');
+ calendarSelectMin.removeAttribute('disabled');
+ }
+ }
+
+ /**
+ * Open the calendar
+ */
+ obj.open = function (value) {
+ if (! calendar.classList.contains('jcalendar-focus')) {
+ if (! calendar.classList.contains('jcalendar-inline')) {
+ obj.getDays();
+ // Get content
+ if (obj.options.type == 'year-month-picker') {
+ obj.getMonths();
+ }
+ // Get time
+ if (obj.options.time) {
+ calendarSelectHour.value = obj.date[3];
+ calendarSelectMin.value = obj.date[4];
+ }
+
+ if (jSuites.calendar.current) {
+ jSuites.calendar.current.close();
+ }
+ // Current
+ jSuites.calendar.current = obj;
+ // Show calendar
+ calendar.classList.add('jcalendar-focus');
+
+ // Get the position of the corner helper
+ if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen) {
+ // Full
+ calendar.classList.add('jcalendar-fullsize');
+ // Animation
+ jSuites.animation.slideBottom(calendarContent, 1);
+ } else {
+ var rect = el.getBoundingClientRect();
+ var rectContent = calendarContent.getBoundingClientRect();
+
+ if (obj.options.position) {
+ calendarContainer.style.position = 'fixed';
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ calendarContainer.style.top = (rect.top - (rectContent.height + 2)) + 'px';
+ } else {
+ calendarContainer.style.top = (rect.top + rect.height + 2) + 'px';
+ }
+ calendarContainer.style.left = rect.left + 'px';
+ } else {
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ calendarContainer.style.bottom = (1 * rect.height + rectContent.height + 2) + 'px';
+ } else {
+ calendarContainer.style.top = 2 + 'px';
+ }
+ }
+ }
+
+ // Events
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el);
+ }
+ }
+ }
+ }
+
+ obj.close = function (ignoreEvents, update) {
+ if (jSuites.calendar.current) {
+ // Current
+ jSuites.calendar.current = null;
+
+ if (update !== false) {
+ var element = calendar.querySelector('.jcalendar-selected');
+
+ if (typeof(update) == 'string') {
+ var value = update;
+ } else if (element && element.classList.contains('jcalendar-disabled')) {
+ var value = obj.options.value
+ } else {
+ var value = obj.getValue();
+ }
+
+ obj.setValue(value);
+ }
+
+ // Events
+ if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el);
+ }
+
+ // Hide
+ calendar.classList.remove('jcalendar-focus');
+ }
+
+ return obj.options.value;
+ }
+
+ obj.prev = function() {
+ // Check if the visualization is the days picker or years picker
+ if (obj.options.mode == 'years') {
+ obj.date[0] = obj.date[0] - 12;
+
+ // Update picker table of days
+ obj.getYears();
+ } else if (obj.options.mode == 'months') {
+ obj.date[0] = parseInt(obj.date[0]) - 1;
+ // Update picker table of months
+ obj.getMonths();
+ } else {
+ // Go to the previous month
+ if (obj.date[1] < 2) {
+ obj.date[0] = obj.date[0] - 1;
+ obj.date[1] = 12;
+ } else {
+ obj.date[1] = obj.date[1] - 1;
+ }
+
+ // Update picker table of days
+ obj.getDays();
+ }
+ }
+
+ obj.next = function() {
+ // Check if the visualization is the days picker or years picker
+ if (obj.options.mode == 'years') {
+ obj.date[0] = parseInt(obj.date[0]) + 12;
+
+ // Update picker table of days
+ obj.getYears();
+ } else if (obj.options.mode == 'months') {
+ obj.date[0] = parseInt(obj.date[0]) + 1;
+ // Update picker table of months
+ obj.getMonths();
+ } else {
+ // Go to the previous month
+ if (obj.date[1] > 11) {
+ obj.date[0] = parseInt(obj.date[0]) + 1;
+ obj.date[1] = 1;
+ } else {
+ obj.date[1] = parseInt(obj.date[1]) + 1;
+ }
+
+ // Update picker table of days
+ obj.getDays();
+ }
+ }
+
+ obj.setValue = function(val) {
+ if (! val) {
+ val = '' + val;
+ }
+ // Values
+ var newValue = val;
+ var oldValue = obj.options.value;
+
+ if (oldValue != newValue) {
+ // Set label
+ var value = obj.setLabel(newValue, obj.options);
+ var date = newValue.split(' ');
+ if (! date[1]) {
+ date[1] = '00:00:00';
+ }
+ var time = date[1].split(':')
+ var date = date[0].split('-');
+ var y = parseInt(date[0]);
+ var m = parseInt(date[1]);
+ var d = parseInt(date[2]);
+ var h = parseInt(time[0]);
+ var i = parseInt(time[1]);
+ obj.date = [ y, m, d, h, i, 0 ];
+ var val = obj.setLabel(newValue, obj.options);
+
+ // New value
+ obj.options.value = newValue;
+
+ // Input value
+ if (el.tagName == 'INPUT') {
+ el.value = val;
+ }
+
+ // Events
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: el });
+ }
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, newValue, oldValue);
+ }
+ }
+
+ obj.getDays();
+ }
+
+ obj.getValue = function() {
+ if (obj.date) {
+ if (obj.options.time) {
+ return jSuites.two(obj.date[0]) + '-' + jSuites.two(obj.date[1]) + '-' + jSuites.two(obj.date[2]) + ' ' + jSuites.two(obj.date[3]) + ':' + jSuites.two(obj.date[4]) + ':' + jSuites.two(0);
+ } else {
+ return jSuites.two(obj.date[0]) + '-' + jSuites.two(obj.date[1]) + '-' + jSuites.two(obj.date[2]) + ' ' + jSuites.two(0) + ':' + jSuites.two(0) + ':' + jSuites.two(0);
+ }
+ } else {
+ return "";
+ }
+ }
+
+ /**
+ * Calendar
+ */
+ obj.update = function(element) {
+ if (element.classList.contains('jcalendar-disabled')) {
+ // Do nothing
+ } else {
+ obj.date[2] = element.innerText;
+
+ var elements = calendar.querySelector('.jcalendar-selected');
+ if (elements) {
+ elements.classList.remove('jcalendar-selected');
+ }
+ element.classList.add('jcalendar-selected');
+
+ if (! obj.options.time) {
+ obj.close();
+ } else {
+ obj.date[3] = calendarSelectHour.value;
+ obj.date[4] = calendarSelectMin.value;
+ }
+
+ // Event
+ if (typeof(obj.options.onupdate) == 'function') {
+ obj.options.onupdate(el, obj.getValue());
+ }
+ }
+
+ // Update
+ updateActions();
+ }
+
+ /**
+ * Set to blank
+ */
+ obj.reset = function() {
+ // Close calendar
+ obj.setValue('');
+ obj.close(false, false);
+ }
+
+ /**
+ * Get calendar days
+ */
+ obj.getDays = function() {
+ // Mode
+ obj.options.mode = 'days';
+
+ // Setting current values in case of NULLs
+ var date = new Date();
+
+ // Current selection
+ var year = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear());
+ var month = obj.date && jSuites.isNumeric(obj.date[1]) ? obj.date[1] : parseInt(date.getMonth()) + 1;
+ var day = obj.date && jSuites.isNumeric(obj.date[2]) ? obj.date[2] : parseInt(date.getDate());
+ var hour = obj.date && jSuites.isNumeric(obj.date[3]) ? obj.date[3] : parseInt(date.getHours());
+ var min = obj.date && jSuites.isNumeric(obj.date[4]) ? obj.date[4] : parseInt(date.getMinutes());
+
+ // Selection container
+ obj.date = [ year, month, day, hour, min, 0 ];
+
+ // Update title
+ calendarLabelYear.innerHTML = year;
+ calendarLabelMonth.innerHTML = obj.options.months[month - 1];
+
+ // Current month and Year
+ var isCurrentMonthAndYear = (date.getMonth() == month - 1) && (date.getFullYear() == year) ? true : false;
+ var currentDay = date.getDate();
+
+ // Number of days in the month
+ var date = new Date(year, month, 0, 0, 0);
+ var numberOfDays = date.getDate();
+
+ // First day
+ var date = new Date(year, month-1, 0, 0, 0);
+ var firstDay = date.getDay() + 1;
+
+ // Index value
+ var index = obj.options.startingDay || 0;
+
+ // First of day relative to the starting calendar weekday
+ firstDay = firstDay - index;
+
+ // Reset table
+ calendarBody.innerHTML = '';
+
+ // Weekdays Row
+ var row = document.createElement('tr');
+ row.setAttribute('align', 'center');
+ calendarBody.appendChild(row);
+
+ // Create weekdays row
+ for (var i = 0; i < 7; i++) {
+ var cell = document.createElement('td');
+ cell.classList.add('jcalendar-weekday')
+ cell.innerHTML = obj.options.weekdays_short[index];
+ row.appendChild(cell);
+ // Next week day
+ index++;
+ // Restart index
+ if (index > 6) {
+ index = 0;
+ }
+ }
+
+ // Index of days
+ var index = 0;
+ var d = 0;
+
+ // Calendar table
+ for (var j = 0; j < 6; j++) {
+ // Reset cells container
+ var row = document.createElement('tr');
+ row.setAttribute('align', 'center');
+ // Data control
+ var emptyRow = true;
+ // Create cells
+ for (var i = 0; i < 7; i++) {
+ // Create cell
+ var cell = document.createElement('td');
+ cell.classList.add('jcalendar-set-day');
+
+ if (index >= firstDay && index < (firstDay + numberOfDays)) {
+ // Day cell
+ d++;
+ cell.innerHTML = d;
+
+ // Selected
+ if (d == day) {
+ cell.classList.add('jcalendar-selected');
+ }
+
+ // Current selection day is today
+ if (isCurrentMonthAndYear && currentDay == d) {
+ cell.style.fontWeight = 'bold';
+ }
+
+ // Current selection day
+ var current = jSuites.calendar.now(new Date(year, month-1, d), true);
+
+ // Available ranges
+ if (obj.options.validRange) {
+ if (! obj.options.validRange[0] || current >= obj.options.validRange[0]) {
+ var test1 = true;
+ } else {
+ var test1 = false;
+ }
+
+ if (! obj.options.validRange[1] || current <= obj.options.validRange[1]) {
+ var test2 = true;
+ } else {
+ var test2 = false;
+ }
+
+ if (! (test1 && test2)) {
+ cell.classList.add('jcalendar-disabled');
+ }
+ }
+
+ // Control
+ emptyRow = false;
+ }
+ // Day cell
+ row.appendChild(cell);
+ // Index
+ index++;
+ }
+
+ // Add cell to the calendar body
+ if (emptyRow == false) {
+ calendarBody.appendChild(row);
+ }
+ }
+
+ // Show time controls
+ if (obj.options.time) {
+ calendarControlsTime.style.display = '';
+ } else {
+ calendarControlsTime.style.display = 'none';
+ }
+
+ // Update
+ updateActions();
+ }
+
+ obj.getMonths = function() {
+ // Mode
+ obj.options.mode = 'months';
+
+ // Loading month labels
+ var months = obj.options.months;
+
+ // Update title
+ calendarLabelYear.innerHTML = obj.date[0];
+ calendarLabelMonth.innerHTML = '';
+
+ // Create months table
+ var html = '<td colspan="7"><table width="100%"><tr align="center">';
+
+ for (i = 0; i < 12; i++) {
+ if ((i > 0) && (!(i % 4))) {
+ html += '</tr><tr align="center">';
+ }
+
+ var month = parseInt(i) + 1;
+ html += '<td class="jcalendar-set-month" data-value="' + month + '">' + months[i] +'</td>';
+ }
+
+ html += '</tr></table></td>';
+
+ calendarBody.innerHTML = html;
+ }
+
+ obj.getYears = function() {
+ // Mode
+ obj.options.mode = 'years';
+
+ // Array of years
+ var y = [];
+ for (i = 0; i < 25; i++) {
+ y[i] = parseInt(obj.date[0]) + (i - 12);
+ }
+
+ // Assembling the year tables
+ var html = '<td colspan="7"><table width="100%"><tr align="center">';
+
+ for (i = 0; i < 25; i++) {
+ if ((i > 0) && (!(i % 5))) {
+ html += '</tr><tr align="center">';
+ }
+ html += '<td class="jcalendar-set-year">'+ y[i] +'</td>';
+ }
+
+ html += '</tr></table></td>';
+
+ calendarBody.innerHTML = html;
+ }
+
+ obj.setLabel = function(value, mixed) {
+ return jSuites.calendar.getDateString(value, mixed);
+ }
+
+ obj.fromFormatted = function (value, format) {
+ return jSuites.calendar.extractDateFromString(value, format);
+ }
+
+ var mouseUpControls = function(e) {
+ var action = e.target.className;
+
+ // Object id
+ if (action == 'jcalendar-prev') {
+ obj.prev();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-next') {
+ obj.next();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-month') {
+ obj.getMonths();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-year') {
+ obj.getYears();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-set-year') {
+ obj.date[0] = e.target.innerText;
+ if (obj.options.type == 'year-month-picker') {
+ obj.getMonths();
+ } else {
+ obj.getDays();
+ }
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-set-month') {
+ obj.date[1] = parseInt(e.target.getAttribute('data-value'));
+ if (obj.options.type == 'year-month-picker') {
+ obj.close();
+ } else {
+ obj.getDays();
+ }
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update') {
+ obj.close();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-close') {
+ obj.close();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-backdrop') {
+ obj.close(false, false);
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (action == 'jcalendar-reset') {
+ obj.reset();
+ e.stopPropagation();
+ e.preventDefault();
+ } else if (e.target.classList.contains('jcalendar-set-day')) {
+ if (e.target.innerText) {
+ obj.update(e.target);
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ }
+
+ var keyUpControls = function(e) {
+ if (e.target.value && e.target.value.length > 3) {
+ var test = jSuites.calendar.extractDateFromString(e.target.value, obj.options.format);
+ if (test) {
+ if (e.target.getAttribute('data-completed') == 'true') {
+ obj.setValue(test);
+ }
+ }
+ }
+ }
+
+ // Handle events
+ el.addEventListener("keyup", keyUpControls);
+
+ // Add global events
+ calendar.addEventListener("swipeleft", function(e) {
+ jSuites.animation.slideLeft(calendarTable, 0, function() {
+ obj.next();
+ jSuites.animation.slideRight(calendarTable, 1);
+ });
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ calendar.addEventListener("swiperight", function(e) {
+ jSuites.animation.slideRight(calendarTable, 0, function() {
+ obj.prev();
+ jSuites.animation.slideLeft(calendarTable, 1);
+ });
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ if ('ontouchend' in document.documentElement === true) {
+ calendar.addEventListener("touchend", mouseUpControls);
+
+ el.addEventListener("touchend", function(e) {
+ obj.open();
+ });
+ } else {
+ calendar.addEventListener("mouseup", mouseUpControls);
+
+ el.addEventListener("mouseup", function(e) {
+ obj.open();
+ });
+ }
+
+ if (! jSuites.calendar.hasEvents) {
+ if ('ontouchstart' in document.documentElement === true) {
+ document.addEventListener("touchstart", jSuites.calendar.isOpen);
+ } else {
+ document.addEventListener("mousedown", jSuites.calendar.isOpen);
+ }
+
+ document.addEventListener("keydown", function(e) {
+ if (e.which == 13) {
+ // ENTER
+ if (jSuites.calendar.current) {
+ jSuites.calendar.current.close(false, true);
+ }
+ } else if (e.which == 27) {
+ // ESC
+ if (jSuites.calendar.current) {
+ jSuites.calendar.current.close(false, false);
+ }
+ }
+ });
+
+ jSuites.calendar.hasEvents = true;
+ }
+
+ // Append element to the DOM
+ if (el.tagName == 'INPUT') {
+ el.parentNode.insertBefore(calendar, el.nextSibling);
+ // Add properties
+ el.setAttribute('autocomplete', 'off');
+ el.setAttribute('data-mask', obj.options.format.toLowerCase());
+
+ if (obj.options.readonly) {
+ el.setAttribute('readonly', 'readonly');
+ }
+ if (obj.options.placeholder) {
+ el.setAttribute('placeholder', obj.options.placeholder);
+ }
+ // Element
+ el.classList.add('jcalendar-input');
+ // Value
+ el.value = obj.setLabel(obj.getValue(), obj.options);
+ } else {
+ // Get days
+ obj.getDays();
+ // Hour
+ if (obj.options.time) {
+ calendarSelectHour.value = obj.date[3];
+ calendarSelectMin.value = obj.date[4];
+ }
+ }
+
+ // Keep object available from the node
+ el.calendar = obj;
+ el.change = obj.setValue;
+
+ if (obj.options.opened == true) {
+ obj.open();
+ }
+
+ return obj;
+});
+
+jSuites.calendar.prettify = function(d, texts) {
+ if (! texts) {
+ var texts = {
+ justNow: 'Just now',
+ xMinutesAgo: '{0}m ago',
+ xHoursAgo: '{0}h ago',
+ xDaysAgo: '{0}d ago',
+ xWeeksAgo: '{0}w ago',
+ xMonthsAgo: '{0} mon ago',
+ xYearsAgo: '{0}y ago',
+ }
+ }
+
+ var d1 = new Date();
+ var d2 = new Date(d);
+ var total = parseInt((d1 - d2) / 1000 / 60);
+
+ String.prototype.format = function(o) {
+ return this.replace('{0}', o);
+ }
+
+ if (total == 0) {
+ var text = texts.justNow;
+ } else if (total < 90) {
+ var text = texts.xMinutesAgo.format(total);
+ } else if (total < 1440) { // One day
+ var text = texts.xHoursAgo.format(Math.round(total/60));
+ } else if (total < 20160) { // 14 days
+ var text = texts.xDaysAgo.format(Math.round(total / 1440));
+ } else if (total < 43200) { // 30 days
+ var text = texts.xWeeksAgo.format(Math.round(total / 10080));
+ } else if (total < 1036800) { // 24 months
+ var text = texts.xMonthsAgo.format(Math.round(total / 43200));
+ } else { // 24 months+
+ var text = texts.xYearsAgo.format(Math.round(total / 525600));
+ }
+
+ return text;
+}
+
+jSuites.calendar.prettifyAll = function() {
+ var elements = document.querySelectorAll('.prettydate');
+ for (var i = 0; i < elements.length; i++) {
+ if (elements[i].getAttribute('data-date')) {
+ elements[i].innerHTML = jSuites.calendar.prettify(elements[i].getAttribute('data-date'));
+ } else {
+ elements[i].setAttribute('data-date', elements[i].innerHTML);
+ elements[i].innerHTML = jSuites.calendar.prettify(elements[i].innerHTML);
+ }
+ }
+}
+
+jSuites.calendar.now = function(date, dateOnly) {
+ if (! date) {
+ var date = new Date();
+ }
+ var y = date.getFullYear();
+ var m = date.getMonth() + 1;
+ var d = date.getDate();
+ var h = date.getHours();
+ var i = date.getMinutes();
+ var s = date.getSeconds();
+
+ if (dateOnly == true) {
+ return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d);
+ } else {
+ return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d) + ' ' + jSuites.two(h) + ':' + jSuites.two(i) + ':' + jSuites.two(s);
+ }
+}
+
+jSuites.calendar.toArray = function(value) {
+ var date = value.split(((value.indexOf('T') !== -1) ? 'T' : ' '));
+ var time = date[1];
+ var date = date[0].split('-');
+ var y = parseInt(date[0]);
+ var m = parseInt(date[1]);
+ var d = parseInt(date[2]);
+
+ if (time) {
+ var time = time.split(':');
+ var h = parseInt(time[0]);
+ var i = parseInt(time[1]);
+ } else {
+ var h = 0;
+ var i = 0;
+ }
+ return [ y, m, d, h, i, 0 ];
+}
+
+// Helper to extract date from a string
+jSuites.calendar.extractDateFromString = function(date, format) {
+ if (date > 0 && Number(date) == date) {
+ var d = new Date(Math.round((date - 25569)*86400*1000));
+ return d.getFullYear() + "-" + jSuites.two(d.getMonth()) + "-" + jSuites.two(d.getDate()) + ' 00:00:00';
+ }
+
+ var v1 = '' + date;
+ var v2 = format.replace(/[0-9]/g,'');
+
+ var test = 1;
+
+ // Get year
+ var y = v2.search("YYYY");
+ y = v1.substr(y,4);
+ if (parseInt(y) != y) {
+ test = 0;
+ }
+
+ // Get month
+ var m = v2.search("MM");
+ m = v1.substr(m,2);
+ if (parseInt(m) != m || m > 12) {
+ test = 0;
+ }
+
+ // Get day
+ var d = v2.search("DD");
+ d = v1.substr(d,2);
+ if (parseInt(d) != d || d > 31) {
+ test = 0;
+ }
+
+ // Get hour
+ var h = v2.search("HH");
+ if (h >= 0) {
+ h = v1.substr(h,2);
+ if (! parseInt(h) || h > 23) {
+ h = '00';
+ }
+ } else {
+ h = '00';
+ }
+
+ // Get minutes
+ var i = v2.search("MI");
+ if (i >= 0) {
+ i = v1.substr(i,2);
+ if (! parseInt(i) || i > 59) {
+ i = '00';
+ }
+ } else {
+ i = '00';
+ }
+
+ // Get seconds
+ var s = v2.search("SS");
+ if (s >= 0) {
+ s = v1.substr(s,2);
+ if (! parseInt(s) || s > 59) {
+ s = '00';
+ }
+ } else {
+ s = '00';
+ }
+
+ if (test == 1 && date.length == v2.length) {
+ // Update source
+ return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s;
+ }
+
+ return '';
+}
+
+// Helper to convert date into string
+jSuites.calendar.getDateString = function(value, options) {
+ if (! options) {
+ var options = {};
+ }
+
+ // Labels
+ if (typeof(options) == 'string') {
+ var format = options;
+ } else {
+ var format = options.format;
+ }
+
+ // Labels
+ if (options && options.weekdays) {
+ var weekdays = options.weekdays;
+ } else {
+ var weekdays = [ 'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday' ];
+ }
+
+ // Labels
+ if (options && options.months) {
+ var months = options.months;
+ } else {
+ var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
+ }
+
+ // Labels
+ if (options && options.months) {
+ var monthsFull = options.monthsFull;
+ } else {
+ var monthsFull = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+ }
+
+ // Default date format
+ if (! format) {
+ format = 'DD/MM/YYYY';
+ }
+
+ if (value) {
+ var d = ''+value;
+ var splitStr = (d.indexOf('T') !== -1) ? 'T' : ' ';
+ d = d.split(splitStr);
+
+ var h = '';
+ var m = '';
+ var s = '';
+
+ if (d[1]) {
+ h = d[1].split(':');
+ m = h[1] ? h[1] : '00';
+ s = h[2] ? h[2] : '00';
+ h = h[0] ? h[0] : '00';
+ } else {
+ h = '00';
+ m = '00';
+ s = '00';
+ }
+
+ d = d[0].split('-');
+
+ if (d[0] && d[1] && d[2] && d[0] > 0 && d[1] > 0 && d[1] < 13 && d[2] > 0 && d[2] < 32) {
+ var calendar = new Date(d[0], d[1]-1, d[2]);
+
+ d[1] = (d[1].length < 2 ? '0' : '') + d[1];
+ d[2] = (d[2].length < 2 ? '0' : '') + d[2];
+ h = (h.length < 2 ? '0' : '') + h;
+ m = (m.length < 2 ? '0' : '') + m;
+ s = (s.length < 2 ? '0' : '') + s;
+
+ // New value
+ value = format;
+ // Legacy
+ value = value.replace('MMM', 'MON');
+
+ // Extract tokens
+ var tokens = [ 'YYYY', 'YYY', 'YY', 'Y', 'MM', 'DD', 'DY', 'DAY', 'WD', 'D', 'Q', 'HH24', 'HH12', 'HH', 'PM', 'AM', 'MI', 'SS', 'MS', 'MONTH', 'MON'];
+ var pieces = [];
+ var tmp = value;
+
+ while (tmp) {
+ var t = 0;
+ for (var i = 0; i < tokens.length; i++) {
+ if (t == 0 && tmp.toUpperCase().indexOf(tokens[i]) === 0) {
+ t = tokens[i].length;
+ }
+ }
+ if (t == 0) {
+ pieces.push(tmp.substr(0, 1));
+ tmp = tmp.substr(1);
+ } else {
+ pieces.push(tmp.substr(0, t));
+ tmp = tmp.substr(t);
+ }
+ }
+
+ // Replace tokens per values
+ var replace = function(k, v, c) {
+ if (c == true) {
+ for (var i = 0; i < pieces.length; i++) {
+ if (pieces[i].toUpperCase() == k) {
+ pieces[i] = v;
+ }
+ }
+ } else {
+ for (var i = 0; i < pieces.length; i++) {
+ if (pieces[i] == k) {
+ pieces[i] = v;
+ }
+ }
+ }
+ }
+
+ replace('YYYY', d[0], true);
+ replace('YYY', d[0].substring(1,4), true);
+ replace('YY', d[0].substring(2,4), true);
+ replace('Y', d[0].substring(3,4), true);
+
+ replace('MM', d[1], true);
+ replace('DD', d[2], true);
+ replace('Q', Math.floor((calendar.getMonth() + 3) / 3), true);
+
+ if (h) {
+ replace('HH24', h);
+ }
+
+ if (h > 12) {
+ replace('HH12', h - 12, true);
+ replace('HH', h - 12, true);
+ replace('AM', 'pm', true);
+ replace('PM', 'pm', true);
+ } else {
+ replace('HH12', h, true);
+ replace('HH', h, true);
+ replace('AM', 'am', true);
+ replace('PM', 'am', true);
+ }
+
+ replace('MI', m, true);
+ replace('SS', s, true);
+ replace('MS', calendar.getMilliseconds(), true);
+
+ // Textual tokens
+ replace('MONTH', monthsFull[calendar.getMonth()].toUpperCase());
+ replace('Month', monthsFull[calendar.getMonth()]);
+ replace('month', monthsFull[calendar.getMonth()].toLowerCase());
+ replace('MON', months[calendar.getMonth()].toUpperCase());
+ replace('MMM', months[calendar.getMonth()].toUpperCase());
+ replace('Mon', months[calendar.getMonth()]);
+ replace('mon', months[calendar.getMonth()].toLowerCase());
+
+ replace('DAY', weekdays[calendar.getDay()].toUpperCase());
+ replace('Day', weekdays[calendar.getDay()]);
+ replace('day', weekdays[calendar.getDay()].toLowerCase());
+ replace('DY', weekdays[calendar.getDay()].substr(0,3).toUpperCase());
+ replace('Dy', weekdays[calendar.getDay()].substr(0,3));
+ replace('dy', weekdays[calendar.getDay()].substr(0,3).toLowerCase());
+ replace('D', weekdays[calendar.getDay()]);
+ replace('WD', weekdays[calendar.getDay()]);
+
+ // Put pieces together
+ value = pieces.join('');
+ } else {
+ value = '';
+ }
+ }
+
+ return value;
+}
+
+jSuites.calendar.isOpen = function(e) {
+ if (jSuites.calendar.current) {
+ if (e.target.className && e.target.className.indexOf('jcalendar') == -1) {
+ jSuites.calendar.current.close(false, false);
+ }
+ }
+}
+
+
+jSuites.color = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+ obj.values = [];
+
+ // Global container
+ if (! jSuites.color.current) {
+ jSuites.color.current = null;
+ }
+
+ /**
+ * @typedef {Object} defaults
+ * @property {(string|Array)} value - Initial value of the compontent
+ * @property {string} placeholder - The default instruction text on the element
+ * @property {requestCallback} onchange - Method to be execute after any changes on the element
+ * @property {requestCallback} onclose - Method to be execute when the element is closed
+ * @property {string} doneLabel - Label for button done
+ * @property {string} resetLabel - Label for button reset
+ * @property {string} resetValue - Value for button reset
+ * @property {Bool} showResetButton - Active or note for button reset - default false
+ */
+ var defaults = {
+ placeholder: '',
+ value: null,
+ onopen: null,
+ onclose: null,
+ onchange: null,
+ closeOnChange: true,
+ palette: null,
+ position: null,
+ doneLabel: 'Done',
+ resetLabel: 'Reset',
+ fullscreen: false,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ if (! obj.options.palette) {
+ // Default pallete
+ obj.options.palette = jSuites.palette();
+ }
+
+ // Value
+ if (obj.options.value) {
+ el.value = obj.options.value;
+ }
+
+ // Change
+ el.change = obj.setValue;
+
+ if (el.tagName == 'INPUT') {
+ el.classList.add('jcolor-input');
+ }
+
+ // Table container
+ var container = document.createElement('div');
+ container.className = 'jcolor';
+
+ // Table container
+ var backdrop = document.createElement('div');
+ backdrop.className = 'jcolor-backdrop';
+ container.appendChild(backdrop);
+
+ // Content
+ var content = document.createElement('div');
+ content.className = 'jcolor-content';
+
+ // Controls
+ var controls = document.createElement('div');
+ controls.className = 'jcolor-controls';
+ content.appendChild(controls);
+
+ // Reset button
+ var resetButton = document.createElement('div');
+ resetButton.className = 'jcolor-reset';
+ resetButton.innerHTML = obj.options.resetLabel;
+ resetButton.onclick = function() {
+ obj.setValue('');
+ obj.close();
+ }
+ controls.appendChild(resetButton);
+
+ // Close button
+ var closeButton = document.createElement('div');
+ closeButton.className = 'jcolor-close';
+ closeButton.innerHTML = obj.options.doneLabel;
+ closeButton.onclick = function() {
+ obj.close();
+ }
+ controls.appendChild(closeButton);
+
+ // Table pallete
+ var table = document.createElement('table');
+ table.setAttribute('cellpadding', '7');
+ table.setAttribute('cellspacing', '0');
+
+ for (var j = 0; j < obj.options.palette.length; j++) {
+ var tr = document.createElement('tr');
+ for (var i = 0; i < obj.options.palette[j].length; i++) {
+ var td = document.createElement('td');
+ var color = obj.options.palette[j][i];
+ if (color.substr(0,1) !== '#') {
+ color = '#' + color;
+ }
+ td.style.backgroundColor = color;
+ td.setAttribute('data-value', color);
+ td.innerHTML = '';
+ tr.appendChild(td);
+
+ // Selected color
+ if (obj.options.value == color) {
+ td.classList.add('jcolor-selected');
+ }
+
+ // Possible values
+ obj.values[color] = td;
+ }
+ table.appendChild(tr);
+ }
+
+ /**
+ * Open color pallete
+ */
+ obj.open = function() {
+ if (jSuites.color.current) {
+ if (jSuites.color.current != obj) {
+ jSuites.color.current.close();
+ }
+ }
+
+ if (! jSuites.color.current) {
+ // Persist element
+ jSuites.color.current = obj;
+ // Show colorpicker
+ container.classList.add('jcolor-focus');
+
+ var rectContent = content.getBoundingClientRect();
+
+ if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen == true) {
+ content.style.top = '';
+ content.classList.add('jcolor-fullscreen');
+ jSuites.animation.slideBottom(content, 1);
+ backdrop.style.display = 'block';
+ } else {
+ if (content.classList.contains('jcolor-fullscreen')) {
+ content.classList.remove('jcolor-fullscreen');
+ backdrop.style.display = '';
+ }
+
+ var rect = el.getBoundingClientRect();
+
+ if (obj.options.position) {
+ content.style.position = 'fixed';
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ content.style.top = (rect.top - (rectContent.height + 2)) + 'px';
+ } else {
+ content.style.top = (rect.top + rect.height + 2) + 'px';
+ }
+ content.style.left = rect.left + 'px';
+ } else {
+ if (window.innerHeight < rect.bottom + rectContent.height) {
+ content.style.top = -1 * (rectContent.height + rect.height + 2) + 'px';
+ } else {
+ content.style.top = '2px';
+ }
+ }
+ }
+
+ container.focus();
+
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el);
+ }
+ }
+ }
+
+ /**
+ * Close color pallete
+ */
+ obj.close = function(ignoreEvents) {
+ if (jSuites.color.current) {
+ el.focus();
+ jSuites.color.current = null;
+ if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el);
+ }
+ container.classList.remove('jcolor-focus');
+ }
+
+ // Make sure backdrop is hidden
+ backdrop.style.display = '';
+
+ return obj.options.value;
+ }
+
+ /**
+ * Set value
+ */
+ obj.setValue = function(color) {
+ if (! color) {
+ color = '';
+ }
+ if (color !== obj.options.value) {
+ el.value = color;
+ obj.options.value = color;
+
+ // Remove current selecded mark
+ var selected = container.querySelector('.jcolor-selected');
+ if (selected) {
+ selected.classList.remove('jcolor-selected');
+ }
+
+ // Mark cell as selected
+ if (obj.values[color]) {
+ obj.values[color].classList.add('jcolor-selected');
+ }
+
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: el });
+ }
+
+ // Onchange
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, color);
+ }
+ }
+
+ if (obj.options.closeOnChange == true) {
+ obj.close();
+ }
+ }
+
+ /**
+ * Get value
+ */
+ obj.getValue = function() {
+ return obj.options.value;
+ }
+
+ var backdropClickControl = false;
+
+ /**
+ * Focus
+ */
+ el.addEventListener("focus", function(e) {
+ if (! jSuites.color.current) {
+ obj.open();
+ }
+ });
+
+ /**
+ * If element is focus open the picker
+ */
+ el.addEventListener("mouseup", function(e) {
+ if (! jSuites.color.current) {
+ obj.open();
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ backdrop.addEventListener("mousedown", function(e) {
+ backdropClickControl = true;
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ backdrop.addEventListener("mouseup", function(e) {
+ if (backdropClickControl && jSuites.color.current) {
+ obj.close();
+ backdropClickControl = false;
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ // Select color
+ container.addEventListener("mouseup", function(e) {
+ if (e.target.tagName == 'TD') {
+ jSuites.color.current.setValue(e.target.getAttribute('data-value'));
+
+ if (jSuites.color.current) {
+ jSuites.color.current.close();
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+
+ // Close controller
+ document.addEventListener("mousedown", function(e) {
+ if (jSuites.color.current) {
+ var element = jSuites.findElement(e.target, 'jcolor');
+ if (! element) {
+ jSuites.color.current.close();
+ }
+ }
+ });
+
+ // Possible to focus the container
+ container.setAttribute('tabindex', '900');
+
+ // Placeholder
+ if (obj.options.placeholder) {
+ el.setAttribute('placeholder', obj.options.placeholder);
+ }
+
+ // Append to the table
+ content.appendChild(table);
+ container.appendChild(content);
+
+ // Insert picker after the element
+ if (el.tagName == 'INPUT') {
+ el.parentNode.insertBefore(container, el.nextSibling);
+ } else {
+ el.appendChild(container);
+ }
+
+ // Keep object available from the node
+ el.color = obj;
+ el.change = obj.setValue;
+
+ return obj;
+});
+
+
+
+jSuites.contextmenu = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ items: null,
+ onclick: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Class definition
+ el.classList.add('jcontextmenu');
+ // Focusable
+ el.setAttribute('tabindex', '900');
+
+ /**
+ * Open contextmenu
+ */
+ obj.open = function(e, items) {
+ if (items) {
+ // Update content
+ obj.options.items = items;
+ // Create items
+ obj.create(items);
+ }
+
+ // Coordinates
+ if ((obj.options.items && obj.options.items.length > 0) || el.children.length) {
+ if (e.target) {
+ var x = e.clientX;
+ var y = e.clientY;
+ } else {
+ var x = e.x;
+ var y = e.y;
+ }
+
+ el.classList.add('jcontextmenu-focus');
+ el.focus();
+
+ var rect = el.getBoundingClientRect();
+
+ if (window.innerHeight < y + rect.height) {
+ var h = y - rect.height;
+ if (h < 0) {
+ h = 0;
+ }
+ el.style.top = h + 'px';
+ } else {
+ el.style.top = y + 'px';
+ }
+
+ if (window.innerWidth < x + rect.width) {
+ if (x - rect.width > 0) {
+ el.style.left = (x - rect.width) + 'px';
+ } else {
+ el.style.left = '10px';
+ }
+ } else {
+ el.style.left = x + 'px';
+ }
+ }
+ }
+
+ /**
+ * Close menu
+ */
+ obj.close = function() {
+ if (el.classList.contains('jcontextmenu-focus')) {
+ el.classList.remove('jcontextmenu-focus');
+ }
+ }
+
+ /**
+ * Create items based on the declared objectd
+ * @param {object} items - List of object
+ */
+ obj.create = function(items) {
+ // Update content
+ el.innerHTML = '';
+
+ // Append items
+ for (var i = 0; i < items.length; i++) {
+ var itemContainer = createItemElement(items[i]);
+ el.appendChild(itemContainer);
+ }
+ }
+
+ /**
+ * Private function for create a new Item element
+ * @param {type} item
+ * @returns {jsuitesL#15.jSuites.contextmenu.createItemElement.itemContainer}
+ */
+ function createItemElement(item) {
+ if (item.type && (item.type == 'line' || item.type == 'divisor')) {
+ var itemContainer = document.createElement('hr');
+ } else {
+ var itemContainer = document.createElement('div');
+ var itemText = document.createElement('a');
+ itemText.innerHTML = item.title;
+
+ if (item.icon) {
+ itemContainer.setAttribute('data-icon', item.icon);
+ }
+
+ if (item.id) {
+ itemContainer.id = item.id;
+ }
+
+ if (item.disabled) {
+ itemContainer.className = 'jcontextmenu-disabled';
+ } else if (item.onclick) {
+ itemContainer.method = item.onclick;
+ itemContainer.addEventListener("mouseup", function() {
+ // Execute method
+ this.method(this);
+ });
+ }
+ itemContainer.appendChild(itemText);
+
+ if (item.submenu) {
+ var itemIconSubmenu = document.createElement('span');
+ itemIconSubmenu.innerHTML = "&#9658;";
+ itemContainer.appendChild(itemIconSubmenu);
+ itemContainer.classList.add('jcontexthassubmenu');
+ var el_submenu = document.createElement('div');
+ // Class definition
+ el_submenu.classList.add('jcontextmenu');
+ // Focusable
+ el_submenu.setAttribute('tabindex', '900');
+
+ // Append items
+ var submenu = item.submenu;
+ for (var i = 0; i < submenu.length; i++) {
+ var itemContainerSubMenu = createItemElement(submenu[i]);
+ el_submenu.appendChild(itemContainerSubMenu);
+ }
+
+ itemContainer.appendChild(el_submenu);
+ } else if (item.shortcut) {
+ var itemShortCut = document.createElement('span');
+ itemShortCut.innerHTML = item.shortcut;
+ itemContainer.appendChild(itemShortCut);
+ }
+ }
+ return itemContainer;
+ }
+
+ if (typeof(obj.options.onclick) == 'function') {
+ el.addEventListener('click', function(e) {
+ obj.options.onclick(obj, e);
+ });
+ }
+
+ // Create items
+ if (obj.options.items) {
+ obj.create(obj.options.items);
+ }
+
+ el.addEventListener('blur', function(e) {
+ setTimeout(function() {
+ obj.close();
+ }, 120);
+ });
+
+ if (! jSuites.contextmenu.hasEvents) {
+ window.addEventListener("mousewheel", function() {
+ obj.close();
+ });
+
+ document.addEventListener("contextmenu", function(e) {
+ var id = jSuites.contextmenu.getElement(e.target);
+ if (id) {
+ var element = document.querySelector('#' + id);
+ if (! element) {
+ console.error('JSUITES: Contextmenu id not found');
+ } else {
+ element.contextmenu.open(e);
+ e.preventDefault();
+ }
+ }
+ });
+
+ jSuites.contextmenu.hasEvents = true;
+ }
+
+ el.contextmenu = obj;
+
+ return obj;
+});
+
+jSuites.contextmenu.getElement = function(element) {
+ var foundId = 0;
+
+ function path (element) {
+ if (element.parentNode && element.getAttribute('aria-contextmenu-id')) {
+ foundId = element.getAttribute('aria-contextmenu-id')
+ } else {
+ if (element.parentNode) {
+ path(element.parentNode);
+ }
+ }
+ }
+
+ path(element);
+
+ return foundId;
+}
+
+jSuites.dropdown = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // If the element is a SELECT tag, create a configuration object
+ if (el.tagName == 'SELECT') {
+ var ret = jSuites.dropdown.extractFromDom(el, options);
+ el = ret.el;
+ options = ret.options;
+ }
+
+ // Default configuration
+ var defaults = {
+ url: null,
+ data: [],
+ multiple: false,
+ autocomplete: false,
+ remoteSearch: false,
+ lazyLoading: false,
+ type: null,
+ width: null,
+ maxWidth: null,
+ opened: false,
+ value: null,
+ placeholder: '',
+ newOptions: false,
+ position: false,
+ onchange: null,
+ onload: null,
+ onopen: null,
+ onclose: null,
+ onfocus: null,
+ onblur: null,
+ oninsert: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Global container
+ if (! jSuites.dropdown.current) {
+ jSuites.dropdown.current = null;
+ }
+
+ // Force autocomplete search
+ if (obj.options.remoteSearch == true) {
+ obj.options.autocomplete = true;
+ }
+
+ // Containers
+ obj.items = [];
+ obj.groups = [];
+ obj.value = [];
+
+ // Search options
+ obj.search = '';
+ obj.results = null;
+ obj.numOfItems = 0;
+
+ // Create dropdown
+ el.classList.add('jdropdown');
+
+ if (obj.options.type == 'searchbar') {
+ el.classList.add('jdropdown-searchbar');
+ } else if (obj.options.type == 'list') {
+ el.classList.add('jdropdown-list');
+ } else if (obj.options.type == 'picker') {
+ el.classList.add('jdropdown-picker');
+ } else {
+ if (jSuites.getWindowWidth() < 800) {
+ el.classList.add('jdropdown-picker');
+ obj.options.type = 'picker';
+ } else {
+ if (obj.options.width) {
+ el.style.width = obj.options.width;
+ el.style.minWidth = obj.options.width;
+ }
+ el.classList.add('jdropdown-default');
+ obj.options.type = 'default';
+ }
+ }
+
+ // Header container
+ var containerHeader = document.createElement('div');
+ containerHeader.className = 'jdropdown-container-header';
+
+ // Header
+ obj.header = document.createElement('input');
+ obj.header.className = 'jdropdown-header';
+ obj.header.setAttribute('autocomplete', 'off');
+ if (typeof(obj.options.onfocus) == 'function') {
+ obj.header.onfocus = function() {
+ obj.options.onfocus(el);
+ }
+ }
+ if (typeof(obj.options.onblur) == 'function') {
+ obj.header.onblur = function() {
+ obj.options.onblur(el);
+ }
+ }
+
+ if (obj.options.newOptions == true) {
+ obj.header.classList.add('jdropdown-add');
+ }
+
+ // Container
+ var container = document.createElement('div');
+ container.className = 'jdropdown-container';
+
+ // Dropdown content
+ var content = document.createElement('div');
+ content.className = 'jdropdown-content';
+
+ // Close button
+ var closeButton = document.createElement('div');
+ closeButton.className = 'jdropdown-close';
+ closeButton.innerHTML = 'Done';
+
+ // Reset button
+ var resetButton = document.createElement('div');
+ resetButton.className = 'jdropdown-reset';
+ resetButton.innerHTML = 'x';
+ resetButton.onclick = function() {
+ obj.reset();
+ obj.close();
+ }
+
+ // Create backdrop
+ var backdrop = document.createElement('div');
+ backdrop.className = 'jdropdown-backdrop';
+
+ // Autocomplete
+ if (obj.options.autocomplete == true) {
+ el.setAttribute('data-autocomplete', true);
+
+ // Handler
+ var keyTimer = null;
+ obj.header.addEventListener('keyup', function(e) {
+ if (! keyTimer) {
+ if (obj.search != obj.header.value.trim()) {
+ keyTimer = setTimeout(function() {
+ obj.find(obj.header.value.trim());
+ keyTimer = null;
+ }, 400);
+ }
+
+ if (! el.classList.contains('jdropdown-focus')) {
+ obj.open();
+ }
+ }
+ });
+ } else {
+ obj.header.setAttribute('readonly', 'readonly');
+ }
+
+ // Place holder
+ if (! obj.options.placeholder && el.getAttribute('placeholder')) {
+ obj.options.placeholder = el.getAttribute('placeholder');
+ }
+
+ if (obj.options.placeholder) {
+ obj.header.setAttribute('placeholder', obj.options.placeholder);
+ }
+
+ // Append elements
+ containerHeader.appendChild(obj.header);
+ if (obj.options.type == 'searchbar') {
+ containerHeader.appendChild(closeButton);
+ } else {
+ container.appendChild(closeButton);
+ }
+ if (! obj.options.type || obj.options.type == 'default') {
+ //containerHeader.appendChild(resetButton);
+ }
+ container.appendChild(content);
+ el.appendChild(containerHeader);
+ el.appendChild(container);
+ el.appendChild(backdrop);
+
+ var filter = function(a) {
+ return a.filter(function(v) {
+ return v;
+ });
+ }
+
+ /**
+ * Init dropdown
+ */
+ obj.init = function() {
+ if (obj.options.url && ! obj.options.data.length) {
+ jSuites.ajax({
+ url: obj.options.url,
+ method: 'GET',
+ dataType: 'json',
+ success: function(data) {
+ if (data) {
+ // Set data
+ obj.setData(data);
+ // Set value
+ if (obj.options.value != null) {
+ obj.setValue(obj.options.value);
+ }
+ // Onload method
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj, data);
+ }
+ }
+ }
+ });
+ } else {
+ var data = [];
+ if (obj.options.data.length) {
+ for (var j = 0; j < obj.options.data.length; j++) {
+ data.push(obj.options.data[j]);
+ }
+ }
+ // Set data
+ obj.setData(data);
+ // Set value
+ if (obj.options.value != null) {
+ obj.setValue(obj.options.value);
+ }
+ // Onload
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj, obj.options.data);
+ }
+ }
+
+ // Open dropdown
+ if (obj.options.opened == true) {
+ obj.open();
+ }
+ }
+
+ obj.getUrl = function() {
+ return obj.options.url;
+ }
+
+ obj.setUrl = function(url) {
+ obj.options.url = url;
+
+ jSuites.ajax({
+ url: obj.options.url,
+ method: 'GET',
+ dataType: 'json',
+ success: function(data) {
+ obj.setData(data);
+ }
+ });
+ }
+
+ /**
+ * Add a new item
+ */
+ obj.add = function(title) {
+ if (! title) {
+ var current = obj.options.autocomplete == true ? obj.header.value : '';
+ var title = prompt('Text', current);
+ if (! title) {
+ return false;
+ }
+ }
+
+ // Create new item
+ var item = {
+ value: jSuites.guid(),
+ text: title,
+ };
+
+ // Add item to the main list
+ obj.options.data.push(item);
+
+ var newItem = obj.createItem(item);
+
+ // Append DOM to the list
+ content.appendChild(newItem.element);
+
+ // Callback
+ if (typeof(obj.options.oninsert) == 'function') {
+ obj.options.oninsert(obj, newItem, item)
+ }
+
+ // Show content
+ if (content.style.display == 'none') {
+ content.style.display = '';
+ }
+
+ return item;
+ }
+
+ /**
+ * Create a new item
+ */
+ obj.createItem = function(data, group, groupName) {
+ if (typeof(data.text) == 'undefined' && data.name) {
+ data.text = data.name;
+ }
+ if (typeof(data.value) == 'undefined' && data.id) {
+ data.value = data.id;
+ }
+ // Create item
+ var item = {};
+ item.element = document.createElement('div');
+ item.element.className = 'jdropdown-item';
+ item.element.indexValue = obj.items.length;
+ item.value = data.value;
+ item.text = data.text;
+
+ // Id
+ if (data.id) {
+ item.element.setAttribute('id', data.id);
+ }
+
+ // Group reference
+ if (group) {
+ item.group = group;
+ item.groupName = groupName;
+ }
+
+ // Image
+ if (data.image) {
+ var image = document.createElement('img');
+ image.className = 'jdropdown-image';
+ image.src = data.image;
+ if (! data.title) {
+ image.classList.add('jdropdown-image-small');
+ }
+ item.element.appendChild(image);
+ } else if (data.color) {
+ var color = document.createElement('div');
+ color.className = 'jdropdown-color';
+ color.style.backgroundColor = data.color;
+ item.element.appendChild(color);
+ }
+
+ // Set content
+ var node = document.createElement('div');
+ node.className = 'jdropdown-description';
+ node.innerHTML = data.text || '&nbsp;';
+
+ // Title
+ if (data.title) {
+ var title = document.createElement('div');
+ title.className = 'jdropdown-title';
+ title.innerHTML = data.title;
+ node.appendChild(title);
+
+ // Keep text reference
+ item.title = data.title;
+ }
+
+ // Value
+ if (obj.value && obj.value[data.value]) {
+ item.element.classList.add('jdropdown-selected');
+ item.selected = true;
+ }
+
+ // Keep DOM accessible
+ obj.items.push(item);
+
+ // Add node to item
+ item.element.appendChild(node);
+
+ return item;
+ }
+
+ obj.appendData = function(data) {
+ // Create elements
+ if (data.length) {
+ // Reset counter
+ obj.numOfItems = 0;
+
+ // Helpers
+ var items = [];
+ var groups = [];
+
+ // Prepare data
+ for (var i = 0; i < data.length; i++) {
+ // Process groups
+ if (data[i].group) {
+ if (! groups[data[i].group]) {
+ groups[data[i].group] = [];
+ }
+ groups[data[i].group].push(i);
+ } else {
+ items.push(i);
+ }
+ }
+
+ // Groups
+ var groupNames = Object.keys(groups);
+
+ // Append groups in case exists
+ if (groupNames.length > 0) {
+ for (var i = 0; i < groupNames.length; i++) {
+ // Group container
+ var group = document.createElement('div');
+ group.className = 'jdropdown-group';
+ // Group name
+ var groupName = document.createElement('div');
+ groupName.className = 'jdropdown-group-name';
+ groupName.innerHTML = groupNames[i];
+ // Group arrow
+ var groupArrow = document.createElement('i');
+ groupArrow.className = 'jdropdown-group-arrow jdropdown-group-arrow-down';
+ groupName.appendChild(groupArrow);
+ // Group items
+ var groupContent = document.createElement('div');
+ groupContent.className = 'jdropdown-group-items';
+ for (var j = 0; j < groups[groupNames[i]].length; j++) {
+ var item = obj.createItem(data[groups[groupNames[i]][j]], group, groupNames[i]);
+
+ if (obj.options.lazyLoading == false || obj.numOfItems < 200) {
+ groupContent.appendChild(item.element);
+ obj.numOfItems++;
+ }
+ }
+ // Group itens
+ group.appendChild(groupName);
+ group.appendChild(groupContent);
+ // Keep group DOM
+ obj.groups.push(group);
+ // Only add to the screen if children on the group
+ if (groupContent.children.length > 0) {
+ // Add DOM to the content
+ content.appendChild(group);
+ }
+ }
+ }
+
+ if (items.length) {
+ for (var i = 0; i < items.length; i++) {
+ var item = obj.createItem(data[items[i]]);
+ if (obj.options.lazyLoading == false || obj.numOfItems < 200) {
+ content.appendChild(item.element);
+ obj.numOfItems++;
+ }
+ }
+ }
+ }
+ }
+
+ obj.setData = function(data) {
+ // Prepare data
+ if (data.length) {
+ for (var i = 0; i < data.length; i++) {
+ // Compatibility
+ if (typeof(data[i]) != 'object') {
+ // Correct format
+ data[i] = {
+ value: data[i],
+ text: data[i]
+ }
+ }
+ }
+
+ // Make sure the content container is blank
+ content.innerHTML = '';
+
+ // Reset
+ obj.reset();
+
+ // Reset items
+ obj.items = [];
+
+ // Append data
+ obj.appendData(data);
+ }
+
+ // Update data
+ obj.options.data = data;
+ }
+
+ /**
+ * Get position of the item
+ */
+ obj.getPosition = function(value) {
+ for (var i = 0; i < obj.items.length; i++) {
+ if (obj.items[i].value == value) {
+ return i;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Get dropdown current text
+ */
+ obj.getText = function(asArray) {
+ var v = [];
+ var k = Object.keys(obj.value);
+ for (var i = 0; i < k.length; i++) {
+ v.push(obj.value[k[i]]);
+ }
+ if (asArray) {
+ return v;
+ } else {
+ return v.join('; ');
+ }
+ }
+
+ /**
+ * Get dropdown current value
+ */
+ obj.getValue = function(asArray) {
+ if (asArray) {
+ return Object.keys(obj.value);
+ } else {
+ return Object.keys(obj.value).join(';');
+ }
+ }
+
+ obj.setValue = function(value) {
+ var setValue = function(item, value) {
+ if (obj.items[item].value == value) {
+ if (obj.items[item].element) {
+ obj.items[item].element.classList.add('jdropdown-selected');
+ }
+ obj.items[item].selected = true;
+
+ // Push to the values container
+ obj.value[value] = obj.items[item].text;
+ }
+ }
+
+ // Old value
+ var oldValue = obj.getValue();
+
+ // Remove selected
+ for (var i = 0; i < obj.items.length; i++) {
+ if (obj.items[i].selected == true) {
+ if (obj.items[i].element) {
+ obj.items[i].element.classList.remove('jdropdown-selected')
+ }
+ obj.items[i].selected = null;
+ }
+ }
+
+ // Reset
+ obj.value = [];
+
+ // Set values
+ if (value !== null) {
+ if (! Array.isArray(value)) {
+ for (var i = 0; i < obj.items.length; i++) {
+ setValue(i, value);
+ }
+ } else {
+ for (var i = 0; i < obj.items.length; i++) {
+ for (var j = 0; j < value.length; j++) {
+ setValue(i, value[j]);
+ }
+ }
+ }
+ }
+
+ // New value
+ var newValue = obj.getValue();
+
+ if (oldValue != newValue) {
+ // Label
+ obj.header.value = obj.getText();
+
+ // Value
+ obj.options.value = obj.getValue();
+
+ // Element value
+ el.value = obj.options.value;
+
+ // Events
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: this });
+ }
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, null, oldValue, obj.options.value);
+ }
+ }
+ }
+
+ obj.resetSelected = function() {
+ obj.setValue(null);
+ }
+
+ obj.selectIndex = function(index) {
+ // Make sure is a number
+ var index = parseInt(index);
+
+ // Only select those existing elements
+ if (obj.items && obj.items[index]) {
+ // Current selection
+ var oldValue = obj.getValue();
+
+ // Reset cursor to a new position
+ obj.setCursor(index, false);
+
+ // Behaviour
+ if (! obj.options.multiple) {
+ // Update value
+ if (! obj.value[obj.items[index].value]) {
+ obj.setValue(obj.items[index].value);
+ } else {
+ obj.setValue(null);
+ }
+ obj.close();
+ } else {
+ // Toggle option
+ if (obj.items[index].selected) {
+ obj.items[index].element.classList.remove('jdropdown-selected');
+ obj.items[index].selected = false;
+ // Remove from selected list
+ delete obj.value[obj.items[index].value];
+ } else {
+ // Select element
+ obj.items[index].element.classList.add('jdropdown-selected');
+ obj.items[index].selected = true;
+ // Add to the selected list
+ obj.value[obj.items[index].value] = obj.items[index].text;
+ }
+
+ // Update labels for multiple dropdown
+ if (! obj.options.autocomplete) {
+ obj.header.value = obj.getText();
+ }
+
+ // Events
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, index, oldValue, obj.getValue());
+ }
+ }
+ }
+ }
+
+ obj.selectItem = function(item) {
+ if (jSuites.dropdown.current) {
+ obj.selectIndex(item.indexValue);
+ }
+ }
+
+ obj.find = function(str) {
+ if (obj.search == str.trim()) {
+ return false;
+ }
+
+ // Search term
+ obj.search = str;
+
+ // Results
+ obj.numOfItems = 0;
+
+ // Remove current items in the remote search
+ if (obj.options.remoteSearch == true) {
+ obj.currentIndex = null;
+ obj.results = null;
+ jSuites.ajax({
+ url: obj.options.url + '?q=' + str,
+ method: 'GET',
+ dataType: 'json',
+ success: function(result) {
+ // Reset items
+ obj.items = [];
+ content.innerHTML = '';
+ obj.appendData(result);
+
+ if (! result.length) {
+ content.style.display = 'none';
+ } else {
+ content.style.display = '';
+ }
+ }
+ });
+ } else {
+ // Search terms
+ str = new RegExp(str, 'gi');
+
+ // Reset search
+ obj.results = [];
+
+ // Append options
+ for (var i = 0; i < obj.items.length; i++) {
+ // Item label
+ var label = obj.items[i].text;
+ // Item title
+ var title = obj.items[i].title || '';
+ // Group name
+ var groupName = obj.items[i].groupName || '';
+
+ if (str == null || obj.value[obj.items[i].value] != undefined || label.match(str) || title.match(str) || groupName.match(str)) {
+ obj.results.push(obj.items[i]);
+
+ if (obj.items[i].group && obj.items[i].group.children[1].children[0]) {
+ // Remove all nodes
+ while (obj.items[i].group.children[1].children[0]) {
+ obj.items[i].group.children[1].removeChild(obj.items[i].group.children[1].children[0]);
+ }
+ }
+ }
+ }
+
+ // Remove all nodes
+ while (content.children[0]) {
+ content.removeChild(content.children[0]);
+ }
+
+ // Show 200 items at once
+ var number = obj.results.length || 0;
+
+ // Lazyloading
+ if (obj.options.lazyLoading == true && number > 200) {
+ number = 200;
+ }
+
+ for (var i = 0; i < number; i++) {
+ if (obj.results[i].group) {
+ if (! obj.results[i].group.parentNode) {
+ content.appendChild(obj.results[i].group);
+ }
+ obj.results[i].group.children[1].appendChild(obj.results[i].element);
+ } else {
+ content.appendChild(obj.results[i].element);
+ }
+ obj.numOfItems++;
+ }
+
+ if (! obj.results.length) {
+ content.style.display = 'none';
+ } else {
+ content.style.display = '';
+ }
+ }
+ }
+
+ obj.open = function() {
+ if (jSuites.dropdown.current != el) {
+ if (jSuites.dropdown.current) {
+ jSuites.dropdown.current.dropdown.close();
+ }
+ jSuites.dropdown.current = el;
+ }
+
+ // Focus
+ if (! el.classList.contains('jdropdown-focus')) {
+ // Add focus
+ el.classList.add('jdropdown-focus');
+
+ // Animation
+ if (jSuites.getWindowWidth() < 800) {
+ if (obj.options.type == null || obj.options.type == 'picker') {
+ jSuites.animation.slideBottom(container, 1);
+ }
+ }
+
+ // Filter
+ if (obj.options.autocomplete == true) {
+ obj.header.value = obj.search;
+ obj.header.focus();
+ }
+
+ // Set cursor for the first or first selected element
+ var k = Object.keys(obj.value);
+ if (k[0]) {
+ var cursor = obj.getPosition(k[0]);
+ if (cursor) {
+ obj.setCursor(cursor);
+ }
+ }
+
+ // Container Size
+ if (! obj.options.type || obj.options.type == 'default') {
+ var rect = el.getBoundingClientRect();
+ var rectContainer = container.getBoundingClientRect();
+
+ if (obj.options.position) {
+ container.style.position = 'fixed';
+ if (window.innerHeight < rect.bottom + rectContainer.height) {
+ container.style.top = '';
+ container.style.bottom = (window.innerHeight - rect.top ) + 1 + 'px';
+ } else {
+ container.style.top = rect.bottom + 'px';
+ container.style.bottom = '';
+ }
+ container.style.left = rect.left + 'px';
+ } else {
+ if (window.innerHeight < rect.bottom + rectContainer.height) {
+ container.style.top = '';
+ container.style.bottom = rect.height + 1 + 'px';
+ } else {
+ container.style.top = '';
+ container.style.bottom = '';
+ }
+ }
+
+ container.style.minWidth = rect.width + 'px';
+
+ if (obj.options.maxWidth) {
+ container.style.maxWidth = obj.options.maxWidth;
+ }
+
+ if (! obj.items.length && obj.options.autocomplete == true) {
+ content.style.display = 'none';
+ } else {
+ content.style.display = '';
+ }
+ }
+ }
+
+ // Events
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el);
+ }
+ }
+
+ obj.close = function(ignoreEvents) {
+ if (jSuites.dropdown.current) {
+ // Remove controller
+ jSuites.dropdown.current = null
+ // Remove cursor
+ obj.setCursor();
+ // Update labels
+ obj.header.value = obj.getText();
+ // Events
+ if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el);
+ }
+ // Blur
+ if (obj.header.blur) {
+ obj.header.blur();
+ }
+ // Remove focus
+ el.classList.remove('jdropdown-focus');
+ }
+
+ return obj.getValue();
+ }
+
+ /**
+ * Set cursor
+ */
+ obj.setCursor = function(index, setPosition) {
+ // Remove current cursor
+ if (obj.currentIndex != null) {
+ // Remove visual cursor
+ if (obj.items && obj.items[obj.currentIndex]) {
+ obj.items[obj.currentIndex].element.classList.remove('jdropdown-cursor');
+ }
+ }
+
+ if (index == undefined) {
+ obj.currentIndex = null;
+ } else {
+ parseInt(index);
+
+ obj.items[index].element.classList.add('jdropdown-cursor');
+ obj.currentIndex = index;
+
+ // Update scroll to the cursor element
+ if (setPosition !== false && obj.items[obj.currentIndex].element) {
+ var container = content.scrollTop;
+ var element = obj.items[obj.currentIndex].element;
+ content.scrollTop = element.offsetTop - element.scrollTop + element.clientTop - 95;
+ }
+ }
+ }
+
+ // Compatibility
+ obj.resetCursor = obj.setCursor;
+ obj.updateCursor = obj.setCursor;
+
+ /**
+ * Reset cursor and selected items
+ */
+ obj.reset = function() {
+ // Reset cursor
+ obj.setCursor();
+
+ // Reset selected
+ obj.setValue(null);
+ }
+
+ /**
+ * First visible item
+ */
+ obj.firstVisible = function() {
+ var newIndex = null;
+ for (var i = 0; i < obj.items.length; i++) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') {
+ newIndex = i;
+ break;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ /**
+ * Navigation
+ */
+ obj.first = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex - 1; i >= 0; i--) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') {
+ newIndex = i;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.last = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex + 1; i < obj.items.length; i++) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') {
+ newIndex = i;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.next = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex + 1; i < obj.items.length; i++) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode) {
+ newIndex = i;
+ break;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.prev = function() {
+ var newIndex = null;
+ for (var i = obj.currentIndex - 1; i >= 0; i--) {
+ if (obj.items && obj.items[i] && obj.items[i].element.parentNode) {
+ newIndex = i;
+ break;
+ }
+ }
+
+ if (newIndex == null) {
+ return false;
+ }
+
+ obj.setCursor(newIndex);
+ }
+
+ obj.loadUp = function() {
+ return false;
+ }
+
+ obj.loadDown = function() {
+ var test = false;
+
+ // Search
+ if (obj.results) {
+ var results = obj.results;
+ } else {
+ var results = obj.items;
+ }
+
+ if (results.length > obj.numOfItems) {
+ var numberOfItems = obj.numOfItems;
+ var number = results.length - numberOfItems;
+ if (number > 200) {
+ number = 200;
+ }
+
+ for (var i = numberOfItems; i < numberOfItems + number; i++) {
+ if (results[i].group) {
+ if (! results[i].group.parentNode) {
+ content.appendChild(results[i].group);
+ }
+ results[i].group.children[2].appendChild(results[i].element);
+ } else {
+ content.appendChild(results[i].element);
+ }
+
+ obj.numOfItems++;
+ }
+
+ // New item added
+ test = true;
+ }
+
+ return test;
+ }
+
+ if (! jSuites.dropdown.hasEvents) {
+ if ('ontouchsend' in document.documentElement === true) {
+ document.addEventListener('touchsend', jSuites.dropdown.mouseup);
+ } else {
+ document.addEventListener('mouseup', jSuites.dropdown.mouseup);
+ }
+ document.addEventListener('keydown', jSuites.dropdown.onkeydown);
+
+ jSuites.dropdown.hasEvents = true;
+ }
+
+ // Lazyloading
+ if (obj.options.lazyLoading == true) {
+ jSuites.lazyLoading(content, {
+ loadUp: obj.loadUp,
+ loadDown: obj.loadDown,
+ });
+ }
+
+ // Start dropdown
+ obj.init();
+
+ // Keep object available from the node
+ el.dropdown = obj;
+ el.change = obj.setValue;
+
+ return obj;
+});
+
+jSuites.dropdown.hasEvents = false;
+
+jSuites.dropdown.mouseup = function(e) {
+ var element = jSuites.findElement(e.target, 'jdropdown');
+ if (element) {
+ var dropdown = element.dropdown;
+ if (e.target.classList.contains('jdropdown-header')) {
+ if (element.classList.contains('jdropdown-focus') && element.classList.contains('jdropdown-default')) {
+ var rect = element.getBoundingClientRect();
+
+ if (e.changedTouches && e.changedTouches[0]) {
+ var x = e.changedTouches[0].clientX;
+ var y = e.changedTouches[0].clientY;
+ } else {
+ var x = e.clientX;
+ var y = e.clientY;
+ }
+
+ if (rect.width - (x - rect.left) < 30) {
+ if (e.target.classList.contains('jdropdown-add')) {
+ dropdown.add();
+ } else {
+ dropdown.close();
+ }
+ } else {
+ if (dropdown.options.autocomplete == false) {
+ dropdown.close();
+ }
+ }
+ } else {
+ dropdown.open();
+ }
+ } else if (e.target.classList.contains('jdropdown-group-name')) {
+ var items = e.target.nextSibling.children;
+ if (e.target.nextSibling.style.display != 'none') {
+ for (var i = 0; i < items.length; i++) {
+ if (items[i].style.display != 'none') {
+ dropdown.selectItem(items[i]);
+ }
+ }
+ }
+ } else if (e.target.classList.contains('jdropdown-group-arrow')) {
+ if (e.target.classList.contains('jdropdown-group-arrow-down')) {
+ e.target.classList.remove('jdropdown-group-arrow-down');
+ e.target.classList.add('jdropdown-group-arrow-up');
+ e.target.parentNode.nextSibling.style.display = 'none';
+ } else {
+ e.target.classList.remove('jdropdown-group-arrow-up');
+ e.target.classList.add('jdropdown-group-arrow-down');
+ e.target.parentNode.nextSibling.style.display = '';
+ }
+ } else if (e.target.classList.contains('jdropdown-item')) {
+ dropdown.selectItem(e.target);
+ } else if (e.target.classList.contains('jdropdown-image')) {
+ dropdown.selectItem(e.target.parentNode);
+ } else if (e.target.classList.contains('jdropdown-description')) {
+ dropdown.selectItem(e.target.parentNode);
+ } else if (e.target.classList.contains('jdropdown-title')) {
+ dropdown.selectItem(e.target.parentNode.parentNode);
+ } else if (e.target.classList.contains('jdropdown-close') || e.target.classList.contains('jdropdown-backdrop')) {
+ dropdown.close();
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+ } else {
+ if (jSuites.dropdown.current) {
+ jSuites.dropdown.current.dropdown.close();
+ }
+ }
+}
+
+// Keydown controls
+jSuites.dropdown.onkeydown = function(e) {
+ if (jSuites.dropdown.current) {
+ // Element
+ var element = jSuites.dropdown.current.dropdown;
+ // Index
+ var index = element.currentIndex;
+
+ if (! e.shiftKey) {
+ if (e.which == 13 || e.which == 27 || e.which == 35 || e.which == 36 || e.which == 38 || e.which == 40) {
+ // Move cursor
+ if (e.which == 13) {
+ element.selectIndex(index);
+ } else if (e.which == 38) {
+ if (index == null) {
+ element.firstVisible();
+ } else if (index > 0) {
+ element.prev();
+ }
+ } else if (e.which == 40) {
+ if (index == null) {
+ element.firstVisible();
+ } else if (index + 1 < element.items.length) {
+ element.next();
+ }
+ } else if (e.which == 36) {
+ element.first();
+ } else if (e.which == 35) {
+ element.last();
+ } else if (e.which == 27) {
+ element.close();
+ }
+
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ }
+}
+
+jSuites.dropdown.extractFromDom = function(el, options) {
+ // Keep reference
+ var select = el;
+ if (! options) {
+ options = {};
+ }
+ // Prepare configuration
+ if (el.getAttribute('multiple') && (! options || options.multiple == undefined)) {
+ options.multiple = true;
+ }
+ if (el.getAttribute('placeholder') && (! options || options.placeholder == undefined)) {
+ options.placeholder = el.getAttribute('placeholder');
+ }
+ if (el.getAttribute('data-autocomplete') && (! options || options.autocomplete == undefined)) {
+ options.autocomplete = true;
+ }
+ if (! options || options.width == undefined) {
+ options.width = el.offsetWidth;
+ }
+ if (el.value && (! options || options.value == undefined)) {
+ options.value = el.value;
+ }
+ if (! options || options.data == undefined) {
+ options.data = [];
+ for (var j = 0; j < el.children.length; j++) {
+ if (el.children[j].tagName == 'OPTGROUP') {
+ for (var i = 0; i < el.children[j].children.length; i++) {
+ options.data.push({
+ value: el.children[j].children[i].value,
+ text: el.children[j].children[i].innerHTML,
+ group: el.children[j].getAttribute('label'),
+ });
+ }
+ } else {
+ options.data.push({
+ value: el.children[j].value,
+ text: el.children[j].innerHTML,
+ });
+ }
+ }
+ }
+ if (! options || options.onchange == undefined) {
+ options.onchange = function(a,b,c,d) {
+ if (options.multiple == true) {
+ if (obj.items[b].classList.contains('jdropdown-selected')) {
+ select.options[b].setAttribute('selected', 'selected');
+ } else {
+ select.options[b].removeAttribute('selected');
+ }
+ } else {
+ select.value = d;
+ }
+ }
+ }
+ // Create DIV
+ var div = document.createElement('div');
+ el.parentNode.insertBefore(div, el);
+ el.style.display = 'none';
+ el = div;
+
+ return { el:el, options:options };
+}
+
+/**
+ * (c) HTML Editor
+ * https://github.com/paulhodel/jsuites
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Inline simple richtext editor
+ */
+
+jSuites.editor = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // If element is textarea, then replace by div editor
+ if (el.tagName == 'TEXTAREA' || el.tagName == 'INPUT') {
+ // Current element
+ var element = el;
+ element.style.display = 'none';
+ // New Element
+ el = document.createElement('div');
+ // Value
+ if (! options.value) {
+ options.value = element.value;
+ }
+ // Event to populate the textarea
+ options.onblur = function(a,b,c) {
+ element.value = b.getData()
+ }
+ element.insertBefore(el);
+ }
+
+ // Default configuration
+ var defaults = {
+ // Initial HTML content
+ value: null,
+ // Initial snippet
+ snippet: null,
+ // Add toolbar
+ toolbar: null,
+ // Website parser is to read websites and images from cross domain
+ remoteParser: null,
+ // Parse URL
+ parseURL: false,
+ // Accept drop files
+ dropZone: false,
+ dropAsAttachment: false,
+ acceptImages: false,
+ acceptFiles: false,
+ maxFileSize: 5000000,
+ allowImageResize: true,
+ // Style
+ border: true,
+ padding: true,
+ maxHeight: null,
+ focus: false,
+ // Events
+ onclick: null,
+ onfocus: null,
+ onblur: null,
+ onload: null,
+ onkeyup: null,
+ onkeydown: null,
+ onchange: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Private controllers
+ var imageResize = 0;
+ var editorTimer = null;
+ var editorAction = null;
+
+ // Make sure element is empty
+ el.innerHTML = '';
+
+ // Change method
+ el.change = obj.setValue;
+
+ if (typeof(obj.options.onclick) == 'function') {
+ el.onclick = function(e) {
+ obj.options.onclick(el, obj, e);
+ }
+ }
+
+ // Prepare container
+ el.classList.add('jeditor-container');
+
+ // Padding
+ if (obj.options.padding == true) {
+ el.classList.add('jeditor-padding');
+ }
+
+ // Border
+ if (obj.options.border == false) {
+ el.style.border = '0px';
+ }
+
+ // Snippet
+ var snippet = document.createElement('div');
+ snippet.className = 'jsnippet';
+ snippet.setAttribute('contenteditable', false);
+
+ // Toolbar
+ var toolbar = document.createElement('div');
+ toolbar.className = 'jeditor-toolbar';
+
+ // Create editor
+ var editor = document.createElement('div');
+ editor.setAttribute('contenteditable', true);
+ editor.setAttribute('spellcheck', false);
+ editor.className = 'jeditor';
+
+ // Max height
+ if (obj.options.maxHeight) {
+ editor.style.overflowY = 'auto';
+ editor.style.maxHeight = obj.options.maxHeight;
+ }
+
+ // Set editor initial value
+ if (obj.options.value) {
+ var value = obj.options.value;
+ } else {
+ var value = el.innerHTML ? el.innerHTML : '';
+ }
+
+ if (! value) {
+ var value = '<br>';
+ }
+
+ /**
+ * Onchange event controllers
+ */
+ var change = function() {
+ // Events
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: el });
+ }
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, obj, e);
+ }
+ }
+
+ /**
+ * Extract images from a HTML string
+ */
+ var extractImageFromHtml = function(html) {
+ // Create temp element
+ var div = document.createElement('div');
+ div.innerHTML = html;
+
+ // Extract images
+ var img = div.querySelectorAll('img');
+
+ if (img.length) {
+ for (var i = 0; i < img.length; i++) {
+ obj.addImage(img[i].src);
+ }
+ }
+ }
+
+ /**
+ * Insert node at caret
+ */
+ var insertNodeAtCaret = function(newNode) {
+ var sel, range;
+
+ if (window.getSelection) {
+ sel = window.getSelection();
+ if (sel.rangeCount) {
+ range = sel.getRangeAt(0);
+ var selectedText = range.toString();
+ range.deleteContents();
+ range.insertNode(newNode);
+ // move the cursor after element
+ range.setStartAfter(newNode);
+ range.setEndAfter(newNode);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+ }
+
+ /**
+ * Append snippet or thumbs in the editor
+ * @Param object data
+ */
+ var appendElement = function(data) {
+ // Reset snippet
+ snippet.innerHTML = '';
+
+ if (data.image) {
+ var div = document.createElement('div');
+ div.className = 'jsnippet-image';
+ div.setAttribute('data-k', 'image');
+ snippet.appendChild(div);
+
+ var image = document.createElement('img');
+ image.src = data.image;
+ div.appendChild(image);
+ }
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-title';
+ div.setAttribute('data-k', 'title');
+ div.innerHTML = data.title;
+ snippet.appendChild(div);
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-description';
+ div.setAttribute('data-k', 'description');
+ div.innerHTML = data.description;
+ snippet.appendChild(div);
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-host';
+ div.setAttribute('data-k', 'host');
+ div.innerHTML = data.host;
+ snippet.appendChild(div);
+
+ var div = document.createElement('div');
+ div.className = 'jsnippet-url';
+ div.setAttribute('data-k', 'url');
+ div.innerHTML = data.url;
+ snippet.appendChild(div);
+
+ editor.appendChild(snippet);
+ }
+
+ var verifyEditor = function() {
+ clearTimeout(editorTimer);
+ editorTimer = setTimeout(function() {
+ var snippet = editor.querySelector('.jsnippet');
+ var thumbsContainer = el.querySelector('.jeditor-thumbs-container');
+
+ if (! snippet && ! thumbsContainer) {
+ var html = editor.innerHTML.replace(/\n/g, ' ');
+ var container = document.createElement('div');
+ container.innerHTML = html;
+ var thumbsContainer = container.querySelector('.jeditor-thumbs-container');
+ if (thumbsContainer) {
+ thumbsContainer.remove();
+ }
+ var text = container.innerText;
+ var url = jSuites.editor.detectUrl(text);
+
+ if (url) {
+ if (url[0].substr(-3) == 'jpg' || url[0].substr(-3) == 'png' || url[0].substr(-3) == 'gif') {
+ if (jSuites.editor.getDomain(url[0]) == window.location.hostname) {
+ obj.importImage(url[0], '');
+ } else {
+ obj.importImage(obj.options.remoteParser + url[0], '');
+ }
+ } else {
+ var id = jSuites.editor.youtubeParser(url[0]);
+ obj.parseWebsite(url[0], id);
+ }
+ }
+ }
+ }, 1000);
+ }
+
+ obj.parseContent = function() {
+ verifyEditor();
+ }
+
+ obj.parseWebsite = function(url, youtubeId) {
+ if (! obj.options.remoteParser) {
+ console.log('The remoteParser is not defined');
+ } else {
+ // Youtube definitions
+ if (youtubeId) {
+ var url = 'https://www.youtube.com/watch?v=' + youtubeId;
+ }
+
+ var p = {
+ title: '',
+ description: '',
+ image: '',
+ host: url.split('/')[2],
+ url: url,
+ }
+
+ jSuites.ajax({
+ url: obj.options.remoteParser + encodeURI(url.trim()),
+ method: 'GET',
+ dataType: 'json',
+ success: function(result) {
+ // Get title
+ if (result.title) {
+ p.title = result.title;
+ }
+ // Description
+ if (result.description) {
+ p.description = result.description;
+ }
+ // Image
+ if (result.image) {
+ p.image = result.image;
+ } else if (result['og:image']) {
+ p.image = result['og:image'];
+ }
+ // Host
+ if (result.host) {
+ p.host = result.host;
+ }
+ // Url
+ if (result.url) {
+ p.url = result.url;
+ }
+
+ appendElement(p);
+ }
+ });
+ }
+ }
+
+ /**
+ * Set editor value
+ */
+ obj.setData = function(html) {
+ editor.innerHTML = html;
+ jSuites.editor.setCursor(editor, true);
+ }
+
+ obj.setValue = obj.setData;
+
+ obj.getText = function() {
+ return editor.innerText;
+ }
+
+ /**
+ * Get editor data
+ */
+ obj.getData = function(json) {
+ if (! json) {
+ var data = editor.innerHTML;
+ } else {
+ var data = {
+ content : '',
+ }
+
+ // Get tag users
+ var tagged = editor.querySelectorAll('.post-tag');
+ if (tagged.length) {
+ data.users = [];
+ for (var i = 0; i < tagged.length; i++) {
+ var userId = tagged[i].getAttribute('data-user');
+ if (userId) {
+ data.users.push(userId);
+ }
+ }
+ data.users = data.users.join(',');
+ }
+
+ if (snippet.innerHTML) {
+ var index = 0;
+ data.snippet = {};
+ for (var i = 0; i < snippet.children.length; i++) {
+ // Get key from element
+ var key = snippet.children[i].getAttribute('data-k');
+ if (key) {
+ if (key == 'image') {
+ data.snippet.image = snippet.children[i].children[0].getAttribute('src');
+ } else {
+ data.snippet[key] = snippet.children[i].innerHTML;
+ }
+ }
+ }
+
+ snippet.innerHTML = '';
+ snippet.remove();
+ }
+
+ var text = editor.innerHTML;
+ text = text.replace(/<br>/g, "\n");
+ text = text.replace(/<\/div>/g, "<\/div>\n");
+ text = text.replace(/<(?:.|\n)*?>/gm, "");
+ data.content = text.trim();
+ data = JSON.stringify(data);
+ }
+
+ return data;
+ }
+
+ // Reset
+ obj.reset = function() {
+ editor.innerHTML = '';
+ }
+
+ obj.addPdf = function(data) {
+ if (data.result.substr(0,4) != 'data') {
+ console.error('Invalid source');
+ } else {
+ var canvas = document.createElement('canvas');
+ canvas.width = 60;
+ canvas.height = 60;
+
+ var img = new Image();
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ canvas.toBlob(function(blob) {
+ var newImage = document.createElement('img');
+ newImage.src = window.URL.createObjectURL(blob);
+ newImage.setAttribute('data-extension', 'pdf');
+ if (data.name) {
+ newImage.setAttribute('data-name', data.name);
+ }
+ if (data.size) {
+ newImage.setAttribute('data-size', data.size);
+ }
+ if (data.date) {
+ newImage.setAttribute('data-date', data.date);
+ }
+ newImage.className = 'jfile pdf';
+
+ insertNodeAtCaret(newImage);
+
+ // Image content
+ newImage.content = data.result.substr(data.result.indexOf(',') + 1);
+ });
+ }
+ }
+
+ obj.getFiles = function() {
+ return jSuites.files(editor).get();
+ }
+
+ obj.addImage = function(src, name, size, date) {
+ if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
+ console.error('remoteParser not defined in your initialization');
+ } else {
+ // This is to process cross domain images
+ if (src.substr(0,4) == 'data') {
+ var extension = src.split(';')
+ extension = extension[0].split('/');
+ extension = extension[1];
+ } else {
+ var extension = src.substr(src.lastIndexOf('.') + 1);
+ // Work for cross browsers
+ src = obj.options.remoteParser + src;
+ }
+
+ var img = new Image();
+
+ img.onload = function onload() {
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ canvas.toBlob(function(blob) {
+ var newImage = document.createElement('img');
+ newImage.src = window.URL.createObjectURL(blob);
+ newImage.setAttribute('tabindex', '900');
+ newImage.setAttribute('data-extension', extension);
+ if (name) {
+ newImage.setAttribute('data-name', name);
+ }
+ if (size) {
+ newImage.setAttribute('data-size', size);
+ }
+ if (date) {
+ newImage.setAttribute('data-date', date);
+ }
+ newImage.className = 'jfile';
+ var content = canvas.toDataURL();
+ insertNodeAtCaret(newImage);
+
+ // Image content
+ newImage.content = content.substr(content.indexOf(',') + 1);
+
+ change();
+ });
+ };
+
+ img.src = src;
+ }
+ }
+
+ obj.addFile = function(files) {
+ var reader = [];
+
+ for (var i = 0; i < files.length; i++) {
+ if (files[i].size > obj.options.maxFileSize) {
+ alert('The file is too big');
+ } else {
+ // Only PDF or Images
+ var type = files[i].type.split('/');
+
+ if (type[0] == 'image') {
+ type = 1;
+ } else if (type[1] == 'pdf') {
+ type = 2;
+ } else {
+ type = 0;
+ }
+
+ if (type) {
+ // Create file
+ reader[i] = new FileReader();
+ reader[i].index = i;
+ reader[i].type = type;
+ reader[i].name = files[i].name;
+ reader[i].date = files[i].lastModified;
+ reader[i].size = files[i].size;
+ reader[i].addEventListener("load", function (data) {
+ // Get result
+ if (data.target.type == 2) {
+ if (obj.options.acceptFiles == true) {
+ obj.addPdf(data.target);
+ }
+ } else {
+ obj.addImage(data.target.result, data.target.name, data.total, data.target.lastModified);
+ }
+ }, false);
+
+ reader[i].readAsDataURL(files[i])
+ } else {
+ alert('The extension is not allowed');
+ }
+ }
+ }
+ }
+
+ // Destroy
+ obj.destroy = function() {
+ editor.removeEventListener('mouseup', editorMouseUp);
+ editor.removeEventListener('mousedown', editorMouseDown);
+ editor.removeEventListener('mousemove', editorMouseMove);
+ editor.removeEventListener('keyup', editorKeyUp);
+ editor.removeEventListener('keydown', editorKeyDown);
+ editor.removeEventListener('dragstart', editorDragStart);
+ editor.removeEventListener('dragenter', editorDragEnter);
+ editor.removeEventListener('dragover', editorDragOver);
+ editor.removeEventListener('drop', editorDrop);
+ editor.removeEventListener('paste', editorPaste);
+
+ if (typeof(obj.options.onblur) == 'function') {
+ editor.removeEventListener('blur', editorBlur);
+ }
+ if (typeof(obj.options.onfocus) == 'function') {
+ editor.removeEventListener('focus', editorFocus);
+ }
+
+ el.editor = null;
+ el.classList.remove('jeditor-container');
+
+ toolbar.remove();
+ snippet.remove();
+ editor.remove();
+ }
+
+ var isLetter = function (str) {
+ var regex = /([\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]+)/g;
+ return str.match(regex) ? 1 : 0;
+ }
+
+ // Event handlers
+ var editorMouseUp = function(e) {
+ editorAction = false;
+ }
+
+ var editorMouseDown = function(e) {
+ var close = function(snippet) {
+ var rect = snippet.getBoundingClientRect();
+ if (rect.width - (e.clientX - rect.left) < 40 && e.clientY - rect.top < 40) {
+ snippet.innerHTML = '';
+ snippet.remove();
+ }
+ }
+
+ if (e.target.tagName == 'IMG') {
+ if (e.target.style.cursor) {
+ var rect = e.target.getBoundingClientRect();
+ editorAction = {
+ e: e.target,
+ x: e.clientX,
+ y: e.clientY,
+ w: rect.width,
+ h: rect.height,
+ d: e.target.style.cursor,
+ }
+
+ if (! e.target.style.width) {
+ e.target.style.width = rect.width + 'px';
+ }
+
+ if (! e.target.style.height) {
+ e.target.style.height = rect.height + 'px';
+ }
+
+ var s = window.getSelection();
+ if (s.rangeCount) {
+ for (var i = 0; i < s.rangeCount; i++) {
+ s.removeRange(s.getRangeAt(i));
+ }
+ }
+ } else {
+ editorAction = true;
+ }
+ } else {
+ if (e.target.classList.contains('jsnippet')) {
+ close(e.target);
+ } else if (e.target.parentNode.classList.contains('jsnippet')) {
+ close(e.target.parentNode);
+ }
+
+ editorAction = true;
+ }
+ }
+
+ var editorMouseMove = function(e) {
+ if (e.target.tagName == 'IMG' && obj.options.allowImageResize == true) {
+ if (e.target.getAttribute('tabindex')) {
+ var rect = e.target.getBoundingClientRect();
+ if (e.clientY - rect.top < 5) {
+ if (rect.width - (e.clientX - rect.left) < 5) {
+ e.target.style.cursor = 'ne-resize';
+ } else if (e.clientX - rect.left < 5) {
+ e.target.style.cursor = 'nw-resize';
+ } else {
+ e.target.style.cursor = 'n-resize';
+ }
+ } else if (rect.height - (e.clientY - rect.top) < 5) {
+ if (rect.width - (e.clientX - rect.left) < 5) {
+ e.target.style.cursor = 'se-resize';
+ } else if (e.clientX - rect.left < 5) {
+ e.target.style.cursor = 'sw-resize';
+ } else {
+ e.target.style.cursor = 's-resize';
+ }
+ } else if (rect.width - (e.clientX - rect.left) < 5) {
+ e.target.style.cursor = 'e-resize';
+ } else if (e.clientX - rect.left < 5) {
+ e.target.style.cursor = 'w-resize';
+ } else {
+ e.target.style.cursor = '';
+ }
+ }
+ }
+
+ // Move
+ if (e.which == 1 && editorAction && editorAction.d) {
+ if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') {
+ editorAction.e.style.width = (editorAction.w + (e.clientX - editorAction.x)) + 'px';
+
+ if (e.shiftKey) {
+ var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w);
+ editorAction.e.style.height = editorAction.h + newHeight + 'px';
+ } else {
+ var newHeight = null;
+ }
+ }
+
+ if (! newHeight) {
+ if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') {
+ if (! e.shiftKey) {
+ editorAction.e.style.height = editorAction.h + (e.clientY - editorAction.y) + 'px';
+ }
+ }
+ }
+ }
+ }
+
+ var editorKeyUp = function(e) {
+ if (! editor.innerHTML) {
+ editor.innerHTML = '<div><br></div>';
+ }
+
+ if (typeof(obj.options.onkeyup) == 'function') {
+ obj.options.onkeyup(el, obj, e);
+ }
+
+ change(e);
+ }
+
+
+ var editorKeyDown = function(e) {
+ // Check for URL
+ if (obj.options.parseURL == true) {
+ verifyEditor();
+ }
+
+ if (typeof(obj.options.onkeydown) == 'function') {
+ obj.options.onkeydown(el, obj, e);
+ }
+ }
+
+ var editorPaste = function(e) {
+ if (e.clipboardData || e.originalEvent.clipboardData) {
+ var html = (e.originalEvent || e).clipboardData.getData('text/html');
+ var text = (e.originalEvent || e).clipboardData.getData('text/plain');
+ var file = (e.originalEvent || e).clipboardData.files
+ } else if (window.clipboardData) {
+ var html = window.clipboardData.getData('Html');
+ var text = window.clipboardData.getData('Text');
+ var file = window.clipboardData.files
+ }
+
+ if (file.length) {
+ // Paste a image from the clipboard
+ obj.addFile(file);
+ } else {
+ // Paste text
+ text = text.split('\r\n');
+ var str = '';
+ if (e.target.nodeName == 'DIV' && e.target.classList.contains('jeditor')) {
+ for (var i = 0; i < text.length; i++) {
+ var tmp = document.createElement('div');
+ if (text[i]) {
+ tmp.innerHTML = text[i];
+ } else {
+ tmp.innerHTML = '<br/>';
+ }
+ e.target.appendChild(tmp);
+ }
+ } else {
+ for (var i = 0; i < text.length; i++) {
+ if (text[i]) {
+ str += '<div>' + text[i] + "</div>\r\n";
+ }
+ }
+ // Insert text
+ document.execCommand('insertHtml', false, str);
+ }
+
+ // Extra images from the paste
+ if (obj.options.acceptImages == true) {
+ extractImageFromHtml(html);
+ }
+ }
+
+ e.preventDefault();
+ }
+
+ var editorDragStart = function(e) {
+ if (editorAction && editorAction.e) {
+ e.preventDefault();
+ }
+ }
+
+ var editorDragEnter = function(e) {
+ if (editorAction || obj.options.dropZone == false) {
+ // Do nothing
+ } else {
+ el.classList.add('jeditor-dragging');
+ }
+ }
+
+ var editorDragOver = function(e) {
+ if (editorAction || obj.options.dropZone == false) {
+ // Do nothing
+ } else {
+ if (editorTimer) {
+ clearTimeout(editorTimer);
+ }
+
+ editorTimer = setTimeout(function() {
+ el.classList.remove('jeditor-dragging');
+ }, 100);
+ }
+ }
+
+ var editorDrop = function(e) {
+ if (editorAction || obj.options.dropZone == false) {
+ // Do nothing
+ } else {
+ // Position caret on the drop
+ var range = null;
+ if (document.caretRangeFromPoint) {
+ range=document.caretRangeFromPoint(e.clientX, e.clientY);
+ } else if (e.rangeParent) {
+ range=document.createRange();
+ range.setStart(e.rangeParent,e.rangeOffset);
+ }
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ sel.anchorNode.parentNode.focus();
+
+ var html = (e.originalEvent || e).dataTransfer.getData('text/html');
+ var text = (e.originalEvent || e).dataTransfer.getData('text/plain');
+ var file = (e.originalEvent || e).dataTransfer.files;
+
+ if (file.length) {
+ obj.addFile(file);
+ } else if (text) {
+ extractImageFromHtml(html);
+ }
+
+ el.classList.remove('jeditor-dragging');
+ e.preventDefault();
+ }
+ }
+
+ var editorBlur = function(e) {
+ obj.options.onblur(el, obj, e);
+ }
+
+ var editorFocus = function(e) {
+ obj.options.onfocus(el, obj, e);
+ }
+
+ editor.addEventListener('mouseup', editorMouseUp);
+ editor.addEventListener('mousedown', editorMouseDown);
+ editor.addEventListener('mousemove', editorMouseMove);
+ editor.addEventListener('keyup', editorKeyUp);
+ editor.addEventListener('keydown', editorKeyDown);
+ editor.addEventListener('dragstart', editorDragStart);
+ editor.addEventListener('dragenter', editorDragEnter);
+ editor.addEventListener('dragover', editorDragOver);
+ editor.addEventListener('drop', editorDrop);
+ editor.addEventListener('paste', editorPaste);
+
+ // Blur
+ if (typeof(obj.options.onblur) == 'function') {
+ editor.addEventListener('blur', editorBlur);
+ }
+
+ // Focus
+ if (typeof(obj.options.onfocus) == 'function') {
+ editor.addEventListener('focus', editorFocus);
+ }
+
+ // Onload
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj, editor);
+ }
+
+ // Set value to the editor
+ editor.innerHTML = value;
+
+ // Append editor to the containre
+ el.appendChild(editor);
+
+ // Snippet
+ if (obj.options.snippet) {
+ appendElement(obj.options.snippet);
+ }
+
+ // Default toolbar
+ if (obj.options.toolbar == null) {
+ obj.options.toolbar = jSuites.editor.getDefaultToolbar();
+ }
+
+ // Add toolbar
+ if (obj.options.toolbar) {
+ // Create toolbar
+ jSuites.toolbar(toolbar, {
+ container: true,
+ items: obj.options.toolbar
+ });
+ // Append to the DOM
+ el.appendChild(toolbar);
+ }
+
+ // Focus to the editor
+ if (obj.options.focus) {
+ jSuites.editor.setCursor(editor, obj.options.focus == 'initial' ? true : false);
+ }
+
+ el.editor = obj;
+
+ return obj;
+});
+
+jSuites.editor.setCursor = function(element, first) {
+ element.focus();
+ document.execCommand('selectAll');
+ var sel = window.getSelection();
+ var range = sel.getRangeAt(0);
+ if (first == true) {
+ var node = range.startContainer;
+ var size = 0;
+ } else {
+ var node = range.endContainer;
+ var size = node.length;
+ }
+ range.setStart(node, size);
+ range.setEnd(node, size);
+ sel.removeAllRanges();
+ sel.addRange(range);
+}
+
+jSuites.editor.getDomain = function(url) {
+ return url.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0].split(/:/g)[0];
+}
+
+jSuites.editor.detectUrl = function(text) {
+ var expression = /(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig;
+ var links = text.match(expression);
+
+ if (links) {
+ if (links[0].substr(0,3) == 'www') {
+ links[0] = 'http://' + links[0];
+ }
+ }
+
+ return links;
+}
+
+jSuites.editor.youtubeParser = function(url) {
+ var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/;
+ var match = url.match(regExp);
+
+ return (match && match[7].length == 11) ? match[7] : false;
+}
+
+jSuites.editor.getDefaultToolbar = function() {
+ return [
+ {
+ content: 'undo',
+ onclick: function() {
+ document.execCommand('undo');
+ }
+ },
+ {
+ content: 'redo',
+ onclick: function() {
+ document.execCommand('redo');
+ }
+ },
+ {
+ type:'divisor'
+ },
+ {
+ content: 'format_bold',
+ onclick: function(a,b,c) {
+ document.execCommand('bold');
+
+ if (document.queryCommandState("bold")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_italic',
+ onclick: function(a,b,c) {
+ document.execCommand('italic');
+
+ if (document.queryCommandState("italic")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_underline',
+ onclick: function(a,b,c) {
+ document.execCommand('underline');
+
+ if (document.queryCommandState("underline")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ type:'divisor'
+ },
+ {
+ content: 'format_list_bulleted',
+ onclick: function(a,b,c) {
+ document.execCommand('insertUnorderedList');
+
+ if (document.queryCommandState("insertUnorderedList")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_list_numbered',
+ onclick: function(a,b,c) {
+ document.execCommand('insertOrderedList');
+
+ if (document.queryCommandState("insertOrderedList")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_indent_increase',
+ onclick: function(a,b,c) {
+ document.execCommand('indent', true, null);
+
+ if (document.queryCommandState("indent")) {
+ c.classList.add('selected');
+ } else {
+ c.classList.remove('selected');
+ }
+ }
+ },
+ {
+ content: 'format_indent_decrease',
+ onclick: function() {
+ document.execCommand('outdent');
+
+ if (document.queryCommandState("outdent")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ }/*,
+ {
+ icon: ['format_align_left', 'format_align_right', 'format_align_center'],
+ onclick: function() {
+ document.execCommand('justifyCenter');
+
+ if (document.queryCommandState("justifyCenter")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ }
+ {
+ type:'select',
+ items: ['Verdana','Arial','Courier New'],
+ onchange: function() {
+ }
+ },
+ {
+ type:'select',
+ items: ['10px','12px','14px','16px','18px','20px','22px'],
+ onchange: function() {
+ }
+ },
+ {
+ icon:'format_align_left',
+ onclick: function() {
+ document.execCommand('JustifyLeft');
+
+ if (document.queryCommandState("JustifyLeft")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_align_center',
+ onclick: function() {
+ document.execCommand('justifyCenter');
+
+ if (document.queryCommandState("justifyCenter")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_align_right',
+ onclick: function() {
+ document.execCommand('justifyRight');
+
+ if (document.queryCommandState("justifyRight")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_align_justify',
+ onclick: function() {
+ document.execCommand('justifyFull');
+
+ if (document.queryCommandState("justifyFull")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ },
+ {
+ icon:'format_list_bulleted',
+ onclick: function() {
+ document.execCommand('insertUnorderedList');
+
+ if (document.queryCommandState("insertUnorderedList")) {
+ this.classList.add('selected');
+ } else {
+ this.classList.remove('selected');
+ }
+ }
+ }*/
+ ];
+}
+
+
+jSuites.files = (function(element) {
+ if (! element) {
+ console.error('No element defined in the arguments of your method');
+ }
+
+ var obj = {};
+ obj.files = [];
+ obj.get = function() {
+ return obj.files;
+ }
+ obj.set = function() {
+ // Get attachments
+ var files = element.querySelectorAll('.jfile');
+
+ if (files.length > 0) {
+ var data = [];
+ for (var i = 0; i < files.length; i++) {
+ var file = {};
+
+ var src = files[i].getAttribute('src');
+
+ if (files[i].classList.contains('jremove')) {
+ file.remove = 1;
+ } else {
+ if (src.substr(0,4) == 'data') {
+ file.content = src.substr(src.indexOf(',') + 1);
+ file.extension = files[i].getAttribute('data-extension');
+ } else {
+ file.file = src;
+ file.extension = files[i].getAttribute('data-extension');
+ if (! file.extension) {
+ file.extension = src.substr(src.lastIndexOf('.') + 1);
+ }
+
+ if (files[i].content) {
+ file.content = files[i].content;
+ }
+ }
+
+ // Optional file information
+ if (files[i].getAttribute('data-name')) {
+ file.name = files[i].getAttribute('data-name');
+ }
+ if (files[i].getAttribute('data-file')) {
+ file.file = files[i].getAttribute('data-file');
+ }
+ if (files[i].getAttribute('data-size')) {
+ file.size = files[i].getAttribute('data-size');
+ }
+ if (files[i].getAttribute('data-date')) {
+ file.date = files[i].getAttribute('data-date');
+ }
+ if (files[i].getAttribute('data-cover')) {
+ file.cover = files[i].getAttribute('data-cover');
+ }
+ }
+ data[i] = file;
+ }
+
+ obj.files = data;
+
+ return data;
+ }
+ }
+
+ obj.set();
+
+ return obj;
+});
+
+jSuites.form = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ url: null,
+ message: 'Are you sure? There are unsaved information in your form',
+ ignore: false,
+ currentHash: null,
+ submitButton:null,
+ validations: null,
+ onload: null,
+ onbeforesave: null,
+ onsave: null,
+ onerror: function(el, message) {
+ jSuites.alert(message);
+ }
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Validations
+ if (! obj.options.validations) {
+ obj.options.validations = {};
+ }
+
+ // submitButton
+ if (obj.options.submitButton && obj.options.url) {
+ obj.options.submitButton.onclick = function() {
+ obj.save();
+ }
+ }
+
+ if (! obj.options.validations.email) {
+ obj.options.validations.email = function(data) {
+ var reg = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
+ return data && reg.test(data) ? true : false;
+ }
+ }
+
+ if (! obj.options.validations.length) {
+ obj.options.validations.length = function(data, element) {
+ var len = element.getAttribute('data-length') || 5;
+ return (data.length >= len) ? true : false;
+ }
+ }
+
+ if (! obj.options.validations.required) {
+ obj.options.validations.required = function(data) {
+ return data.trim() ? true : false;
+ }
+ }
+
+ obj.setUrl = function(url) {
+ obj.options.url = url;
+ }
+
+ obj.load = function() {
+ jSuites.ajax({
+ url: obj.options.url,
+ method: 'GET',
+ dataType: 'json',
+ success: function(data) {
+ jSuites.form.setElements(el, data);
+
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, data);
+ }
+ }
+ });
+ }
+
+ obj.save = function() {
+ var test = obj.validate();
+
+ if (test) {
+ obj.options.onerror(el, test);
+ } else {
+ var data = jSuites.form.getElements(el, true);
+
+ if (typeof(obj.options.onbeforesave) == 'function') {
+ var data = obj.options.onbeforesave(el, data);
+
+ if (data === false) {
+ console.log('Onbeforesave returned false');
+ return;
+ }
+ }
+
+ jSuites.ajax({
+ url: obj.options.url,
+ method: 'POST',
+ dataType: 'json',
+ data: data,
+ success: function(result) {
+ if (typeof(obj.options.onsave) == 'function') {
+ obj.options.onsave(el, data, result);
+ }
+
+ obj.reset();
+ }
+ });
+ }
+ }
+
+ var addError = function(element) {
+ // Add error in the element
+ element.classList.add('error');
+ // Submit button
+ if (obj.options.submitButton) {
+ obj.options.submitButton.setAttribute('disabled', true);
+ }
+ // Return error message
+ var error = element.getAttribute('data-error') || 'There is an error in the form';
+ element.setAttribute('title', error);
+ return error;
+ }
+
+ var delError = function(element) {
+ var error = false;
+ // Remove class from this element
+ element.classList.remove('error');
+ element.removeAttribute('title');
+ // Get elements in the form
+ var elements = el.querySelectorAll("input, select, textarea");
+ // Run all elements
+ for (var i = 0; i < elements.length; i++) {
+ if (elements[i].getAttribute('data-validation')) {
+ if (elements[i].classList.contains('error')) {
+ error = true;
+ }
+ }
+ }
+
+ if (obj.options.submitButton) {
+ if (error) {
+ obj.options.submitButton.setAttribute('disabled', true);
+ } else {
+ obj.options.submitButton.removeAttribute('disabled');
+ }
+ }
+ }
+
+ obj.validateElement = function(element) {
+ // Test results
+ var test = false;
+ // Validation
+ var validation = element.getAttribute('data-validation');
+ // Parse
+ if (typeof(obj.options.validations[validation]) == 'function' && ! obj.options.validations[validation](element.value, element)) {
+ // Not passed in the test
+ test = addError(element);
+ } else {
+ if (element.classList.contains('error')) {
+ delError(element);
+ }
+ }
+
+ return test;
+ }
+
+ obj.reset = function() {
+ // Get elements in the form
+ var elements = el.querySelectorAll("input, select, textarea");
+ // Run all elements
+ for (var i = 0; i < elements.length; i++) {
+ if (elements[i].tagName == 'INPUT' && elements[i].type == 'checkbox') {
+ elements[i].removeAttribute('checked');
+ } else {
+ elements[i].value = '';
+ }
+ }
+ }
+
+ // Run form validation
+ obj.validate = function() {
+ var test = [];
+ // Get elements in the form
+ var elements = el.querySelectorAll("input, select, textarea");
+ // Run all elements
+ for (var i = 0; i < elements.length; i++) {
+ // Required
+ if (elements[i].getAttribute('data-validation')) {
+ var res = obj.validateElement(elements[i]);
+ if (res) {
+ test.push(res);
+ }
+ }
+ }
+ if (test.length > 0) {
+ return test.join('<br>');
+ } else {
+ return false;
+ }
+ }
+
+ // Check the form
+ obj.getError = function() {
+ // Validation
+ return obj.validation() ? true : false;
+ }
+
+ // Return the form hash
+ obj.setHash = function() {
+ return obj.getHash(jSuites.form.getElements(el));
+ }
+
+ // Get the form hash
+ obj.getHash = function(str) {
+ var hash = 0, i, chr;
+
+ if (str.length === 0) {
+ return hash;
+ } else {
+ for (i = 0; i < str.length; i++) {
+ chr = str.charCodeAt(i);
+ hash = ((hash << 5) - hash) + chr;
+ hash |= 0;
+ }
+ }
+
+ return hash;
+ }
+
+ // Is there any change in the form since start tracking?
+ obj.isChanged = function() {
+ var hash = obj.setHash();
+ return (obj.options.currentHash != hash);
+ }
+
+ // Restart tracking
+ obj.resetTracker = function() {
+ obj.options.currentHash = obj.setHash();
+ obj.options.ignore = false;
+ }
+
+ obj.reset = function() {
+ obj.options.currentHash = obj.setHash();
+ obj.options.ignore = false;
+ }
+
+ // Ignore flag
+ obj.setIgnore = function(ignoreFlag) {
+ obj.options.ignore = ignoreFlag ? true : false;
+ }
+
+ // Start tracking in one second
+ setTimeout(function() {
+ obj.options.currentHash = obj.setHash();
+ }, 1000);
+
+ // Validations
+ el.addEventListener("keyup", function(e) {
+ if (e.target.getAttribute('data-validation')) {
+ obj.validateElement(e.target);
+ }
+ });
+
+ // Alert
+ if (! jSuites.form.hasEvents) {
+ window.addEventListener("beforeunload", function (e) {
+ if (obj.isChanged() && obj.options.ignore == false) {
+ var confirmationMessage = obj.options.message? obj.options.message : "\o/";
+
+ if (confirmationMessage) {
+ if (typeof e == 'undefined') {
+ e = window.event;
+ }
+
+ if (e) {
+ e.returnValue = confirmationMessage;
+ }
+
+ return confirmationMessage;
+ } else {
+ return void(0);
+ }
+ }
+ });
+
+ jSuites.form.hasEvents = true;
+ }
+
+ el.form = obj;
+
+ return obj;
+});
+
+// Get form elements
+jSuites.form.getElements = function(el, asArray) {
+ var data = {};
+ var elements = el.querySelectorAll("input, select, textarea");
+
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ var name = element.name;
+ var value = element.value;
+
+ if (name) {
+ if (elements[i].type == 'checkbox' || elements[i].type == 'radio') {
+ value = elements[i].checked;
+ }
+ data[name] = value;
+ }
+ }
+
+ return asArray == true ? data : JSON.stringify(data);
+}
+
+//Get form elements
+jSuites.form.setElements = function(el, data) {
+ var elements = el.querySelectorAll("input, select, textarea");
+
+ for (var i = 0; i < elements.length; i++) {
+ var name = elements[i].getAttribute('name');
+ if (data[name]) {
+ elements[i].value = data[name];
+ }
+ }
+}
+
+// Legacy
+jSuites.tracker = jSuites.form;
+
+jSuites.isNumeric = (function (num) {
+ return !isNaN(num) && num != null && num != '';
+});
+
+jSuites.guid = function() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+}
+
+jSuites.getWindowWidth = function() {
+ var w = window,
+ d = document,
+ e = d.documentElement,
+ g = d.getElementsByTagName('body')[0],
+ x = w.innerWidth || e.clientWidth || g.clientWidth;
+ return x;
+}
+
+jSuites.getWindowHeight = function() {
+ var w = window,
+ d = document,
+ e = d.documentElement,
+ g = d.getElementsByTagName('body')[0],
+ y = w.innerHeight|| e.clientHeight|| g.clientHeight;
+ return y;
+}
+
+jSuites.getPosition = function(e) {
+ if (e.changedTouches && e.changedTouches[0]) {
+ var x = e.changedTouches[0].pageX;
+ var y = e.changedTouches[0].pageY;
+ } else {
+ var x = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
+ var y = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
+ }
+
+ return [ x, y ];
+}
+
+jSuites.click = function(el) {
+ if (el.click) {
+ el.click();
+ } else {
+ var evt = new MouseEvent('click', {
+ bubbles: true,
+ cancelable: true,
+ view: window
+ });
+ el.dispatchEvent(evt);
+ }
+}
+
+jSuites.findElement = function(element, condition) {
+ var foundElement = false;
+
+ function path (element) {
+ if (element && ! foundElement) {
+ if (typeof(condition) == 'function') {
+ foundElement = condition(element)
+ } else if (typeof(condition) == 'string') {
+ if (element.classList && element.classList.contains(condition)) {
+ foundElement = element;
+ }
+ }
+ }
+
+ if (element.parentNode && ! foundElement) {
+ path(element.parentNode);
+ }
+ }
+
+ path(element);
+
+ return foundElement;
+}
+
+// Two digits
+jSuites.two = function(value) {
+ value = '' + value;
+ if (value.length == 1) {
+ value = '0' + value;
+ }
+ return value;
+}
+
+jSuites.sha512 = (function(str) {
+ function int64(msint_32, lsint_32) {
+ this.highOrder = msint_32;
+ this.lowOrder = lsint_32;
+ }
+
+ var H = [new int64(0x6a09e667, 0xf3bcc908), new int64(0xbb67ae85, 0x84caa73b),
+ new int64(0x3c6ef372, 0xfe94f82b), new int64(0xa54ff53a, 0x5f1d36f1),
+ new int64(0x510e527f, 0xade682d1), new int64(0x9b05688c, 0x2b3e6c1f),
+ new int64(0x1f83d9ab, 0xfb41bd6b), new int64(0x5be0cd19, 0x137e2179)];
+
+ var K = [new int64(0x428a2f98, 0xd728ae22), new int64(0x71374491, 0x23ef65cd),
+ new int64(0xb5c0fbcf, 0xec4d3b2f), new int64(0xe9b5dba5, 0x8189dbbc),
+ new int64(0x3956c25b, 0xf348b538), new int64(0x59f111f1, 0xb605d019),
+ new int64(0x923f82a4, 0xaf194f9b), new int64(0xab1c5ed5, 0xda6d8118),
+ new int64(0xd807aa98, 0xa3030242), new int64(0x12835b01, 0x45706fbe),
+ new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, 0xd5ffb4e2),
+ new int64(0x72be5d74, 0xf27b896f), new int64(0x80deb1fe, 0x3b1696b1),
+ new int64(0x9bdc06a7, 0x25c71235), new int64(0xc19bf174, 0xcf692694),
+ new int64(0xe49b69c1, 0x9ef14ad2), new int64(0xefbe4786, 0x384f25e3),
+ new int64(0x0fc19dc6, 0x8b8cd5b5), new int64(0x240ca1cc, 0x77ac9c65),
+ new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
+ new int64(0x5cb0a9dc, 0xbd41fbd4), new int64(0x76f988da, 0x831153b5),
+ new int64(0x983e5152, 0xee66dfab), new int64(0xa831c66d, 0x2db43210),
+ new int64(0xb00327c8, 0x98fb213f), new int64(0xbf597fc7, 0xbeef0ee4),
+ new int64(0xc6e00bf3, 0x3da88fc2), new int64(0xd5a79147, 0x930aa725),
+ new int64(0x06ca6351, 0xe003826f), new int64(0x14292967, 0x0a0e6e70),
+ new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
+ new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, 0x9d95b3df),
+ new int64(0x650a7354, 0x8baf63de), new int64(0x766a0abb, 0x3c77b2a8),
+ new int64(0x81c2c92e, 0x47edaee6), new int64(0x92722c85, 0x1482353b),
+ new int64(0xa2bfe8a1, 0x4cf10364), new int64(0xa81a664b, 0xbc423001),
+ new int64(0xc24b8b70, 0xd0f89791), new int64(0xc76c51a3, 0x0654be30),
+ new int64(0xd192e819, 0xd6ef5218), new int64(0xd6990624, 0x5565a910),
+ new int64(0xf40e3585, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
+ new int64(0x19a4c116, 0xb8d2d0c8), new int64(0x1e376c08, 0x5141ab53),
+ new int64(0x2748774c, 0xdf8eeb99), new int64(0x34b0bcb5, 0xe19b48a8),
+ new int64(0x391c0cb3, 0xc5c95a63), new int64(0x4ed8aa4a, 0xe3418acb),
+ new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, 0xd6b2b8a3),
+ new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
+ new int64(0x84c87814, 0xa1f0ab72), new int64(0x8cc70208, 0x1a6439ec),
+ new int64(0x90befffa, 0x23631e28), new int64(0xa4506ceb, 0xde82bde9),
+ new int64(0xbef9a3f7, 0xb2c67915), new int64(0xc67178f2, 0xe372532b),
+ new int64(0xca273ece, 0xea26619c), new int64(0xd186b8c7, 0x21c0c207),
+ new int64(0xeada7dd6, 0xcde0eb1e), new int64(0xf57d4f7f, 0xee6ed178),
+ new int64(0x06f067aa, 0x72176fba), new int64(0x0a637dc5, 0xa2c898a6),
+ new int64(0x113f9804, 0xbef90dae), new int64(0x1b710b35, 0x131c471b),
+ new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
+ new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, 0x9c100d4c),
+ new int64(0x4cc5d4be, 0xcb3e42b6), new int64(0x597f299c, 0xfc657e2a),
+ new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)];
+
+ var W = new Array(64);
+ var a, b, c, d, e, f, g, h, i, j;
+ var T1, T2;
+ var charsize = 8;
+
+ function utf8_encode(str) {
+ return unescape(encodeURIComponent(str));
+ }
+
+ function str2binb(str) {
+ var bin = [];
+ var mask = (1 << charsize) - 1;
+ var len = str.length * charsize;
+
+ for (var i = 0; i < len; i += charsize) {
+ bin[i >> 5] |= (str.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32));
+ }
+
+ return bin;
+ }
+
+ function binb2hex(binarray) {
+ var hex_tab = "0123456789abcdef";
+ var str = "";
+ var length = binarray.length * 4;
+ var srcByte;
+
+ for (var i = 0; i < length; i += 1) {
+ srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
+ str += hex_tab.charAt((srcByte >> 4) & 0xF) + hex_tab.charAt(srcByte & 0xF);
+ }
+
+ return str;
+ }
+
+ function safe_add_2(x, y) {
+ var lsw, msw, lowOrder, highOrder;
+
+ lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
+ msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
+ lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
+ msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
+ highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ return new int64(highOrder, lowOrder);
+ }
+
+ function safe_add_4(a, b, c, d) {
+ var lsw, msw, lowOrder, highOrder;
+
+ lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
+ msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
+ lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
+ msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
+ highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ return new int64(highOrder, lowOrder);
+ }
+
+ function safe_add_5(a, b, c, d, e) {
+ var lsw, msw, lowOrder, highOrder;
+
+ lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + (e.lowOrder & 0xFFFF);
+ msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + (lsw >>> 16);
+ lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (e.highOrder & 0xFFFF) + (msw >>> 16);
+ msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (e.highOrder >>> 16) + (lsw >>> 16);
+ highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
+
+ return new int64(highOrder, lowOrder);
+ }
+
+ function maj(x, y, z) {
+ return new int64(
+ (x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder),
+ (x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder)
+ );
+ }
+
+ function ch(x, y, z) {
+ return new int64(
+ (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
+ (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
+ );
+ }
+
+ function rotr(x, n) {
+ if (n <= 32) {
+ return new int64(
+ (x.highOrder >>> n) | (x.lowOrder << (32 - n)),
+ (x.lowOrder >>> n) | (x.highOrder << (32 - n))
+ );
+ } else {
+ return new int64(
+ (x.lowOrder >>> n) | (x.highOrder << (32 - n)),
+ (x.highOrder >>> n) | (x.lowOrder << (32 - n))
+ );
+ }
+ }
+
+ function sigma0(x) {
+ var rotr28 = rotr(x, 28);
+ var rotr34 = rotr(x, 34);
+ var rotr39 = rotr(x, 39);
+
+ return new int64(
+ rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
+ rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
+ );
+ }
+
+ function sigma1(x) {
+ var rotr14 = rotr(x, 14);
+ var rotr18 = rotr(x, 18);
+ var rotr41 = rotr(x, 41);
+
+ return new int64(
+ rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
+ rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
+ );
+ }
+
+ function gamma0(x) {
+ var rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7);
+
+ return new int64(
+ rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
+ rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
+ );
+ }
+
+ function gamma1(x) {
+ var rotr19 = rotr(x, 19);
+ var rotr61 = rotr(x, 61);
+ var shr6 = shr(x, 6);
+
+ return new int64(
+ rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
+ rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
+ );
+ }
+
+ function shr(x, n) {
+ if (n <= 32) {
+ return new int64(
+ x.highOrder >>> n,
+ x.lowOrder >>> n | (x.highOrder << (32 - n))
+ );
+ } else {
+ return new int64(
+ 0,
+ x.highOrder << (32 - n)
+ );
+ }
+ }
+
+ var str = utf8_encode(str);
+ var strlen = str.length*charsize;
+ str = str2binb(str);
+
+ str[strlen >> 5] |= 0x80 << (24 - strlen % 32);
+ str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
+
+ for (var i = 0; i < str.length; i += 32) {
+ a = H[0];
+ b = H[1];
+ c = H[2];
+ d = H[3];
+ e = H[4];
+ f = H[5];
+ g = H[6];
+ h = H[7];
+
+ for (var j = 0; j < 80; j++) {
+ if (j < 16) {
+ W[j] = new int64(str[j*2 + i], str[j*2 + i + 1]);
+ } else {
+ W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]);
+ }
+
+ T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]);
+ T2 = safe_add_2(sigma0(a), maj(a, b, c));
+ h = g;
+ g = f;
+ f = e;
+ e = safe_add_2(d, T1);
+ d = c;
+ c = b;
+ b = a;
+ a = safe_add_2(T1, T2);
+ }
+
+ H[0] = safe_add_2(a, H[0]);
+ H[1] = safe_add_2(b, H[1]);
+ H[2] = safe_add_2(c, H[2]);
+ H[3] = safe_add_2(d, H[3]);
+ H[4] = safe_add_2(e, H[4]);
+ H[5] = safe_add_2(f, H[5]);
+ H[6] = safe_add_2(g, H[6]);
+ H[7] = safe_add_2(h, H[7]);
+ }
+
+ var binarray = [];
+ for (var i = 0; i < H.length; i++) {
+ binarray.push(H[i].highOrder);
+ binarray.push(H[i].lowOrder);
+ }
+
+ return binb2hex(binarray);
+});
+
+if (! jSuites.login) {
+ jSuites.login = {};
+ jSuites.login.sha512 = jSuites.sha512;
+}
+
+jSuites.image = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ input: false,
+ minWidth: false,
+ maxWidth: null,
+ maxHeight: null,
+ maxJpegSizeBytes: null, // For example, 350Kb would be 350000
+ onchange: null,
+ singleFile: true,
+ remoteParser: null,
+ text:{
+ extensionNotAllowed:'The extension is not allowed',
+ imageTooSmall:'The resolution is too low, try a image with a better resolution. width > 800px',
+ }
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Upload icon
+ el.classList.add('jupload');
+
+ if (obj.options.input == true) {
+ el.classList.add('input');
+ }
+
+ // Add image
+ obj.addImage = function(file) {
+ if (! file.date) {
+ file.date = '';
+ }
+ var img = document.createElement('img');
+ img.setAttribute('data-date', file.lastmodified ? file.lastmodified : file.date);
+ img.setAttribute('data-name', file.name);
+ img.setAttribute('data-size', file.size);
+ img.setAttribute('data-small', file.small ? file.small : '');
+ img.setAttribute('data-cover', file.cover ? 1 : 0);
+ img.setAttribute('data-extension', file.extension);
+ img.setAttribute('src', file.file);
+ img.className = 'jfile';
+ img.style.width = '100%';
+
+ return img;
+ }
+
+ // Add image
+ obj.addImages = function(files) {
+ if (obj.options.singleFile == true) {
+ el.innerHTML = '';
+ }
+
+ for (var i = 0; i < files.length; i++) {
+ el.appendChild(obj.addImage(files[i]));
+ }
+ }
+
+ obj.addFromFile = function(file) {
+ var type = file.type.split('/');
+ if (type[0] == 'image') {
+ if (obj.options.singleFile == true) {
+ el.innerHTML = '';
+ }
+
+ var imageFile = new FileReader();
+ imageFile.addEventListener("load", function (v) {
+
+ var img = new Image();
+
+ img.onload = function onload() {
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ var data = {
+ file: obj.getDataURL(canvas, file.type),
+ extension: file.name.substr(file.name.lastIndexOf('.') + 1),
+ name: file.name,
+ size: file.size,
+ lastmodified: file.lastModified,
+ }
+ var newImage = obj.addImage(data);
+ el.appendChild(newImage);
+
+ // Onchange
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(newImage);
+ }
+ };
+
+ img.src = v.srcElement.result;
+ });
+
+ imageFile.readAsDataURL(file);
+ } else {
+ alert(text.extentionNotAllowed);
+ }
+ }
+
+ obj.addFromUrl = function(src) {
+ if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
+ console.error('remoteParser not defined in your initialization');
+ } else {
+ // This is to process cross domain images
+ if (src.substr(0,4) == 'data') {
+ var extension = src.split(';')
+ extension = extension[0].split('/');
+ extension = extension[1];
+ } else {
+ var extension = src.substr(src.lastIndexOf('.') + 1);
+ // Work for cross browsers
+ src = obj.options.remoteParser + src;
+ }
+
+ var img = new Image();
+
+ img.onload = function onload() {
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
+
+ canvas.toBlob(function(blob) {
+ var data = {
+ file: window.URL.createObjectURL(blob),
+ extension: extension
+ }
+ var newImage = obj.addImage(data);
+ el.appendChild(newImage);
+
+ // Keep base64 ready to go
+ var content = canvas.toDataURL();
+
+ // Onchange
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(newImage);
+ }
+ });
+ };
+
+ img.src = src;
+ }
+ }
+
+ obj.getCanvas = function(img) {
+ var canvas = document.createElement('canvas');
+ var r1 = (obj.options.maxWidth || img.width ) / img.width;
+ var r2 = (obj.options.maxHeight || img.height) / img.height;
+ var r = Math.min(r1, r2, 1);
+ canvas.width = img.width * r;
+ canvas.height = img.height * r;
+ return canvas;
+ }
+
+ obj.getDataURL = function(canvas, type) {
+ var compression = 0.92;
+ var lastContentLength = null;
+ var content = canvas.toDataURL(type, compression);
+ while (obj.options.maxJpegSizeBytes && type === 'image/jpeg' &&
+ content.length > obj.options.maxJpegSizeBytes && content.length !== lastContentLength) {
+ // Apply the compression
+ compression *= 0.9;
+ lastContentLength = content.length;
+ content = canvas.toDataURL(type, compression);
+ }
+ return content;
+ }
+
+ var attachmentInput = document.createElement('input');
+ attachmentInput.type = 'file';
+ attachmentInput.setAttribute('accept', 'image/*');
+ attachmentInput.onchange = function() {
+ for (var i = 0; i < this.files.length; i++) {
+ obj.addFromFile(this.files[i]);
+ }
+ }
+
+ el.addEventListener("click", function(e) {
+ jSuites.click(attachmentInput);
+ });
+
+ el.addEventListener('dragenter', function(e) {
+ el.style.border = '1px dashed #000';
+ });
+
+ el.addEventListener('dragleave', function(e) {
+ el.style.border = '1px solid #eee';
+ });
+
+ el.addEventListener('dragstop', function(e) {
+ el.style.border = '1px solid #eee';
+ });
+
+ el.addEventListener('dragover', function(e) {
+ e.preventDefault();
+ });
+
+ el.addEventListener('drop', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+
+ var html = (e.originalEvent || e).dataTransfer.getData('text/html');
+ var file = (e.originalEvent || e).dataTransfer.files;
+
+ if (file.length) {
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
+ obj.addFromFile(e.dataTransfer.files[i]);
+ }
+ } else if (html) {
+ if (obj.options.singleFile == true) {
+ el.innerHTML = '';
+ }
+
+ // Create temp element
+ var div = document.createElement('div');
+ div.innerHTML = html;
+
+ // Extract images
+ var img = div.querySelectorAll('img');
+
+ if (img.length) {
+ for (var i = 0; i < img.length; i++) {
+ obj.addFromUrl(img[i].src);
+ }
+ }
+ }
+
+ el.style.border = '1px solid #eee';
+
+ return false;
+ });
+
+ el.image = obj;
+
+ return obj;
+});
+
+
+jSuites.lazyLoading = (function(el, options) {
+ var obj = {}
+
+ // Mandatory options
+ if (! options.loadUp || typeof(options.loadUp) != 'function') {
+ options.loadUp = function() {
+ return false;
+ }
+ }
+ if (! options.loadDown || typeof(options.loadDown) != 'function') {
+ options.loadDown = function() {
+ return false;
+ }
+ }
+ // Timer ms
+ if (! options.timer) {
+ options.timer = 100;
+ }
+
+ // Timer
+ var timeControlLoading = null;
+
+ // Controls
+ var scrollControls = function(e) {
+ if (timeControlLoading == null) {
+ var scrollTop = el.scrollTop;
+ if (el.scrollTop + (el.clientHeight * 2) >= el.scrollHeight) {
+ if (options.loadDown()) {
+ if (scrollTop == el.scrollTop) {
+ el.scrollTop = el.scrollTop - (el.clientHeight);
+ }
+ }
+ } else if (el.scrollTop <= el.clientHeight) {
+ if (options.loadUp()) {
+ if (scrollTop == el.scrollTop) {
+ el.scrollTop = el.scrollTop + (el.clientHeight);
+ }
+ }
+ }
+
+ timeControlLoading = setTimeout(function() {
+ timeControlLoading = null;
+ }, options.timer);
+ }
+ }
+
+ // Onscroll
+ el.onscroll = function(e) {
+ scrollControls(e);
+ }
+
+ el.onwheel = function(e) {
+ scrollControls(e);
+ }
+
+ return obj;
+});
+
+jSuites.loading = (function() {
+ var obj = {};
+
+ var loading = null;
+
+ obj.show = function() {
+ if (! loading) {
+ loading = document.createElement('div');
+ loading.className = 'jloading';
+ }
+ document.body.appendChild(loading);
+ }
+
+ obj.hide = function() {
+ if (loading) {
+ document.body.removeChild(loading);
+ }
+ }
+
+ return obj;
+})();
+
+jSuites.mask = (function() {
+ var obj = {};
+ var index = 0;
+ var values = []
+ var pieces = [];
+
+ /**
+ * Apply a mask over a value considering a custom decimal representation. Default: '.'
+ */
+ obj.run = function(value, mask, decimal) {
+ if (value.toString().length && mask.toString().length) {
+ // Default decimal separator
+ if (typeof(decimal) == 'undefined') {
+ decimal = '.';
+ }
+
+ if (jSuites.isNumeric(value)) {
+ var number = (''+value).split(decimal);
+ var value = number[0];
+ var valueDecimal = number[1];
+ } else {
+ value = '' + value;
+ }
+
+ // Helpers
+ index = 0;
+ values = [];
+ // Create mask token
+ obj.prepare(mask);
+ // Current value
+ var currentValue = value;
+ if (currentValue) {
+ // Checking current value
+ for (var i = 0; i < currentValue.length; i++) {
+ if (currentValue[i] != null) {
+ obj.process(currentValue[i]);
+ }
+ }
+ }
+ if (valueDecimal) {
+ obj.process(decimal);
+ var currentValue = valueDecimal;
+ if (currentValue) {
+ // Checking current value
+ for (var i = 0; i < currentValue.length; i++) {
+ if (currentValue[i] != null) {
+ obj.process(currentValue[i]);
+ }
+ }
+ }
+ }
+ // Formatted value
+ return values.join('');
+ } else {
+ return '';
+ }
+ }
+
+ obj.apply = function(e) {
+ if (e.target && ! e.target.getAttribute('readonly')) {
+ var mask = e.target.getAttribute('data-mask');
+ if (mask) {
+ index = 0;
+ values = [];
+ // Create mask token
+ obj.prepare(mask);
+ // Current value
+ if (e.target.selectionStart < e.target.selectionEnd) {
+ var currentValue = e.target.value.substring(0, e.target.selectionStart);
+ } else {
+ var currentValue = e.target.value;
+ }
+ if (currentValue) {
+ // Checking current value
+ for (var i = 0; i < currentValue.length; i++) {
+ if (currentValue[i] != null) {
+ obj.process(currentValue[i]);
+ }
+ }
+ }
+ // New input
+ if (e.keyCode > 46) {
+ obj.process(obj.fromKeyCode(e));
+ // Prevent default
+ e.preventDefault();
+ }
+ // Update value to the element
+ e.target.value = values.join('');
+ if (pieces.length == values.length && pieces[pieces.length-1].length == values[values.length-1].length) {
+ e.target.setAttribute('data-completed', 'true');
+ } else {
+ e.target.setAttribute('data-completed', 'false');
+ }
+ }
+ }
+ }
+
+ /**
+ * Process inputs and save to values
+ */
+ obj.process = function(input) {
+ do {
+ if (pieces[index] == 'mm') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 1 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 1 && values[index] < 2 && parseInt(input) < 3) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] == 0 && values[index] < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'dd') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 3 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 3 && parseInt(input) < 2) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] < 3 && parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'hh24') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 2 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 2 && parseInt(input) < 4) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] < 2 && parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'hh') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 1 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (values[index] == 1 && parseInt(input) < 3) {
+ values[index] += input;
+ index++;
+ return true;
+ } else if (values[index] < 1 && parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'mi' || pieces[index] == 'ss') {
+ if (values[index] == null || values[index] == '') {
+ if (parseInt(input) > 5 && parseInt(input) < 10) {
+ values[index] = '0' + input;
+ index++;
+ return true;
+ } else if (parseInt(input) < 10) {
+ values[index] = input;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (parseInt(input) < 10) {
+ values[index] += input;
+ index++;
+ return true;
+ } else {
+ return false
+ }
+ }
+ } else if (pieces[index] == 'yy' || pieces[index] == 'yyyy') {
+ if (parseInt(input) < 10) {
+ if (values[index] == null || values[index] == '') {
+ values[index] = input;
+ } else {
+ values[index] += input;
+ }
+
+ if (values[index].length == pieces[index].length) {
+ index++;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ } else if (pieces[index] == '#' || pieces[index] == '#.##' || pieces[index] == '#,##' || pieces[index] == '# ##') {
+ if (input.match(/[0-9]/g)) {
+ if (pieces[index] == '#.##') {
+ var separator = '.';
+ } else if (pieces[index] == '#,##') {
+ var separator = ',';
+ } else if (pieces[index] == '# ##') {
+ var separator = ' ';
+ } else {
+ var separator = '';
+ }
+ if (values[index] == null || values[index] == '') {
+ values[index] = input;
+ } else {
+ values[index] += input;
+ if (separator) {
+ values[index] = values[index].match(/[0-9]/g).join('');
+ var t = [];
+ var s = 0;
+ for (var j = values[index].length - 1; j >= 0 ; j--) {
+ t.push(values[index][j]);
+ s++;
+ if (! (s % 3)) {
+ t.push(separator);
+ }
+ }
+ t = t.reverse();
+ values[index] = t.join('');
+ if (values[index].substr(0,1) == separator) {
+ values[index] = values[index].substr(1);
+ }
+ }
+ }
+ return true;
+ } else {
+ if (pieces[index] == '#.##' && input == '.') {
+ // Do nothing
+ } else if (pieces[index] == '#,##' && input == ',') {
+ // Do nothing
+ } else if (pieces[index] == '# ##' && input == ' ') {
+ // Do nothing
+ } else {
+ if (values[index]) {
+ index++;
+ if (pieces[index]) {
+ if (pieces[index] == input) {
+ values[index] = input;
+ return true;
+ } else {
+ if (pieces[index] == '0' && pieces[index+1] == input) {
+ index++;
+ values[index] = input;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+ } else if (pieces[index] == '0') {
+ if (input.match(/[0-9]/g)) {
+ values[index] = input;
+ index++;
+ return true;
+ } else {
+ return false;
+ }
+ } else if (pieces[index] == 'a') {
+ if (input.match(/[a-zA-Z]/g)) {
+ values[index] = input;
+ index++;
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (pieces[index] != null) {
+ if (pieces[index] == '\\a') {
+ var v = 'a';
+ } else if (pieces[index] == '\\0') {
+ var v = '0';
+ } else if (pieces[index] == '[-]') {
+ if (input == '-' || input == '+') {
+ var v = input;
+ } else {
+ var v = ' ';
+ }
+ } else {
+ var v = pieces[index];
+ }
+ values[index] = v;
+ if (input == v) {
+ index++;
+ return true;
+ }
+ }
+ }
+
+ index++;
+ } while (pieces[index]);
+ }
+
+ /**
+ * Create tokens for the mask
+ */
+ obj.prepare = function(mask) {
+ pieces = [];
+ for (var i = 0; i < mask.length; i++) {
+ if (mask[i].match(/[0-9]|[a-z]|\\/g)) {
+ if (mask[i] == 'y' && mask[i+1] == 'y' && mask[i+2] == 'y' && mask[i+3] == 'y') {
+ pieces.push('yyyy');
+ i += 3;
+ } else if (mask[i] == 'y' && mask[i+1] == 'y') {
+ pieces.push('yy');
+ i++;
+ } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm' && mask[i+3] == 'm') {
+ pieces.push('mmmm');
+ i += 3;
+ } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm') {
+ pieces.push('mmm');
+ i += 2;
+ } else if (mask[i] == 'm' && mask[i+1] == 'm') {
+ pieces.push('mm');
+ i++;
+ } else if (mask[i] == 'd' && mask[i+1] == 'd') {
+ pieces.push('dd');
+ i++;
+ } else if (mask[i] == 'h' && mask[i+1] == 'h' && mask[i+2] == '2' && mask[i+3] == '4') {
+ pieces.push('hh24');
+ i += 3;
+ } else if (mask[i] == 'h' && mask[i+1] == 'h') {
+ pieces.push('hh');
+ i++;
+ } else if (mask[i] == 'm' && mask[i+1] == 'i') {
+ pieces.push('mi');
+ i++;
+ } else if (mask[i] == 's' && mask[i+1] == 's') {
+ pieces.push('ss');
+ i++;
+ } else if (mask[i] == 'a' && mask[i+1] == 'm') {
+ pieces.push('am');
+ i++;
+ } else if (mask[i] == 'p' && mask[i+1] == 'm') {
+ pieces.push('pm');
+ i++;
+ } else if (mask[i] == '\\' && mask[i+1] == '0') {
+ pieces.push('\\0');
+ i++;
+ } else if (mask[i] == '\\' && mask[i+1] == 'a') {
+ pieces.push('\\a');
+ i++;
+ } else {
+ pieces.push(mask[i]);
+ }
+ } else {
+ if (mask[i] == '#' && mask[i+1] == '.' && mask[i+2] == '#' && mask[i+3] == '#') {
+ pieces.push('#.##');
+ i += 3;
+ } else if (mask[i] == '#' && mask[i+1] == ',' && mask[i+2] == '#' && mask[i+3] == '#') {
+ pieces.push('#,##');
+ i += 3;
+ } else if (mask[i] == '#' && mask[i+1] == ' ' && mask[i+2] == '#' && mask[i+3] == '#') {
+ pieces.push('# ##');
+ i += 3;
+ } else if (mask[i] == '[' && mask[i+1] == '-' && mask[i+2] == ']') {
+ pieces.push('[-]');
+ i += 2;
+ } else {
+ pieces.push(mask[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Thanks for the collaboration
+ */
+ obj.fromKeyCode = function(e) {
+ var _to_ascii = {
+ '188': '44',
+ '109': '45',
+ '190': '46',
+ '191': '47',
+ '192': '96',
+ '220': '92',
+ '222': '39',
+ '221': '93',
+ '219': '91',
+ '173': '45',
+ '187': '61', //IE Key codes
+ '186': '59', //IE Key codes
+ '189': '45' //IE Key codes
+ }
+
+ var shiftUps = {
+ "96": "~",
+ "49": "!",
+ "50": "@",
+ "51": "#",
+ "52": "$",
+ "53": "%",
+ "54": "^",
+ "55": "&",
+ "56": "*",
+ "57": "(",
+ "48": ")",
+ "45": "_",
+ "61": "+",
+ "91": "{",
+ "93": "}",
+ "92": "|",
+ "59": ":",
+ "39": "\"",
+ "44": "<",
+ "46": ">",
+ "47": "?"
+ };
+
+ var c = e.which;
+
+ if (_to_ascii.hasOwnProperty(c)) {
+ c = _to_ascii[c];
+ }
+
+ if (!e.shiftKey && (c >= 65 && c <= 90)) {
+ c = String.fromCharCode(c + 32);
+ } else if (e.shiftKey && shiftUps.hasOwnProperty(c)) {
+ c = shiftUps[c];
+ } else if (96 <= c && c <= 105) {
+ c = String.fromCharCode(c - 48);
+ } else {
+ c = String.fromCharCode(c);
+ }
+
+ return c;
+ }
+
+ if (typeof document !== 'undefined') {
+ document.addEventListener('keydown', function(e) {
+ if (jSuites.mask) {
+ jSuites.mask.apply(e);
+ }
+ });
+ }
+
+ return obj;
+})();
+
+
+/**
+ * (c) jSuites modal
+ * https://github.com/paulhodel/jsuites
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Modal
+ */
+
+jSuites.modal = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ url: null,
+ onopen: null,
+ onclose: null,
+ closed: false,
+ width: null,
+ height: null,
+ title: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Title
+ if (! obj.options.title && el.getAttribute('title')) {
+ obj.options.title = el.getAttribute('title');
+ }
+
+ var temp = document.createElement('div');
+ for (var i = 0; i < el.children.length; i++) {
+ temp.appendChild(el.children[i]);
+ }
+
+ obj.content = document.createElement('div');
+ obj.content.className = 'jmodal_content';
+ obj.content.innerHTML = el.innerHTML;
+
+ for (var i = 0; i < temp.children.length; i++) {
+ obj.content.appendChild(temp.children[i]);
+ }
+
+ obj.container = document.createElement('div');
+ obj.container.className = 'jmodal';
+ obj.container.appendChild(obj.content);
+
+ if (obj.options.width) {
+ obj.container.style.width = obj.options.width;
+ }
+ if (obj.options.height) {
+ obj.container.style.height = obj.options.height;
+ }
+ if (obj.options.title) {
+ obj.container.setAttribute('title', obj.options.title);
+ } else {
+ obj.container.classList.add('no-title');
+ }
+ el.innerHTML = '';
+ el.style.display = 'none';
+ el.appendChild(obj.container);
+
+ // Backdrop
+ var backdrop = document.createElement('div');
+ backdrop.className = 'jmodal_backdrop';
+ el.appendChild(backdrop);
+
+ obj.open = function() {
+ el.style.display = 'block';
+ // Fullscreen
+ var rect = obj.container.getBoundingClientRect();
+ if (jSuites.getWindowWidth() < rect.width) {
+ obj.container.style.top = '';
+ obj.container.style.left = '';
+ obj.container.classList.add('jmodal_fullscreen');
+ jSuites.animation.slideBottom(obj.container, 1);
+ } else {
+ backdrop.style.display = 'block';
+ }
+ // Current
+ jSuites.modal.current = obj;
+ // Event
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el, obj);
+ }
+ }
+
+ obj.resetPosition = function() {
+ obj.container.style.top = '';
+ obj.container.style.left = '';
+ }
+
+ obj.isOpen = function() {
+ return el.style.display != 'none' ? true : false;
+ }
+
+ obj.close = function() {
+ el.style.display = 'none';
+ // Backdrop
+ backdrop.style.display = '';
+ // Current
+ jSuites.modal.current = null;
+ // Remove fullscreen class
+ obj.container.classList.remove('jmodal_fullscreen');
+ // Event
+ if (typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el, obj);
+ }
+ }
+
+ if (! jSuites.modal.hasEvents) {
+ jSuites.modal.current = obj;
+
+ if ('ontouchstart' in document.documentElement === true) {
+ document.addEventListener("touchstart", jSuites.modal.mouseDownControls);
+ } else {
+ document.addEventListener('mousedown', jSuites.modal.mouseDownControls);
+ document.addEventListener('mousemove', jSuites.modal.mouseMoveControls);
+ document.addEventListener('mouseup', jSuites.modal.mouseUpControls);
+ }
+
+ document.addEventListener('keydown', jSuites.modal.keyDownControls);
+
+ jSuites.modal.hasEvents = true;
+ }
+
+ if (obj.options.url) {
+ jSuites.ajax({
+ url: obj.options.url,
+ method: 'GET',
+ success: function(data) {
+ obj.content.innerHTML = data;
+
+ if (! obj.options.closed) {
+ obj.open();
+ }
+ }
+ });
+ } else {
+ if (! obj.options.closed) {
+ obj.open();
+ }
+ }
+
+ // Keep object available from the node
+ el.modal = obj;
+
+ return obj;
+});
+
+jSuites.modal.current = null;
+jSuites.modal.position = null;
+
+jSuites.modal.keyDownControls = function(e) {
+ if (e.which == 27) {
+ if (jSuites.modal.current) {
+ jSuites.modal.current.close();
+ }
+ }
+}
+
+jSuites.modal.mouseUpControls = function(e) {
+ if (jSuites.modal.current) {
+ jSuites.modal.current.container.style.cursor = 'auto';
+ }
+ jSuites.modal.position = null;
+}
+
+jSuites.modal.mouseMoveControls = function(e) {
+ if (jSuites.modal.current && jSuites.modal.position) {
+ if (e.which == 1 || e.which == 3) {
+ var position = jSuites.modal.position;
+ jSuites.modal.current.container.style.top = (position[1] + (e.clientY - position[3]) + (position[5] / 2)) + 'px';
+ jSuites.modal.current.container.style.left = (position[0] + (e.clientX - position[2]) + (position[4] / 2)) + 'px';
+ jSuites.modal.current.container.style.cursor = 'move';
+ } else {
+ jSuites.modal.current.container.style.cursor = 'auto';
+ }
+ }
+}
+
+jSuites.modal.mouseDownControls = function(e) {
+ jSuites.modal.position = [];
+
+ if (e.target.classList.contains('jmodal')) {
+ setTimeout(function() {
+ // Get target info
+ var rect = e.target.getBoundingClientRect();
+
+ if (e.changedTouches && e.changedTouches[0]) {
+ var x = e.changedTouches[0].clientX;
+ var y = e.changedTouches[0].clientY;
+ } else {
+ var x = e.clientX;
+ var y = e.clientY;
+ }
+
+ if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) {
+ setTimeout(function() {
+ jSuites.modal.current.close();
+ }, 100);
+ } else {
+ if (e.target.getAttribute('title') && (y - rect.top) < 50) {
+ if (document.selection) {
+ document.selection.empty();
+ } else if ( window.getSelection ) {
+ window.getSelection().removeAllRanges();
+ }
+
+ jSuites.modal.position = [
+ rect.left,
+ rect.top,
+ e.clientX,
+ e.clientY,
+ rect.width,
+ rect.height,
+ ];
+ }
+ }
+ }, 100);
+ }
+}
+
+
+jSuites.notification = (function(options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ icon: null,
+ name: 'Notification',
+ date: null,
+ error: null,
+ title: null,
+ message: null,
+ timeout: 4000,
+ autoHide: true,
+ closeable: true,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ var notification = document.createElement('div');
+ notification.className = 'jnotification';
+
+ if (obj.options.error) {
+ notification.classList.add('jnotification-error');
+ }
+
+ var notificationContainer = document.createElement('div');
+ notificationContainer.className = 'jnotification-container';
+ notification.appendChild(notificationContainer);
+
+ var notificationHeader = document.createElement('div');
+ notificationHeader.className = 'jnotification-header';
+ notificationContainer.appendChild(notificationHeader);
+
+ var notificationImage = document.createElement('div');
+ notificationImage.className = 'jnotification-image';
+ notificationHeader.appendChild(notificationImage);
+
+ if (obj.options.icon) {
+ var notificationIcon = document.createElement('img');
+ notificationIcon.src = obj.options.icon;
+ notificationImage.appendChild(notificationIcon);
+ }
+
+ var notificationName = document.createElement('div');
+ notificationName.className = 'jnotification-name';
+ notificationName.innerHTML = obj.options.name;
+ notificationHeader.appendChild(notificationName);
+
+ if (obj.options.closeable == true) {
+ var notificationClose = document.createElement('div');
+ notificationClose.className = 'jnotification-close';
+ notificationClose.onclick = function() {
+ obj.hide();
+ }
+ notificationHeader.appendChild(notificationClose);
+ }
+
+ var notificationDate = document.createElement('div');
+ notificationDate.className = 'jnotification-date';
+ notificationHeader.appendChild(notificationDate);
+
+ var notificationContent = document.createElement('div');
+ notificationContent.className = 'jnotification-content';
+ notificationContainer.appendChild(notificationContent);
+
+ if (obj.options.title) {
+ var notificationTitle = document.createElement('div');
+ notificationTitle.className = 'jnotification-title';
+ notificationTitle.innerHTML = obj.options.title;
+ notificationContent.appendChild(notificationTitle);
+ }
+
+ var notificationMessage = document.createElement('div');
+ notificationMessage.className = 'jnotification-message';
+ notificationMessage.innerHTML = obj.options.message;
+ notificationContent.appendChild(notificationMessage);
+
+ obj.show = function() {
+ document.body.appendChild(notification);
+ if (jSuites.getWindowWidth() > 800) {
+ jSuites.animation.fadeIn(notification);
+ } else {
+ jSuites.animation.slideTop(notification, 1);
+ }
+ }
+
+ obj.hide = function() {
+ if (jSuites.getWindowWidth() > 800) {
+ jSuites.animation.fadeOut(notification, function() {
+ if (notification.parentNode) {
+ notification.parentNode.removeChild(notification);
+ if (notificationTimeout) {
+ clearTimeout(notificationTimeout);
+ }
+ }
+ });
+ } else {
+ jSuites.animation.slideTop(notification, 0, function() {
+ if (notification.parentNode) {
+ notification.parentNode.removeChild(notification);
+ if (notificationTimeout) {
+ clearTimeout(notificationTimeout);
+ }
+ }
+ });
+ }
+ };
+
+ obj.show();
+
+ if (obj.options.autoHide == true) {
+ var notificationTimeout = setTimeout(function() {
+ obj.hide();
+ }, obj.options.timeout);
+ }
+
+ if (jSuites.getWindowWidth() < 800) {
+ notification.addEventListener("swipeup", function(e) {
+ obj.hide();
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ }
+
+ return obj;
+});
+
+jSuites.notification.isVisible = function() {
+ var j = document.querySelector('.jnotification');
+ return j && j.parentNode ? true : false;
+}
+
+// More palettes https://coolors.co/ or https://gka.github.io/palettes/#/10|s|003790,005647,ffffe0|ffffe0,ff005e,93003a|1|1
+
+jSuites.palette = function(o) {
+ // Material
+ var palette = {};
+
+ palette.material = [
+ [ "#ffebee", "#fce4ec", "#f3e5f5", "#e8eaf6", "#e3f2fd", "#e0f7fa", "#e0f2f1", "#e8f5e9", "#f1f8e9", "#f9fbe7", "#fffde7", "#fff8e1", "#fff3e0", "#fbe9e7", "#efebe9", "#fafafa", "#eceff1" ],
+ [ "#ffcdd2", "#f8bbd0", "#e1bee7", "#c5cae9", "#bbdefb", "#b2ebf2", "#b2dfdb", "#c8e6c9", "#dcedc8", "#f0f4c3", "#fff9c4", "#ffecb3", "#ffe0b2", "#ffccbc", "#d7ccc8", "#f5f5f5", "#cfd8dc" ],
+ [ "#ef9a9a", "#f48fb1", "#ce93d8", "#9fa8da", "#90caf9", "#80deea", "#80cbc4", "#a5d6a7", "#c5e1a5", "#e6ee9c", "#fff59d", "#ffe082", "#ffcc80", "#ffab91", "#bcaaa4", "#eeeeee", "#b0bec5" ],
+ [ "#e57373", "#f06292", "#ba68c8", "#7986cb", "#64b5f6", "#4dd0e1", "#4db6ac", "#81c784", "#aed581", "#dce775", "#fff176", "#ffd54f", "#ffb74d", "#ff8a65", "#a1887f", "#e0e0e0", "#90a4ae" ],
+ [ "#ef5350", "#ec407a", "#ab47bc", "#5c6bc0", "#42a5f5", "#26c6da", "#26a69a", "#66bb6a", "#9ccc65", "#d4e157", "#ffee58", "#ffca28", "#ffa726", "#ff7043", "#8d6e63", "#bdbdbd", "#78909c" ],
+ [ "#f44336", "#e91e63", "#9c27b0", "#3f51b5", "#2196f3", "#00bcd4", "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722", "#795548", "#9e9e9e", "#607d8b" ],
+ [ "#e53935", "#d81b60", "#8e24aa", "#3949ab", "#1e88e5", "#00acc1", "#00897b", "#43a047", "#7cb342", "#c0ca33", "#fdd835", "#ffb300", "#fb8c00", "#f4511e", "#6d4c41", "#757575", "#546e7a" ],
+ [ "#d32f2f", "#c2185b", "#7b1fa2", "#303f9f", "#1976d2", "#0097a7", "#00796b", "#388e3c", "#689f38", "#afb42b", "#fbc02d", "#ffa000", "#f57c00", "#e64a19", "#5d4037", "#616161", "#455a64" ],
+ [ "#c62828", "#ad1457", "#6a1b9a", "#283593", "#1565c0", "#00838f", "#00695c", "#2e7d32", "#558b2f", "#9e9d24", "#f9a825", "#ff8f00", "#ef6c00", "#d84315", "#4e342e", "#424242", "#37474f" ],
+ [ "#b71c1c", "#880e4f", "#4a148c", "#1a237e", "#0d47a1", "#006064", "#004d40", "#1b5e20", "#33691e", "#827717", "#f57f17", "#ff6f00", "#e65100", "#bf360c", "#3e2723", "#212121", "#263238" ],
+ ];
+
+ palette.fire = [
+ ["0b1a6d","840f38","b60718","de030b","ff0c0c","fd491c","fc7521","faa331","fbb535","ffc73a"],
+ ["071147","5f0b28","930513","be0309","ef0000","fa3403","fb670b","f9991b","faad1e","ffc123"],
+ ["03071e","370617","6a040f","9d0208","d00000","dc2f02","e85d04","f48c06","faa307","ffba08"],
+ ["020619","320615","61040d","8c0207","bc0000","c82a02","d05203","db7f06","e19405","efab00"],
+ ["020515","2d0513","58040c","7f0206","aa0000","b62602","b94903","c57205","ca8504","d89b00"],
+ ]
+
+ if (palette[o]) {
+ return palette[o];
+ } else {
+ return palette.material;
+ }
+}
+
+jSuites.picker = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ value: null,
+ data: null,
+ render: null,
+ onchange: null,
+ width: null,
+ header: true,
+ right: false,
+ content: false,
+ };
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Legacy purpose only
+ if (options.options) {
+ obj.options.data = options.options;
+ }
+
+ // Default value
+ if (obj.options.value === null) {
+ obj.options.value = Object.keys(obj.options.data)[0];
+ }
+
+ var dropdownHeader = null;
+ var dropdownContent = null;
+
+ // Class
+ el.classList.add('jpicker');
+ el.setAttribute('tabindex', '900');
+
+ /**
+ * Create floating picker
+ */
+ obj.init = function() {
+ // Dropdown Header
+ dropdownHeader = document.createElement('div');
+ dropdownHeader.classList.add('jpicker-header');
+
+ if (obj.options.header === false) {
+ dropdownHeader.style.display = 'none';
+ }
+
+ // Width
+ if (obj.options.width) {
+ dropdownHeader.style.width = parseInt(obj.options.width) + 'px';
+ }
+
+ // Start value
+ dropdownHeader.innerHTML = obj.options.value && obj.options.data[obj.options.value] ? obj.options.data[obj.options.value] : '<div><br/></div>';
+
+ // Dropdown content
+ dropdownContent = document.createElement('div');
+ dropdownContent.classList.add('jpicker-content');
+ el.appendChild(dropdownHeader);
+ el.appendChild(dropdownContent);
+
+ // Create items
+ var keys = Object.keys(obj.options.data);
+
+ // Go though all options
+ for (var i = 0; i < keys.length; i++) {
+ // Item
+ var dropdownItem = document.createElement('div');
+ dropdownItem.k = keys[i];
+ dropdownItem.v = obj.options.data[keys[i]];
+ // Label
+ dropdownItem.innerHTML = obj.getLabel(keys[i]);
+ // Onchange
+ dropdownItem.onclick = function() {
+ // Update label
+ obj.setValue(this.k);
+
+ // Call method
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, obj, this.v, this.k);
+ }
+ }
+
+ // Append
+ dropdownContent.appendChild(dropdownItem);
+ }
+
+ // Initial value
+ obj.setValue(obj.options.value);
+ }
+
+ obj.setValue = function(v) {
+ if (obj.options.content) {
+ var label = '<i class="material-icons">' + obj.options.content + '</i>';
+ } else {
+ var label = obj.getLabel(v);
+ }
+ dropdownHeader.innerHTML = label;
+ }
+
+ obj.getLabel = function(v) {
+ var label = obj.options.data[v];
+ if (typeof(obj.options.render) == 'function') {
+ label = obj.options.render(label);
+ }
+ return label;
+ }
+
+ obj.open = function() {
+ // Open picker
+ el.classList.add('jpicker-focus');
+ el.focus();
+
+ var rectHeader = dropdownHeader.getBoundingClientRect();
+ var rectContent = dropdownContent.getBoundingClientRect();
+
+ if (window.innerHeight < rectHeader.bottom + rectContent.height) {
+ dropdownContent.style.marginTop = -1 * (rectContent.height + 4) + 'px';
+ } else {
+ dropdownContent.style.marginTop = rectHeader.height + 2 + 'px';
+ }
+
+ if (obj.options.right === true) {
+ dropdownContent.style.marginLeft = -1 * rectContent.width + 24 + 'px';
+ }
+ }
+
+ el.onclick = function() {
+ if (! el.classList.contains('jpicker-focus')) {
+ obj.open();
+ } else {
+ el.classList.remove('jpicker-focus')
+ }
+ }
+
+ el.onblur = function() {
+ setTimeout(function() {
+ el.classList.remove('jpicker-focus');
+ }, 250);
+ }
+
+ obj.init();
+
+ el.picker = obj;
+
+ return obj;
+});
+
+
+jSuites.progressbar = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ value: 0,
+ onchange: null,
+ width: null,
+ };
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Class
+ el.classList.add('jprogressbar');
+ el.setAttribute('tabindex', 1);
+ el.setAttribute('data-value', obj.options.value);
+
+ var bar = document.createElement('div');
+ bar.style.width = obj.options.value + '%';
+ bar.style.color = '#fff';
+ el.appendChild(bar);
+
+ if (obj.options.width) {
+ el.style.width = obj.options.width;
+ }
+
+ // Set value
+ obj.setValue = function(value) {
+ value = parseInt(value);
+ obj.options.value = value;
+ bar.style.width = value + '%';
+ el.setAttribute('data-value', value + '%');
+
+ if (value < 6) {
+ el.style.color = '#000';
+ } else {
+ el.style.color = '#fff';
+ }
+
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, value);
+ }
+ }
+
+ obj.getValue = function() {
+ return obj.options.value;
+ }
+
+ var action = function(e) {
+ if (e.which) {
+ // Get target info
+ var rect = el.getBoundingClientRect();
+
+ if (e.changedTouches && e.changedTouches[0]) {
+ var x = e.changedTouches[0].clientX;
+ var y = e.changedTouches[0].clientY;
+ } else {
+ var x = e.clientX;
+ var y = e.clientY;
+ }
+
+ obj.setValue(Math.round((x - rect.left) / rect.width * 100));
+ }
+ }
+
+ // Events
+ if ('touchstart' in document.documentElement === true) {
+ el.addEventListener('touchstart', action);
+ el.addEventListener('touchend', action);
+ } else {
+ el.addEventListener('mousedown', action);
+ el.addEventListener("mousemove", action);
+ }
+
+ el.progressbar = obj;
+
+ return obj;
+});
+
+jSuites.rating = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ number: 5,
+ value: 0,
+ tooltip: [ 'Very bad', 'Bad', 'Average', 'Good', 'Very good' ],
+ onchange: null,
+ };
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Class
+ el.classList.add('jrating');
+
+ // Add elements
+ for (var i = 0; i < obj.options.number; i++) {
+ var div = document.createElement('div');
+ div.setAttribute('data-index', (i + 1))
+ div.setAttribute('title', obj.options.tooltip[i])
+ el.appendChild(div);
+ }
+
+ // Set value
+ obj.setValue = function(index) {
+ for (var i = 0; i < obj.options.number; i++) {
+ if (i < index) {
+ el.children[i].classList.add('jrating-selected');
+ } else {
+ el.children[i].classList.remove('jrating-over');
+ el.children[i].classList.remove('jrating-selected');
+ }
+ }
+
+ obj.options.value = index;
+
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, index);
+ }
+ }
+
+ obj.getValue = function() {
+ return obj.options.value;
+ }
+
+ if (obj.options.value) {
+ for (var i = 0; i < obj.options.number; i++) {
+ if (i < obj.options.value) {
+ el.children[i].classList.add('jrating-selected');
+ }
+ }
+ }
+
+ // Events
+ el.addEventListener("click", function(e) {
+ var index = e.target.getAttribute('data-index');
+ if (index != undefined) {
+ if (index == obj.options.value) {
+ obj.setValue(0);
+ } else {
+ obj.setValue(index);
+ }
+ }
+ });
+
+ el.addEventListener("mouseover", function(e) {
+ var index = e.target.getAttribute('data-index');
+ for (var i = 0; i < obj.options.number; i++) {
+ if (i < index) {
+ el.children[i].classList.add('jrating-over');
+ } else {
+ el.children[i].classList.remove('jrating-over');
+ }
+ }
+ });
+
+ el.addEventListener("mouseout", function(e) {
+ for (var i = 0; i < obj.options.number; i++) {
+ el.children[i].classList.remove('jrating-over');
+ }
+ });
+
+ el.rating = obj;
+
+ return obj;
+});
+
+
+/**
+ * (c) Image slider
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Image Slider
+ */
+
+jSuites.slider = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+ obj.currentImage = null;
+
+ if (options) {
+ obj.options = options;
+ }
+
+ // Items
+ obj.options.items = [];
+
+ if (! el.classList.contains('jslider')) {
+ el.classList.add('jslider');
+
+ // Create container
+ var container = document.createElement('div');
+ container.className = 'jslider-container';
+
+ // Move children inside
+ if (el.children.length > 0) {
+ // Keep children items
+ for (var i = 0; i < el.children.length; i++) {
+ obj.options.items.push(el.children[i]);
+ }
+ }
+ if (obj.options.items.length > 0) {
+ for (var i = 0; i < obj.options.items.length; i++) {
+ obj.options.items[i].classList.add('jfile');
+ var index = obj.options.items[i].src.lastIndexOf('/');
+ if (index < 0) {
+ obj.options.items[i].setAttribute('data-name', obj.options.items[i].src);
+ } else {
+ obj.options.items[i].setAttribute('data-name', obj.options.items[i].src.substr(index + 1));
+ }
+ var index = obj.options.items[i].src.lastIndexOf('/');
+
+ container.appendChild(obj.options.items[i]);
+ }
+ }
+ el.appendChild(container);
+ // Add close buttom
+ var close = document.createElement('div');
+ close.className = 'jslider-close';
+ close.innerHTML = '';
+ close.onclick = function() {
+ obj.close();
+ }
+ el.appendChild(close);
+ } else {
+ var container = el.querySelector('slider-container');
+ }
+
+ obj.show = function(target) {
+ if (! target) {
+ var target = container.children[0];
+ }
+
+ if (! container.classList.contains('jslider-preview')) {
+ container.classList.add('jslider-preview');
+ close.style.display = 'block';
+ }
+
+ // Hide all images
+ for (var i = 0; i < container.children.length; i++) {
+ container.children[i].style.display = 'none';
+ }
+
+ // Show clicked only
+ target.style.display = 'block';
+
+ // Is there any previous
+ if (target.previousSibling) {
+ container.classList.add('jslider-left');
+ } else {
+ container.classList.remove('jslider-left');
+ }
+
+ // Is there any next
+ if (target.nextSibling) {
+ container.classList.add('jslider-right');
+ } else {
+ container.classList.remove('jslider-right');
+ }
+
+ obj.currentImage = target;
+ }
+
+ obj.open = function() {
+ obj.show();
+
+ // Event
+ if (typeof(obj.options.onopen) == 'function') {
+ obj.options.onopen(el);
+ }
+ }
+
+ obj.close = function() {
+ container.classList.remove('jslider-preview');
+ container.classList.remove('jslider-left');
+ container.classList.remove('jslider-right');
+
+ for (var i = 0; i < container.children.length; i++) {
+ container.children[i].style.display = '';
+ }
+
+ close.style.display = '';
+
+ obj.currentImage = null;
+
+ // Event
+ if (typeof(obj.options.onclose) == 'function') {
+ obj.options.onclose(el);
+ }
+ }
+
+ obj.reset = function() {
+ container.innerHTML = '';
+ }
+
+ obj.addFile = function(v, ignoreEvents) {
+ var img = document.createElement('img');
+ img.setAttribute('data-lastmodified', v.lastmodified);
+ img.setAttribute('data-name', v.name);
+ img.setAttribute('data-size', v.size);
+ img.setAttribute('data-extension', v.extension);
+ img.setAttribute('data-cover', v.cover);
+ img.setAttribute('src', v.file);
+ img.className = 'jfile';
+ container.appendChild(img);
+ obj.options.items.push(img);
+
+ // Onchange
+ if (! ignoreEvents) {
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, v);
+ }
+ }
+ }
+
+ obj.addFiles = function(files) {
+ for (var i = 0; i < files.length; i++) {
+ obj.addFile(files[i]);
+ }
+ }
+
+ obj.next = function() {
+ if (obj.currentImage.nextSibling) {
+ obj.show(obj.currentImage.nextSibling);
+ }
+ }
+
+ obj.prev = function() {
+ if (obj.currentImage.previousSibling) {
+ obj.show(obj.currentImage.previousSibling);
+ }
+ }
+
+ obj.getData = function() {
+ return jSuites.files(container).get();
+ }
+
+ // Append data
+ if (obj.options.data && obj.options.data.length) {
+ for (var i = 0; i < obj.options.data.length; i++) {
+ if (obj.options.data[i]) {
+ obj.addFile(obj.options.data[i]);
+ }
+ }
+ }
+
+ // Allow insert
+ if (obj.options.allowAttachment) {
+ var attachmentInput = document.createElement('input');
+ attachmentInput.type = 'file';
+ attachmentInput.className = 'slider-attachment';
+ attachmentInput.setAttribute('accept', 'image/*');
+ attachmentInput.style.display = 'none';
+ attachmentInput.onchange = function() {
+ var reader = [];
+
+ for (var i = 0; i < this.files.length; i++) {
+ var type = this.files[i].type.split('/');
+
+ if (type[0] == 'image') {
+ var extension = this.files[i].name;
+ extension = extension.split('.');
+ extension = extension[extension.length-1];
+
+ var file = {
+ size: this.files[i].size,
+ name: this.files[i].name,
+ extension: extension,
+ cover: 0,
+ lastmodified: this.files[i].lastModified,
+ }
+
+ reader[i] = new FileReader();
+ reader[i].addEventListener("load", function (e) {
+ file.file = e.target.result;
+ obj.addFile(file);
+ }, false);
+
+ reader[i].readAsDataURL(this.files[i]);
+ } else {
+ alert('The extension is not allowed');
+ }
+ };
+ }
+
+ var attachmentIcon = document.createElement('i');
+ attachmentIcon.innerHTML = 'attachment';
+ attachmentIcon.className = 'jslider-attach material-icons';
+ attachmentIcon.onclick = function() {
+ jSuites.click(attachmentInput);
+ }
+
+ el.appendChild(attachmentInput);
+ el.appendChild(attachmentIcon);
+ }
+
+ // Push to refresh
+ var longTouchTimer = null;
+
+ var mouseDown = function(e) {
+ if (e.target.tagName == 'IMG') {
+ // Remove
+ var targetImage = e.target;
+ longTouchTimer = setTimeout(function() {
+ if (e.target.src.substr(0,4) == 'data') {
+ e.target.remove();
+ } else {
+ if (e.target.classList.contains('jremove')) {
+ e.target.classList.remove('jremove');
+ } else {
+ e.target.classList.add('jremove');
+ }
+ }
+
+ // Onchange
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, e.target);
+ }
+ }, 1000);
+ }
+ }
+
+ var mouseUp = function(e) {
+ if (longTouchTimer) {
+ clearTimeout(longTouchTimer);
+ }
+
+ // Open slider
+ if (e.target.tagName == 'IMG') {
+ if (! e.target.classList.contains('jremove')) {
+ obj.show(e.target);
+ }
+ } else {
+ // Arrow controls
+ if (e.target.clientWidth - e.offsetX < 40) {
+ // Show next image
+ obj.next();
+ } else if (e.offsetX < 40) {
+ // Show previous image
+ obj.prev();
+ }
+ }
+ }
+
+ container.addEventListener('mousedown', mouseDown);
+ container.addEventListener('touchstart', mouseDown);
+ container.addEventListener('mouseup', mouseUp);
+ container.addEventListener('touchend', mouseUp);
+
+ // Add global events
+ el.addEventListener("swipeleft", function(e) {
+ obj.next();
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ el.addEventListener("swiperight", function(e) {
+ obj.prev();
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ if (! jSuites.slider.hasEvents) {
+ document.addEventListener('keydown', function(e) {
+ if (e.which == 27) {
+ obj.close();
+ }
+ });
+
+ jSuites.slider.hasEvents = true;
+ }
+
+ el.slider = obj;
+
+ return obj;
+});
+
+/**
+ * (c) jTools v1.0.1 - Element sorting
+ * https://github.com/paulhodel/jtools
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Element drag and drop sorting
+ */
+
+jSuites.sorting = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ var defaults = {
+ pointer: null,
+ direction: null,
+ ondragstart: null,
+ ondragend: null,
+ ondrop: null,
+ }
+
+ var dragElement = null;
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ el.classList.add('jsorting');
+
+ el.addEventListener('dragstart', function(e) {
+ var position = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
+ dragElement = {
+ element: e.target,
+ o: position,
+ d: position
+ }
+ e.target.style.opacity = '0.25';
+
+ if (typeof(obj.options.ondragstart) == 'function') {
+ obj.options.ondragstart(el, e.target, e);
+ }
+ });
+
+ el.addEventListener('dragover', function(e) {
+ e.preventDefault();
+
+ if (getElement(e.target) && dragElement) {
+ if (e.target.getAttribute('draggable') == 'true' && dragElement.element != e.target) {
+ if (! obj.options.direction) {
+ var condition = e.target.clientHeight / 2 > e.offsetY;
+ } else {
+ var condition = e.target.clientWidth / 2 > e.offsetX;
+ }
+
+ if (condition) {
+ e.target.parentNode.insertBefore(dragElement.element, e.target);
+ } else {
+ e.target.parentNode.insertBefore(dragElement.element, e.target.nextSibling);
+ }
+
+ dragElement.d = Array.prototype.indexOf.call(e.target.parentNode.children, dragElement.element);
+ }
+ }
+ });
+
+ el.addEventListener('dragleave', function(e) {
+ e.preventDefault();
+ });
+
+ el.addEventListener('dragend', function(e) {
+ e.preventDefault();
+
+ if (dragElement) {
+ if (typeof(obj.options.ondragend) == 'function') {
+ obj.options.ondragend(el, dragElement.element, e);
+ }
+
+ // Cancelled put element to the original position
+ if (dragElement.o < dragElement.d) {
+ e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o]);
+ } else {
+ e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o].nextSibling);
+ }
+
+ dragElement.element.style.opacity = '';
+ dragElement = null;
+ }
+ });
+
+ el.addEventListener('drop', function(e) {
+ e.preventDefault();
+
+ if (dragElement && (dragElement.o != dragElement.d)) {
+ if (typeof(obj.options.ondrop) == 'function') {
+ obj.options.ondrop(el, dragElement.o, dragElement.d, dragElement.element, e.target, e);
+ }
+ }
+
+ dragElement.element.style.opacity = '';
+ dragElement = null;
+ });
+
+ var getElement = function(element) {
+ var sorting = false;
+
+ function path (element) {
+ if (element.className) {
+ if (element.classList.contains('jsorting')) {
+ sorting = true;
+ }
+ }
+
+ if (! sorting) {
+ path(element.parentNode);
+ }
+ }
+
+ path(element);
+
+ return sorting;
+ }
+
+ for (var i = 0; i < el.children.length; i++) {
+ if (! el.children[i].hasAttribute('draggable')) {
+ el.children[i].setAttribute('draggable', 'true');
+ }
+ }
+
+ return el;
+});
+
+jSuites.tabs = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ data: [],
+ position: null,
+ allowCreate: false,
+ allowChangePosition: false,
+ onclick: null,
+ onload: null,
+ onchange: null,
+ oncreate: null,
+ ondelete: null,
+ onbeforecreate: null,
+ onchangeposition: null,
+ animation: false,
+ hideHeaders: false,
+ padding: null,
+ }
+
+ // Loop through the initial configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Class
+ el.classList.add('jtabs');
+
+ var prev = null;
+ var next = null;
+ var border = null;
+
+ // Helpers
+ var setBorder = function(index) {
+ var rect = obj.headers.children[index].getBoundingClientRect();
+ border.style.width = rect.width + 'px';
+ border.style.left = (obj.headers.children[index].offsetLeft) + 'px';
+ border.style.bottom = '0px';
+ }
+
+ var updateControls = function(x) {
+ if (typeof(obj.headers.scrollTo) == 'function') {
+ obj.headers.scrollTo({
+ left: x,
+ behavior: 'smooth',
+ });
+ } else {
+ obj.headers.scrollLeft = x;
+ }
+
+ if (x <= 1) {
+ prev.classList.add('disabled');
+ } else {
+ prev.classList.remove('disabled');
+ }
+
+ if (x >= obj.headers.scrollWidth - obj.headers.offsetWidth) {
+ next.classList.add('disabled');
+ } else {
+ next.classList.remove('disabled');
+ }
+
+ if (obj.headers.scrollWidth <= obj.headers.offsetWidth) {
+ prev.style.display = 'none';
+ next.style.display = 'none';
+ } else {
+ prev.style.display = '';
+ next.style.display = '';
+ }
+ }
+
+ // Set value
+ obj.open = function(index) {
+ var previous = null;
+ for (var i = 0; i < obj.headers.children.length; i++) {
+ if (obj.headers.children[i].classList.contains('jtabs-selected')) {
+ // Current one
+ previous = i;
+ // Remote selected
+ obj.headers.children[i].classList.remove('jtabs-selected');
+ if (obj.content.children[i]) {
+ obj.content.children[i].classList.remove('jtabs-selected');
+ }
+ }
+ }
+
+ obj.headers.children[index].classList.add('jtabs-selected');
+ if (obj.content.children[index]) {
+ obj.content.children[index].classList.add('jtabs-selected');
+ }
+
+ if (previous != index && typeof(obj.options.onchange) == 'function') {
+ if (obj.content.children[index]) {
+ obj.options.onchange(el, obj, index, obj.headers.children[index], obj.content.children[index]);
+ }
+ }
+
+ // Hide
+ if (obj.options.hideHeaders == true && (obj.headers.children.length < 3 && obj.options.allowCreate == false)) {
+ obj.headers.parentNode.style.display = 'none';
+ } else {
+ obj.headers.parentNode.style.display = '';
+ // Set border
+ if (obj.options.animation == true) {
+ setBorder(index);
+ }
+
+ var x1 = obj.headers.children[index].offsetLeft;
+ var x2 = x1 + obj.headers.children[index].offsetWidth;
+ var r1 = obj.headers.scrollLeft;
+ var r2 = r1 + obj.headers.offsetWidth;
+
+ if (! (r1 <= x1 && r2 >= x2)) {
+ // Out of the viewport
+ updateControls(x1 - 1);
+ }
+ }
+ }
+
+ obj.selectIndex = function(a) {
+ var index = Array.prototype.indexOf.call(obj.headers.children, a);
+ if (index >= 0) {
+ obj.open(index);
+ }
+
+ return index;
+ }
+
+ obj.rename = function(i, title) {
+ if (! title) {
+ title = prompt('New title', obj.headers.children[i].innerText);
+ }
+ obj.headers.children[i].innerText = title;
+ obj.open(i);
+ }
+
+ obj.create = function(title, url) {
+ if (typeof(obj.options.onbeforecreate) == 'function') {
+ var ret = obj.options.onbeforecreate(el);
+ if (ret === false) {
+ return false;
+ } else {
+ title = ret;
+ }
+ }
+
+ var div = obj.appendElement(title);
+
+ if (typeof(obj.options.oncreate) == 'function') {
+ obj.options.oncreate(el, div)
+ }
+
+ return div;
+ }
+
+ obj.remote = function(index) {
+ return obj.deleteElement(index);
+ }
+
+ obj.nextNumber = function() {
+ var num = 0;
+ for (var i = 0; i < obj.headers.children.length; i++) {
+ var tmp = obj.headers.children[i].innerText.match(/[0-9].*/);
+ if (tmp > num) {
+ num = parseInt(tmp);
+ }
+ }
+ if (! num) {
+ num = 1;
+ } else {
+ num++;
+ }
+
+ return num;
+ }
+
+ obj.deleteElement = function(index) {
+ if (! obj.headers.children[index]) {
+ return false;
+ } else {
+ obj.headers.removeChild(obj.headers.children[index]);
+ obj.content.removeChild(obj.content.children[index]);
+ }
+
+ obj.open(0);
+
+ if (typeof(obj.options.ondelete) == 'function') {
+ obj.options.ondelete(el, index)
+ }
+ }
+
+ obj.appendElement = function(title) {
+ if (! title) {
+ var title = prompt('Title?', '');
+ }
+
+ if (title) {
+ // Add content
+ var div = document.createElement('div');
+ obj.content.appendChild(div);
+
+ // Add headers
+ var h = document.createElement('div');
+ h.innerHTML = title;
+ h.content = div;
+ obj.headers.insertBefore(h, obj.headers.lastChild);
+
+ // Sortable
+ if (obj.options.allowChangePosition) {
+ h.setAttribute('draggable', 'true');
+ }
+ // Open new tab
+ obj.selectIndex(h);
+
+ // Return element
+ return div;
+ }
+ }
+
+ obj.init = function() {
+ el.innerHTML = '';
+
+ // Make sure the component is blank
+ obj.headers = document.createElement('div');
+ obj.content = document.createElement('div');
+ obj.headers.classList.add('jtabs-headers');
+ obj.content.classList.add('jtabs-content');
+
+ // Padding
+ if (obj.options.padding) {
+ obj.content.style.padding = parseInt(obj.options.padding) + 'px';
+ }
+
+ // Header
+ var header = document.createElement('div');
+ header.className = 'jtabs-headers-container';
+ header.appendChild(obj.headers);
+
+ // Controls
+ var controls = document.createElement('div');
+ controls.className = 'jtabs-controls';
+ controls.setAttribute('draggable', 'false');
+ header.appendChild(controls);
+
+ // Append DOM elements
+ el.appendChild(header);
+ el.appendChild(obj.content);
+
+ // New button
+ if (obj.options.allowCreate == true) {
+ var add = document.createElement('div');
+ add.className = 'jtabs-add';
+ add.onclick = function() {
+ obj.create();
+ }
+ controls.appendChild(add);
+ }
+
+ prev = document.createElement('div');
+ prev.className = 'jtabs-prev';
+ prev.onclick = function() {
+ updateControls(obj.headers.scrollLeft - obj.headers.offsetWidth);
+ }
+ controls.appendChild(prev);
+
+ next = document.createElement('div');
+ next.className = 'jtabs-next';
+ next.onclick = function() {
+ updateControls(obj.headers.scrollLeft + obj.headers.offsetWidth);
+ }
+ controls.appendChild(next);
+
+ // Data
+ for (var i = 0; i < obj.options.data.length; i++) {
+ var headerItem = document.createElement('div');
+ var contentItem = document.createElement('div');
+ headerItem.innerText = obj.options.data[i].title;
+ contentItem.innerHTML = obj.options.data[i].content;
+ obj.headers.appendChild(headerItem);
+ obj.content.appendChild(contentItem);
+ }
+
+ // Animation
+ border = document.createElement('div');
+ border.className = 'jtabs-border';
+ obj.headers.appendChild(border);
+
+ if (obj.options.animation) {
+ el.classList.add('jtabs-animation');
+ }
+
+ // Events
+ obj.headers.addEventListener("click", function(e) {
+ var index = obj.selectIndex(e.target);
+
+ if (typeof(obj.options.onclick) == 'function') {
+ obj.options.onclick(el, obj, index, obj.headers.children[index], obj.content.children[index]);
+ }
+ });
+
+ obj.headers.addEventListener("contextmenu", function(e) {
+ obj.selectIndex(e.target);
+ });
+
+ if (obj.headers.children.length) {
+ // Open first tab
+ obj.open(0);
+ }
+
+ // Update controls
+ updateControls(0);
+
+ if (obj.options.allowChangePosition == true) {
+ jSuites.sorting(obj.headers, {
+ direction: 1,
+ ondrop: function(a,b,c,d,e,f) {
+ // Ondrop update position of content
+ if (b > c) {
+ obj.content.insertBefore(obj.content.children[b], obj.content.children[c]);
+ } else {
+ obj.content.insertBefore(obj.content.children[b], obj.content.children[c].nextSibling);
+ }
+ // Open destination tab
+ obj.open(c);
+ // Call event
+ if (typeof(obj.options.onchangeposition) == 'function') {
+ obj.options.onchangeposition(a,b,c,d,e,f);
+ }
+ },
+ });
+ }
+
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj);
+ }
+ }
+
+ // Loading existing nodes as the data
+ if (el.children[0] && el.children[1]) {
+ // Create from existing elements
+ for (var i = 0; i < el.children[0].children.length; i++) {
+ if (el.children[1].children[i] && el.children[0].children[i].innerHTML) {
+ var title = el.children[0].children[i].innerText;
+ var content = el.children[1].children[i].innerHTML;
+ } else {
+ var title = 'Tab ' + (i + 1);
+ var content = el.children[0].children[i].innerHTML;
+ }
+
+ obj.options.data.push({ title: title, content: content });
+ }
+ }
+
+ // Remote controller flag
+ var loadingRemoteData = false;
+
+ // Create from data
+ if (obj.options.data) {
+ // Append children
+ for (var i = 0; i < obj.options.data.length; i++) {
+ if (obj.options.data[i].url) {
+ jSuites.ajax({
+ url: obj.options.data[i].url,
+ type: 'GET',
+ dataType: 'text/html',
+ index: i,
+ success: function(result) {
+ obj.options.data[this.index].content = result;
+ },
+ complete: function() {
+ obj.init();
+ }
+ });
+
+ // Flag loading
+ loadingRemoteData = true;
+ }
+ }
+ }
+
+ if (! loadingRemoteData) {
+ obj.init();
+ }
+
+ el.tabs = obj;
+
+ return obj;
+});
+
+jSuites.tags = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ /**
+ * @typedef {Object} defaults
+ * @property {(string|Array)} value - Initial value of the compontent
+ * @property {number} limit - Max number of tags inside the element
+ * @property {string} search - The URL for suggestions
+ * @property {string} placeholder - The default instruction text on the element
+ * @property {validation} validation - Method to validate the tags
+ * @property {requestCallback} onbeforechange - Method to be execute before any changes on the element
+ * @property {requestCallback} onchange - Method to be execute after any changes on the element
+ * @property {requestCallback} onfocus - Method to be execute when on focus
+ * @property {requestCallback} onblur - Method to be execute when on blur
+ * @property {requestCallback} onload - Method to be execute when the element is loaded
+ */
+ var defaults = {
+ value: null,
+ limit: null,
+ limitMessage: 'The limit of entries is: ',
+ search: null,
+ placeholder: null,
+ validation: null,
+ onbeforechange: null,
+ onchange: null,
+ onfocus: null,
+ onblur: null,
+ onload: null,
+ colors: null,
+ };
+
+ // Loop through though the default configuration
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Search helpers
+ var searchContainer = null;
+ var searchTerms = null;
+ var searchIndex = 0;
+ var searchTimer = 0;
+
+ // Change methods
+ el.change = obj.setValue;
+
+ /**
+ * Add a new tag to the element
+ * @param {(?string|Array)} value - The value of the new element
+ */
+ obj.add = function(value, focus) {
+ if (typeof(obj.options.onbeforechange) == 'function') {
+ var v = obj.options.onbeforechange(el, obj, value);
+ if (v != null) {
+ value = v;
+ }
+ }
+
+ // Close search
+ if (searchContainer) {
+ searchContainer.style.display = '';
+ }
+
+ if (obj.options.limit > 0 && el.children.length >= obj.options.limit) {
+ alert(obj.options.limitMessage + ' ' + obj.options.limit);
+ } else {
+ // Get node
+ var node = getSelectionStart();
+
+ // Mix argument string or array
+ if (! value || typeof(value) == 'string') {
+ var div = document.createElement('div');
+ div.innerHTML = value ? value : '<br>';
+ if (node && node.parentNode.classList.contains('jtags')) {
+ el.insertBefore(div, node.nextSibling);
+ } else {
+ el.appendChild(div);
+ }
+ } else {
+ if (node && node.parentNode.classList.contains('jtags')) {
+ if (! node.innerText.replace("\n", "")) {
+ el.removeChild(node);
+ }
+ }
+
+ for (var i = 0; i <= value.length; i++) {
+ if (! obj.options.limit || el.children.length < obj.options.limit) {
+ var div = document.createElement('div');
+ div.innerHTML = value[i] ? value[i] : '<br>';
+ el.appendChild(div);
+ }
+ }
+ }
+
+ // Place caret
+ if (focus) {
+ setTimeout(function() {
+ caret(div);
+ }, 0);
+ }
+
+ // Filter
+ filter();
+
+ // Change
+ change();
+ }
+ }
+
+ obj.remove = function(node) {
+ // Remove node
+ node.parentNode.removeChild(node);
+ if (! el.children.length) {
+ obj.add('');
+ }
+ }
+
+ /**
+ * Get all tags in the element
+ * @return {Array} data - All tags as an array
+ */
+ obj.getData = function() {
+ var data = [];
+ for (var i = 0; i < el.children.length; i++) {
+ // Get value
+ var text = el.children[i].innerText.replace("\n", "");
+ // Get id
+ var value = el.children[i].getAttribute('data-value');
+ if (! value) {
+ value = text;
+ }
+ // Item
+ if (text || value) {
+ data.push({ text: text, value: value });
+ }
+ }
+ return data;
+ }
+
+ /**
+ * Get the value of one tag. Null for all tags
+ * @param {?number} index - Tag index number. Null for all tags.
+ * @return {string} value - All tags separated by comma
+ */
+ obj.getValue = function(index) {
+ var value = null;
+
+ if (index != null) {
+ // Get one individual value
+ value = el.children[index].getAttribute('data-value');
+ if (! value) {
+ value = el.children[index].innerText.replace("\n", "");
+ }
+ } else {
+ // Get all
+ var data = [];
+ for (var i = 0; i < el.children.length; i++) {
+ value = el.children[i].innerText.replace("\n", "");
+ if (value) {
+ data.push(obj.getValue(i));
+ }
+ }
+ value = data.join(',');
+ }
+
+ return value;
+ }
+
+ /**
+ * Set the value of the element based on a string separeted by (,|;|\r\n)
+ * @param {string} value - A string with the tags
+ */
+ obj.setValue = function(text) {
+ // Remove whitespaces
+ text = text.trim();
+
+ if (text) {
+ // Tags
+ var data = extractTags(text);
+ // Add tags to the element
+ obj.add(data);
+ }
+ }
+
+ obj.reset = function() {
+ el.innerHTML = '<div><br></div>';
+
+ change();
+ }
+
+ /**
+ * Verify if all tags in the element are valid
+ * @return {boolean}
+ */
+ obj.isValid = function() {
+ var test = 0;
+ for (var i = 0; i < el.children.length; i++) {
+ if (el.children[i].classList.contains('jtags_error')) {
+ test++;
+ }
+ }
+ return test == 0 ? true : false;
+ }
+
+ /**
+ * Add one element from the suggestions to the element
+ * @param {object} item - Node element in the suggestions container
+ */
+ obj.selectIndex = function(item) {
+ // Reset terms
+ searchTerms = '';
+ var node = getSelectionStart();
+ // Append text to the caret
+ node.innerText = item.children[1].innerText;
+ // Set node id
+ if (item.children[1].getAttribute('data-value')) {
+ node.setAttribute('data-value', item.children[1].getAttribute('data-value'));
+ }
+ // Close container
+ if (searchContainer) {
+ searchContainer.style.display = '';
+ searchContainer.innerHTML = '';
+ }
+ // Remove any error
+ node.classList.remove('jtags_error');
+ // Add new item
+ obj.add();
+ }
+
+ /**
+ * Search for suggestions
+ * @param {object} node - Target node for any suggestions
+ */
+ obj.search = function(node) {
+ // Create and append search container to the DOM
+ if (! searchContainer) {
+ var div = document.createElement('div');
+ div.style.position = 'relative';
+ el.parentNode.insertBefore(div, el.nextSibling);
+
+ // Create container
+ searchContainer = document.createElement('div');
+ searchContainer.classList.add('jtags_search');
+ div.appendChild(searchContainer);
+ }
+
+ // Search for
+ var terms = node.anchorNode.nodeValue;
+
+ // Search
+ if (node.anchorNode.nodeValue && terms != searchTerms) {
+ // Terms
+ searchTerms = node.anchorNode.nodeValue;
+ // Reset index
+ searchIndex = 0;
+ // Get remove results
+ jSuites.ajax({
+ url: obj.options.search + searchTerms,
+ method: 'GET',
+ dataType: 'json',
+ success: function(data) {
+ // Reset container
+ searchContainer.innerHTML = '';
+
+ // Print results
+ if (! data.length) {
+ // Show container
+ searchContainer.style.display = '';
+ } else {
+ // Show container
+ searchContainer.style.display = 'block';
+
+ // Show items
+ var len = data.length < 11 ? data.length : 10;
+ for (var i = 0; i < len; i++) {
+ // Legacy
+ var text = data[i].text;
+ if (! text && data[i].name) {
+ text = data[i].name;
+ }
+ var value = data[i].value;
+ if (! value && data[i].id) {
+ value = data[i].id;
+ }
+
+ var div = document.createElement('div');
+ if (i == 0) {
+ div.classList.add('selected');
+ }
+ var img = document.createElement('img');
+ if (data[i].image) {
+ img.src = data[i].image;
+ } else {
+ img.style.display = 'none';
+ }
+ div.appendChild(img);
+
+ var item = document.createElement('div');
+ item.setAttribute('data-value', value);
+ item.innerHTML = text;
+ div.onclick = function() {
+ // Add item
+ obj.selectIndex(this);
+ }
+ div.appendChild(item);
+ // Append item to the container
+ searchContainer.appendChild(div);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ // Destroy tags element
+ obj.destroy = function() {
+ // Bind events
+ el.removeEventListener('mouseup', tagsMouseUp);
+ el.removeEventListener('keydown', tagsKeyDown);
+ el.removeEventListener('keyup', tagsKeyUp);
+ el.removeEventListener('paste', tagsPaste);
+ el.removeEventListener('focus', tagsFocus);
+ el.removeEventListener('blur', tagsBlur);
+ // Remove element
+ el.parentNode.removeChild(el);
+ }
+
+ var change = function() {
+ // Events
+ if (typeof(el.onchange) == 'function') {
+ el.onchange({ type: 'change', target: el });
+ }
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, obj, value ? value : '');
+ }
+ }
+
+ var getRandomColor = function(index) {
+ var rand = function(min, max) {
+ return min + Math.random() * (max - min);
+ }
+ return 'hsl(' + rand(1, 360) + ',' + rand(40, 70) + '%,' + rand(65, 72) + '%)';
+ }
+
+ /**
+ * Filter tags
+ */
+ var filter = function() {
+ for (var i = 0; i < el.children.length; i++) {
+ // Create label design
+ if (! obj.getValue(i)) {
+ el.children[i].classList.remove('jtags_label');
+ } else {
+ el.children[i].classList.add('jtags_label');
+
+ // Validation in place
+ if (typeof(obj.options.validation) == 'function') {
+ if (obj.getValue(i)) {
+ if (! obj.options.validation(el.children[i], el.children[i].innerText, el.children[i].getAttribute('data-value'))) {
+ el.children[i].classList.add('jtags_error');
+ } else {
+ el.children[i].classList.remove('jtags_error');
+ }
+ } else {
+ el.children[i].classList.remove('jtags_error');
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Place caret in the element node
+ */
+ var caret = function(e) {
+ var range = document.createRange();
+ var sel = window.getSelection();
+ range.setStart(e, e.innerText.length);
+ range.collapse(true);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+
+ /**
+ * Selection
+ */
+ var getSelectionStart = function() {
+ var node = document.getSelection().anchorNode;
+ if (node) {
+ return (node.nodeType == 3 ? node.parentNode : node);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Extract tags from a string
+ * @param {string} text - Raw string
+ * @return {Array} data - Array with extracted tags
+ */
+ var extractTags = function(text) {
+ /** @type {Array} */
+ var data = [];
+
+ /** @type {string} */
+ var word = '';
+
+ // Remove whitespaces
+ text = text.trim();
+
+ if (text) {
+ for (var i = 0; i < text.length; i++) {
+ if (text[i] == ',' || text[i] == ';' || text[i] == '\n') {
+ if (word) {
+ data.push(word.trim());
+ word = '';
+ }
+ } else {
+ word += text[i];
+ }
+ }
+
+ if (word) {
+ data.push(word);
+ }
+ }
+
+ return data;
+ }
+
+ /** @type {number} */
+ var anchorOffset = 0;
+
+ /**
+ * Processing event keydown on the element
+ * @param e {object}
+ */
+ var tagsKeyDown = function(e) {
+ // Anchoroffset
+ anchorOffset = window.getSelection().anchorOffset;
+
+ // If starts blank create the first element
+ if (! el.children.length) {
+ var div = document.createElement('div');
+ div.innerHTML = '<div><br/></div>';
+ el.appendChild(div);
+ }
+ // Comma
+ if (e.which == 9 || e.which == 186 || e.which == 188) {
+ var n = window.getSelection().anchorOffset;
+ if (n > 1) {
+ if (! obj.options.limit || el.children.length < obj.options.limit) {
+ obj.add('', true);
+ }
+ }
+ e.preventDefault();
+ } else if (e.which == 13) {
+ // Enter
+ if (searchContainer && searchContainer.style.display != '') {
+ obj.selectIndex(searchContainer.children[searchIndex]);
+ } else {
+ var n = window.getSelection().anchorOffset;
+ if (n > 1) {
+ if (! obj.options.limit || el.children.length < obj.options.limit) {
+ obj.add('', true);
+ }
+ }
+ }
+ e.preventDefault();
+ } else if (e.which == 38) {
+ // Up
+ if (searchContainer && searchContainer.style.display != '') {
+ searchContainer.children[searchIndex].classList.remove('selected');
+ if (searchIndex > 0) {
+ searchIndex--;
+ }
+ searchContainer.children[searchIndex].classList.add('selected');
+ e.preventDefault();
+ }
+ } else if (e.which == 40) {
+ // Down
+ if (searchContainer && searchContainer.style.display != '') {
+ searchContainer.children[searchIndex].classList.remove('selected');
+ if (searchIndex < 9) {
+ searchIndex++;
+ }
+ searchContainer.children[searchIndex].classList.add('selected');
+ e.preventDefault();
+ }
+ } else if (e.which == 8) {
+ // Back space - do not let last item to be removed
+ if (el.children.length == 1 && window.getSelection().anchorOffset < 1) {
+ e.preventDefault();
+ }
+ }
+ }
+
+ /**
+ * Processing event keyup on the element
+ * @param e {object}
+ */
+ var tagsKeyUp = function(e) {
+ if (e.which == 39) {
+ // Right arrow
+ var n = window.getSelection().anchorOffset;
+ if (n > 1 && n == anchorOffset) {
+ obj.add('', true);
+ }
+ } else if (e.which == 13 || e.which == 38 || e.which == 40) {
+ e.preventDefault();
+ } else if (e.which == 8) {
+ // Back space - add a new element just in case is blank
+ if (! el.innerHTML) {
+ obj.add('', true);
+ }
+ e.preventDefault();
+ } else if (e.which == 46) {
+ // Verify content and don't let blank element
+ if (! el.children.length) {
+ var div = document.createElement('div');
+ div.innerHTML = '<div><br/></div>';
+ el.appendChild(div);
+ }
+ e.preventDefault();
+ } else {
+ if (searchTimer) {
+ clearTimeout(searchTimer);
+ }
+
+ searchTimer = setTimeout(function() {
+ // Current node
+ var node = window.getSelection();
+ // Search
+ if (obj.options.search) {
+ obj.search(node);
+ }
+ searchTimer = null;
+ }, 300);
+ }
+
+ filter();
+ }
+
+ /**
+ * Processing event paste on the element
+ * @param e {object}
+ */
+ var tagsPaste = function(e) {
+ if (e.clipboardData || e.originalEvent.clipboardData) {
+ var html = (e.originalEvent || e).clipboardData.getData('text/html');
+ var text = (e.originalEvent || e).clipboardData.getData('text/plain');
+ } else if (window.clipboardData) {
+ var html = window.clipboardData.getData('Html');
+ var text = window.clipboardData.getData('Text');
+ }
+
+ obj.setValue(text);
+ e.preventDefault();
+ }
+
+ /**
+ * Processing event mouseup on the element
+ * @param e {object}
+ */
+ var tagsMouseUp = function(e) {
+ if (e.target.parentNode && e.target.parentNode.classList.contains('jtags')) {
+ if (e.target.classList.contains('jtags_label') || e.target.classList.contains('jtags_error')) {
+ var rect = e.target.getBoundingClientRect();
+ if (rect.width - (e.clientX - rect.left) < 16) {
+ obj.remove(e.target);
+ }
+ }
+ }
+
+ if (searchContainer) {
+ searchContainer.style.display = '';
+ }
+ }
+
+ /**
+ * Processing event focus on the element
+ * @param e {object}
+ */
+ var tagsFocus = function(e) {
+ if (! el.children.length || obj.getValue(el.children.length - 1)) {
+ if (! obj.options.limit || el.children.length < obj.options.limit) {
+ var div = document.createElement('div');
+ div.innerHTML = '<br>';
+ el.appendChild(div);
+ }
+ }
+
+ if (typeof(obj.options.onfocus) == 'function') {
+ obj.options.onfocus(el, obj, obj.getValue());
+ }
+ }
+
+ /**
+ * Processing event blur on the element
+ * @param e {object}
+ */
+ var tagsBlur = function(e) {
+ if (searchContainer) {
+ setTimeout(function() {
+ searchContainer.style.display = '';
+ }, 200);
+ }
+
+ for (var i = 0; i < el.children.length - 1; i++) {
+ // Create label design
+ if (! obj.getValue(i)) {
+ el.removeChild(el.children[i]);
+ }
+ }
+
+ if (typeof(obj.options.onblur) == 'function') {
+ obj.options.onblur(el, obj, obj.getValue());
+ }
+ }
+
+ // Bind events
+ el.addEventListener('mouseup', tagsMouseUp);
+ el.addEventListener('keydown', tagsKeyDown);
+ el.addEventListener('keyup', tagsKeyUp);
+ el.addEventListener('paste', tagsPaste);
+ el.addEventListener('focus', tagsFocus);
+ el.addEventListener('blur', tagsBlur);
+
+ // Prepare container
+ el.classList.add('jtags');
+ el.setAttribute('contenteditable', true);
+ el.setAttribute('spellcheck', false);
+
+ if (obj.options.placeholder) {
+ el.placeholder = obj.options.placeholder;
+ }
+
+ // Make sure element is empty
+ if (obj.options.value) {
+ obj.setValue(obj.options.value);
+ } else {
+ el.innerHTML = '<div><br></div>';
+ }
+
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj);
+ }
+
+ el.tags = obj;
+
+ return obj;
+});
+
+jSuites.toolbar = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ app: null,
+ container: false,
+ badge: false,
+ title: false,
+ items: [],
+ }
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ if (! el && options.app && options.app.el) {
+ el = document.createElement('div');
+ options.app.el.appendChild(el);
+ }
+
+ obj.selectItem = function(element) {
+ var elements = toolbarContent.children;
+ for (var i = 0; i < elements.length; i++) {
+ if (element != elements[i]) {
+ elements[i].classList.remove('jtoolbar-selected');
+ }
+ }
+ element.classList.add('jtoolbar-selected');
+ }
+
+ obj.hide = function() {
+ jSuites.animation.slideBottom(el, 0, function() {
+ el.style.display = 'none';
+ });
+ }
+
+ obj.show = function() {
+ el.style.display = '';
+ jSuites.animation.slideBottom(el, 1);
+ }
+
+ obj.get = function() {
+ return el;
+ }
+
+ obj.setBadge = function(index, value) {
+ toolbarContent.children[index].children[1].firstChild.innerHTML = value;
+ }
+
+ obj.destroy = function() {
+ toolbar.remove();
+ el.innerHTML = '';
+ }
+
+ var toggleState = function() {
+ if (this.classList.contains('jtoolbar-active')) {
+ this.classList.remove('jtoolbar-active');
+ } else {
+ this.classList.add('jtoolbar-active');
+ }
+ }
+
+ obj.create = function(items) {
+ // Reset anything in the toolbar
+ toolbarContent.innerHTML = '';
+ // Create elements in the toolbar
+ for (var i = 0; i < items.length; i++) {
+ var toolbarItem = document.createElement('div');
+ toolbarItem.classList.add('jtoolbar-item');
+
+ if (items[i].width) {
+ toolbarItem.style.width = parseInt(items[i].width) + 'px';
+ }
+
+ if (items[i].k) {
+ toolbarItem.k = items[i].k;
+ }
+
+ if (items[i].tooltip) {
+ toolbarItem.setAttribute('title', items[i].tooltip);
+ }
+
+ // Id
+ if (items[i].id) {
+ toolbarItem.setAttribute('id', items[i].id);
+ }
+
+ // Selected
+ if (items[i].state) {
+ toolbarItem.toggleState = toggleState;
+ }
+
+ if (items[i].active) {
+ toolbarItem.classList.add('jtoolbar-active');
+ }
+
+ if (items[i].type == 'select' || items[i].type == 'dropdown') {
+ if (typeof(items[i].onchange) == 'function') {
+ // Event for picker has different arguments
+ items[i].onchange = (function(o) {
+ return function(a,b,c,d) {
+ o(el, obj, a, c, d);
+ }
+ })(items[i].onchange);
+ }
+ jSuites.picker(toolbarItem, items[i]);
+ } else if (items[i].type == 'divisor') {
+ toolbarItem.classList.add('jtoolbar-divisor');
+ } else if (items[i].type == 'label') {
+ toolbarItem.classList.add('jtoolbar-label');
+ toolbarItem.innerHTML = items[i].content;
+ } else {
+ // Material icons
+ var toolbarIcon = document.createElement('i');
+ if (typeof(items[i].class) === 'undefined') {
+ toolbarIcon.classList.add('material-icons');
+ } else {
+ var c = items[i].class.split(' ');
+ for (var j = 0; j < c.length; j++) {
+ toolbarIcon.classList.add(c[j]);
+ }
+ }
+ toolbarIcon.innerHTML = items[i].content ? items[i].content : '';
+ toolbarItem.appendChild(toolbarIcon);
+
+ // Badge options
+ if (obj.options.badge == true) {
+ var toolbarBadge = document.createElement('div');
+ toolbarBadge.classList.add('jbadge');
+ var toolbarBadgeContent = document.createElement('div');
+ toolbarBadgeContent.innerHTML = items[i].badge ? items[i].badge : '';
+ toolbarBadge.appendChild(toolbarBadgeContent);
+ toolbarItem.appendChild(toolbarBadge);
+ }
+
+ // Title
+ if (items[i].title) {
+ if (obj.options.title == true) {
+ var toolbarTitle = document.createElement('span');
+ toolbarTitle.innerHTML = items[i].title;
+ toolbarItem.appendChild(toolbarTitle);
+ } else {
+ toolbarItem.setAttribute('title', items[i].title);
+ }
+ }
+
+ if (obj.options.app && items[i].route) {
+ // Route
+ toolbarItem.route = items[i].route;
+ // Onclick for route
+ toolbarItem.onclick = function() {
+ obj.options.app.pages(this.route);
+ }
+ // Create pages
+ obj.options.app.pages(items[i].route, {
+ toolbarItem: toolbarItem,
+ closed: true
+ });
+ }
+ }
+
+ if (items[i].onclick) {
+ toolbarItem.onclick = (function (a) {
+ return function () {
+ items[a].onclick(el, obj, this);
+ };
+ })(i);
+ }
+
+ toolbarContent.appendChild(toolbarItem);
+ }
+ }
+
+ el.classList.add('jtoolbar');
+
+ if (obj.options.container == true) {
+ el.classList.add('jtoolbar-container');
+ }
+
+ el.innerHTML = '';
+ el.onclick = function(e) {
+ var element = jSuites.findElement(e.target, 'jtoolbar-item');
+ if (element) {
+ obj.selectItem(element);
+ }
+ }
+
+ var toolbarContent = document.createElement('div');
+ el.appendChild(toolbarContent);
+
+ if (obj.options.app) {
+ el.classList.add('jtoolbar-mobile');
+ }
+
+ obj.create(obj.options.items);
+
+ el.toolbar = obj;
+
+ return obj;
+});
+
+
+
+ return jSuites;
+
+}))); \ No newline at end of file
diff --git a/web-tools/web/_static/jsuites/jsuites.layout.css b/web-tools/web/_static/jsuites/jsuites.layout.css
new file mode 100644
index 0000000..33114c5
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.layout.css
@@ -0,0 +1,1395 @@
+
+/**
+ * (c) jSuites Javascript Web Components
+ *
+ * Author: Paul Hodel <paul.hodel@gmail.com>
+ * Website: https://bossanova.uk/jsuites/
+ * Description: Create amazing web based applications.
+ *
+ * MIT License
+ *
+ */
+
+/** Buttons **/
+
+.jbutton {
+ padding: 8px;
+ padding-left: 15px;
+ padding-right: 15px;
+ border: 1px solid #ddd;
+ border-radius: 2px;
+ cursor:pointer;
+ -webkit-font-smoothing: antialiased;
+ outline: none;
+}
+
+.jbutton.dark {
+ background-color: #737373;
+ border: 1px solid transparent;
+ color: #fff;
+}
+
+.jbutton.blue {
+ border:1px solid transparent;
+ color:#fff;
+ background-color:#1a73e8;
+}
+
+.jbutton[data-icon] {
+ display: flex;
+}
+
+.jbutton[data-icon].center {
+ -webkit-justify-content: center;
+ justify-content: center;
+ padding-right:20px;
+}
+
+.jbutton[data-icon]::before {
+ content: attr(data-icon);
+ width: 24px;
+ height: 24px;
+ font-size: 24px;
+ line-height: 24px;
+ font-family: 'Material icons';
+ color: #999;
+ margin-right:2px;
+ color: #fff;
+}
+
+.jbutton:hover {
+ opacity: 0.8;
+ text-decoration: underline;
+}
+
+.jbutton[disabled] {
+ opacity: 0.5;
+ text-decoration: none;
+}
+
+.jbuttons-group {
+ display: flex;
+}
+
+.jbuttons-group .jbutton {
+ border-radius: 0px;
+ margin: 0px;
+}
+
+.jbuttons-group .jbutton:first-child {
+ border-top-left-radius: 2px;
+ border-bottom-left-radius: 2px;
+}
+
+.jbuttons-group .jbutton:last-child {
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+}
+
+/*.button-plain {
+ border:0px;
+ background-color:transparent;
+ cursor:pointer;
+ outline: none;
+}
+
+.button-dark {
+ background-color:#737373;
+ color:#fff;
+ border:1px solid transparent;
+ border-radius:2px;
+ cursor:pointer;
+ min-width:120px;
+ outline:none;
+}
+
+.button-dark:disabled {
+ background-color:#d3d3d3;
+ color:#a3a3a3;
+}
+
+.button-light {
+ background-color:#fff;
+ color:#737373;
+ border:1px solid #737373;
+ border-radius:2px;
+ cursor:pointer;
+ min-width:120px;
+ outline:none;
+}
+
+.button-light:disabled {
+ color:#a3a3a3;
+}
+
+.button-red {
+ background-color:#733333;
+ color:#fff;
+ border:1px solid transparent;
+ border-radius:2px;
+ cursor:pointer;
+ min-width:120px;
+ outline:none;
+}*/
+
+
+
+
+/** Switch **/
+
+.jswitch {
+ display: flex;
+ cursor: pointer;
+ -webkit-tap-highlight-color: transparent;
+ align-items: center;
+}
+
+.jswitch i {
+ position: relative;
+ display: inline-block;
+ width: 46px;
+ height: 26px;
+ background-color: #e6e6e6;
+ border-radius: 23px;
+ vertical-align: text-bottom;
+ transition: all 0.3s linear;
+}
+
+.jswitch i::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ width: 42px;
+ height: 22px;
+ background-color: #fff;
+ border-radius: 11px;
+ transform: translate3d(2px, 2px, 0) scale3d(1, 1, 1);
+ transition: all 0.25s linear;
+}
+
+.jswitch i::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ width: 22px;
+ height: 22px;
+ background-color: #fff;
+ border-radius: 11px;
+ box-shadow: 0 2px 2px rgba(0, 0, 0, 0.24);
+ transform: translate3d(2px, 2px, 0);
+ transition: all 0.2s ease-in-out;
+}
+
+.jswitch:active i::after {
+ width: 28px;
+ transform: translate3d(2px, 2px, 0);
+}
+
+.jswitch:active input:checked + i::after { transform: translate3d(16px, 2px, 0); }
+
+.jswitch input { display: none; }
+
+.jswitch input:checked + i { background-color: #4BD763; }
+
+.jswitch input:checked + i::before { transform: translate3d(18px, 2px, 0) scale3d(0, 0, 0); }
+
+.jswitch input:checked + i::after { transform: translate3d(22px, 2px, 0); }
+
+@media (min-width: 576px)
+{
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px)
+{
+ .container {
+ max-width: 732px;
+ }
+}
+
+@media (min-width: 992px)
+{
+ .container {
+ max-width: 956px;
+ }
+}
+
+@media (min-width: 1200px)
+{
+ .container {
+ max-width: 1168px;
+ }
+}
+
+@media (min-width: 1440px) {
+ .container {
+ max-width: 1404px;
+ }
+}
+
+@media only screen and (max-device-width: 800px)
+{
+ .form-group {
+ min-width: 50vw !important;
+ }
+ .section {
+ margin-right:0px !important;
+ }
+ .section-content {
+ padding: 12px !important;
+ }
+}
+
+@media (max-device-width: 800px) {
+ .small-screen-only {
+ display: block;
+ }
+ .big-screen-only {
+ display: none;
+ }
+}
+
+@media (min-device-width: 800px) {
+ .small-screen-only {
+ display: none;
+ }
+ .big-screen-only {
+ display: block;
+ }
+}
+
+body, div, td
+{
+ font-family:'Open Sans';
+}
+
+body
+{
+ margin:0px;
+}
+
+h1:empty
+{
+ display:none;
+}
+
+h2:empty
+{
+ display:none;
+}
+
+input, select, textarea, button, .input {
+ border-radius: 1px;
+ border:1px solid #ccc;
+ padding:8px;
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ background-color:#fff;
+ font-size:1em;
+}
+
+select {
+ padding:7px;
+}
+
+input:disabled, select:disabled, textarea:disabled, button:disabled {
+ background-color:#eee;
+ color:#888;
+}
+
+blockquote {
+ font-style: italic;
+ font-family: Georgia, Times, "Times New Roman", serif;
+ padding: 2px 0;
+ border-style: solid;
+ border-color: #ccc;
+ border-width: 0;
+ padding-left: 20px;
+ padding-right: 8px;
+ border-left-width: 5px;
+}
+
+section.middle {
+ max-width:540px;
+}
+
+.center {
+ text-align:center;
+}
+
+.justify {
+ text-align:justify;
+}
+
+.separator {
+ background-color:#eee;
+ height:1px;
+}
+
+.clear {
+ clear:both;
+}
+
+.top {
+ padding-left:10px;
+ padding-right:10px;
+}
+
+.top > .row > .column {
+ margin-top:5px;
+ margin-bottom:5px;
+}
+
+.container {
+ width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+.container-box {
+ padding-right: 15px;
+ padding-left: 15px;
+}
+
+.row {
+ display:flex;
+ flex-wrap: wrap;
+ -ms-flex-direction: row;
+ -webkit-flex-direction: row;
+ flex-direction: row;
+ -ms-flex-pack: justify;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+}
+
+.row.container {
+ flex-wrap: nowrap;
+}
+
+.row.middle {
+ -ms-flex-align: center;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+ align-items: center;
+}
+
+.column.top {
+ -webkit-align-self: flex-start;
+ -ms-flex-item-align: start;
+ align-self: flex-start;
+}
+
+.column.bottom {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end;
+}
+
+.start {
+ justify-content:flex-start;
+}
+
+.header {
+ width:100%;
+ position:absolute;
+ background-color:rgba(255, 255, 255, 0.2);
+ padding-top:12px;
+ padding-bottom:12px;
+ text-align:center;
+}
+
+.space {
+ height:4px;
+}
+
+.line .row {
+ max-width:1280px;
+ margin: 0 auto;
+}
+
+.large {
+ font-size:1.2em;
+}
+
+.extra-large {
+ font-size:1.4em;
+}
+
+.small {
+ font-size:0.8em;
+}
+
+.extra-small {
+ font-size:0.7em;
+}
+
+.form-group {
+ padding:4px;
+}
+
+.form-group label {
+}
+
+.form-group input[type='text'], .form-group input[type='number'], .form-group input[type='password'], .form-group select, .form-group textarea, .form-group .jdropdown, .form-group .jprogressbar {
+ width:100%;
+}
+
+.f1
+{
+ flex:1;
+}
+
+.f2
+{
+ flex:2;
+}
+
+.f3
+{
+ flex:3;
+}
+
+.f4
+{
+ flex:4;
+}
+
+.f5
+{
+ flex:5;
+}
+
+.f6
+{
+ flex:6;
+}
+
+.f7
+{
+ flex:7;
+}
+
+.f8
+{
+ flex:8;
+}
+
+.f9
+{
+ flex:9;
+}
+
+.f10
+{
+ flex:10;
+}
+
+.w5
+{
+ width:5% !important;
+}
+
+.w10
+{
+ width:10% !important;
+}
+
+.w15
+{
+ width:15% !important;
+}
+
+.w20
+{
+ width:15% !important;
+}
+
+.w25
+{
+ width:25% !important;
+}
+
+.w30
+{
+ width:30% !important;
+}
+
+.w33
+{
+ width:33% !important;
+}
+
+.w40
+{
+ width:40% !important;
+}
+
+.w50
+{
+ width:50% !important;
+}
+
+.w60
+{
+ width:60% !important;
+}
+
+.w66
+{
+ width:66% !important;
+}
+
+.w70
+{
+ width:70% !important;
+}
+
+.w100
+{
+ width:100% !important;
+}
+
+.r20 .column
+{
+ width:20%;
+}
+
+.r25 .column
+{
+ width:25%;
+}
+
+.r33 .column
+{
+ width:33%;
+}
+
+.r66 .column
+{
+ width:66%;
+}
+
+.r50 .column
+{
+ width:50%;
+}
+
+.r100 .column
+{
+ width:100%;
+}
+
+.p0
+{
+ padding:0px;
+}
+
+.p2
+{
+ padding:2px;
+}
+
+.p4
+{
+ padding:4px;
+}
+
+.p6
+{
+ padding:6px;
+}
+
+.p8
+{
+ padding:8px;
+}
+
+.p10
+{
+ padding:10px;
+}
+
+.p15
+{
+ padding:15px;
+}
+
+.p20
+{
+ padding:20px;
+}
+
+.m0
+{
+ margin:0px;
+}
+
+.m2
+{
+ margin:2px;
+}
+
+.m4
+{
+ margin:4px;
+}
+
+.m6
+{
+ margin:6px;
+}
+
+.m8
+{
+ margin:8px;
+}
+
+.m10
+{
+ margin:10px;
+}
+
+.m15
+{
+ margin:15px;
+}
+
+.m20
+{
+ margin:20px;
+}
+
+.mr1 {
+ margin-right:10px;
+}
+
+.mr2 {
+ margin-right:20px;
+}
+
+.mr3 {
+ margin-right:30px;
+}
+
+.ml1 {
+ margin-left:10px;
+}
+
+.ml2 {
+ margin-left:20px;
+}
+
+.ml3 {
+ margin-left:30px;
+}
+
+.pl1 {
+ padding-left:10px;
+}
+
+.pl2 {
+ padding-left:20px;
+}
+
+.pl3 {
+ padding-left:30px;
+}
+
+.pr1 {
+ padding-right:10px;
+}
+
+.pr2 {
+ padding-right:20px;
+}
+
+.pr3 {
+ padding-right:30px;
+}
+
+.section {
+ background-color: #fff;
+ box-shadow: 1px 1px 2px rgba(0,0,0,.1);
+ margin-top:10px;
+ margin-right:10px;
+}
+
+.section-divisor {
+ margin-top:6px;
+ margin-bottom:5px;
+ border-bottom:1px solid #e1e1e1;
+ text-transform:uppercase;
+}
+
+.section-divisor div {
+ display:inline-block;
+}
+
+.section-divisor .section-number {
+ padding:8px;
+ width:40px;
+ height:40px;
+ text-align:center;
+ font-weight:bold;
+ font-size:23px;
+ display:inline;
+}
+
+.section-container {
+ padding:6px;
+}
+
+.section-header {
+ font-size:2em;
+ margin-bottom:20px;
+}
+
+.section-content {
+ padding:30px;
+}
+
+.fullpath {
+ display:flex;
+ color: #999;
+ padding:4px;
+ padding-left:8px;
+}
+
+.fullpath > div {
+ line-height:24px;
+}
+.fullpath > input {
+ border-color: transparent;
+ padding: 0px;
+ margin: 0px;
+ outline: none;
+}
+
+.fullpath > input.error {
+ border-bottom: 1px solid red;
+}
+
+.title {
+ font-size:1.8em;
+ font-family: Roboto,Helvetica,Arial,sans-serif;
+ font-size: 22px;
+ font-weight: 400;
+ line-height: 28px;
+}
+
+.t1 {
+ font-family: Roboto,Helvetica,Arial,sans-serif;
+ font-size: 22px;
+ font-weight: 400;
+ line-height: 28px;
+}
+
+.t2 {
+ font-family: Roboto,Helvetica,Arial,sans-serif;
+ font-size: 18px;
+ font-weight: 400;
+ line-height: 22px;
+}
+
+.uppercase {
+ text-transform:uppercase;
+}
+
+.subtitle {
+ position:relative;
+ top:-5px;
+ margin-bottom:10px;
+}
+
+/* Admin */
+
+.breadcrumb {
+ display: flex;
+}
+
+.breadcrumb > div {
+ font-size: 0.9em;
+}
+
+.breadcrumb a {
+ text-decoration:none;
+ color:#000;
+}
+
+.left {
+ float:left;
+}
+
+.right {
+ float:right;
+}
+
+.material-icons {
+ font-size:24px;
+ width:24px;
+ height:24px;
+ line-height:24px;
+}
+
+.material-icons.selected {
+ color:#777;
+}
+
+.material-icons.small {
+ font-size:16px;
+ width:16px;
+ height:16px;
+ line-height:16px;
+}
+
+.material-icons.large {
+ font-size:36px;
+ width:36px;
+ height:36px;
+ line-height:36px;
+}
+
+.material-icons.larger {
+ font-size:48px;
+ width:48px;
+ height:48px;
+ line-height:48px;
+}
+
+.favorite {
+ font-size:24px;
+ width:24px;
+ height:24px;
+}
+
+.favorite.selected {
+ color:red;
+}
+
+.alert {
+ padding: 12px;
+ padding-left: 30px;
+ padding-right: 30px;
+ background-color: #f44336;
+ color: white;
+ display:none;
+}
+
+.alert.success {
+ background-color: #4CAF50;
+}
+
+.alert.info {
+ background-color: #2196F3;
+}
+
+.alert.warning {
+ background-color: #ff9800;
+}
+
+.error {
+ border:1px solid red;
+}
+
+.users {
+ width:40px;
+ height:40px;
+ border-radius:20px;
+}
+
+.users-overlap {
+ vertical-align:bottom;
+ min-height:28px;
+ padding-left:10px;
+}
+
+.users-overlap img {
+ width:24px;
+ height:24px;
+ line-height:24px;
+ border-radius:24px;
+ border:2px solid #fff;
+ vertical-align: middle;
+ margin-left:-10px;
+}
+
+.users-overlap span {
+ margin-left:3px;
+ font-size:0.8em;
+}
+
+.users-micro {
+ width:24px;
+ height:24px;
+ border-radius:12px;
+}
+
+.users-small {
+ width:30px;
+ height:30px;
+ border-radius:15px;
+}
+
+.users-medium {
+ width:45px;
+ height:45px;
+ border-radius:23px;
+}
+
+.users-large {
+ width:60px;
+ height:60px;
+ border-radius:30px;
+}
+
+.users-extra-large {
+ width:120px;
+ height:120px;
+ border-radius:60px;
+}
+
+.badge {
+ position:absolute;
+ background-color:red;
+ color:#fff;
+ width:16px;
+ height:16px;
+ line-height:16px;
+ border-radius:16px;
+ text-align:center;
+ font-size:8px;
+ margin:12px;
+}
+
+.badge:empty {
+ display:none;
+}
+
+.video-container {
+ position: relative;
+ width: 100%;
+ height: 0;
+ padding-bottom: 56.25%;
+}
+
+.video-container iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.cursor {
+ cursor:pointer;
+}
+
+.cursor.link:hover {
+ text-decoration: underline;
+}
+
+.arrow-right {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z' fill='gray'/%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ width:24px;
+ height:24px;
+ line-height:24px;
+ cursor:pointer;
+}
+
+.arrow-left {
+ background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z' fill='gray'/%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ width:24px;
+ height:24px;
+ line-height:24px;
+ cursor:pointer;
+}
+
+[contenteditable=true] div:empty:not(:focus)::before{
+ content:attr(placeholder);
+ color:#ccc;
+}
+
+.mirror {
+ -moz-transform: scaleX(-1);
+ -o-transform: scaleX(-1);
+ -webkit-transform: scaleX(-1);
+ transform: scaleX(-1);
+ filter: FlipH;
+}
+
+.hover:hover {
+ background-color:#efefef;
+}
+
+.unselectable {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+::-webkit-input-placeholder {
+ color: #000000;
+}
+
+:-moz-placeholder {
+ color: #000000;
+}
+
+::-moz-placeholder {
+ color: #000000;
+}
+
+:-ms-input-placeholder {
+ color: #000000;
+}
+
+
+.jlogin {
+ width: 100%;
+ box-sizing: border-box;
+ margin:0 auto;
+ vertical-align:middle;
+ border-radius: 5px;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ font-size:1em;
+}
+
+.jlogin-fullscreen {
+ position:absolute;
+ top:0px;
+ left:0px;
+ width:100%;
+ height:100%;
+ background-color:#fff;
+ z-index:9000;
+}
+
+.jlogin > form {
+ max-width:480px;
+ padding:20px;
+ margin: 0 auto;
+}
+
+.jlogin > form > div {
+ margin-bottom:10px;
+}
+
+.jlogin label {
+ display:block;
+}
+
+.jlogin > form > div > input {
+ width:100%;
+ outline:none;
+ padding:15px;
+ margin:0px;
+}
+
+.jlogin input[type='checkbox'] {
+ float:left;
+}
+
+.jlogin input[type='button'] {
+ padding:10px;
+ background-color: var(--button-color);
+ border: 1px solid var(--button-color);
+ color: #fff;
+ cursor:pointer;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+}
+
+.jlogin span
+{
+ margin:0 auto;
+}
+.jlogin img
+{
+ text-align:center;
+ max-width:220px;
+}
+
+.jlogin .jlogin-logo
+{
+ text-align:center;
+ padding:20px;
+}
+
+.jlogin .jlogin-logo:empty {
+ display: none;
+}
+
+.jlogin .captcha
+{
+ width:100%;
+ margin-top:4px;
+ margin-bottom:4px;
+ border:1px solid #ccc;
+ display:block;
+}
+
+.jlogin .facebookButton
+{
+ padding:10px;
+ background-color: var(--button-color);
+ border: 1px solid var(--button-color);
+ color: #fff;
+ text-align:center;
+ background-repeat:no-repeat;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24px' height='24px'%3E%3Cpath d='M19,3H5C3.895,3,3,3.895,3,5v14c0,1.105,0.895,2,2,2h7.621v-6.961h-2.343v-2.725h2.343V9.309 c0-2.324,1.421-3.591,3.495-3.591c0.699-0.002,1.397,0.034,2.092,0.105v2.43h-1.428c-1.13,0-1.35,0.534-1.35,1.322v1.735h2.7 l-0.351,2.725h-2.365V21H19c1.105,0,2-0.895,2-2V5C21,3.895,20.105,3,19,3z' fill='white'/%3E%3C/svg%3E%0A");
+ background-position:10px 40%;
+ cursor:pointer;
+}
+
+.jlogin .rememberButton
+{
+ padding:10px;
+ display:none;
+}
+
+.jlogin .requestButton, .jlogin .cancelButton, .jlogin .newProfileButton
+{
+ padding:20px;
+ padding-bottom:0px;
+ text-align:center;
+ cursor:pointer;
+}
+
+.jlogin-captcha img {
+ min-width:280px;
+}
+
+.jlogin-loading:before {
+ content: "";
+ display: block;
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ width: 200px;
+ height: 4px;
+ background-color: var(--button-color);
+ animation: loading 2s linear infinite;
+}
+
+@keyframes loading {
+ from { left: 0px; width: 25%; }
+ 25% { width: 25%; }
+ 50% { width: 50%; }
+ 75% { left: 75%; }
+ 100% { left: 100%; }
+ to { left: 100%; }
+}
+
+.jtemplate-pagination {
+ display:flex;
+ cursor:pointer;
+ margin-top:10px;
+ margin-bottom:10px;
+}
+
+.jtemplate-pagination div {
+ text-align:center;
+ font-size:0.8em;
+ width:30px;
+ height:30px;
+ line-height:30px;
+ -webkit-touch-callout: none; /* iOS Safari */
+ -webkit-user-select: none; /* Safari */
+ khtml-user-select: none; /* Konqueror HTML */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none;
+}
+
+.jtemplate-pagination div:hover {
+ background-color:#eee;
+}
+
+.jtemplate-pagination:empty {
+ display:none;
+}
+
+.jtemplate-results {
+ margin-top:15px;
+ margin-bottom:15px;
+}
+
+
+.jtimeline {
+ min-height:calc(100vh - 90px);
+}
+
+.jtimeline-item {
+ display:flex;
+ margin-left:15px;
+ margin-right:15px;
+}
+
+.jtimeline-header {
+ position:fixed;
+ width:100%;
+ display:flex;
+ align-items: center;
+ justify-content:space-between;
+ padding:15px;
+ border-top:1px solid #eee;
+ border-bottom:1px solid #eee;
+ margin-top:-1px;
+ margin-bottom:10px;
+ background-color:#fff;
+ z-index:1;
+ box-sizing: border-box;
+}
+
+.jtimeline-year {
+ font-size:2.2em;
+ display:inline-block;
+}
+
+.jtimeline-month {
+ font-size:0.8em;
+ position:relative;
+ top:6px;
+}
+
+.jtimeline-navigation div {
+ display:inline-block;
+ background-color:#eee;
+ padding:8px;
+ padding-right:12px;
+ padding-left:12px;
+ margin-left:4px;
+}
+
+.jtimeline-navigation i {
+ width:32px;
+ height:32px;
+ font-size:32px;
+ line-height:32px;
+ display:inline-block;
+}
+
+.jtimeline-container {
+ padding-top:110px;
+ padding-bottom:30px;
+}
+
+.jtimeline-subtitle {
+ color:#aaa;
+ font-size:0.8em;
+}
+
+.jtimeline-content {
+ padding-top:0px;
+ padding-left:20px;
+ padding-bottom:30px;
+ font-size:0.8em;
+ border-left:3px solid #aaa;
+ width:100%;
+}
+
+.jtimeline-item:last-child .jtimeline-content {
+ padding-bottom:0px;
+}
+
+.jtimeline-text {
+ color:#888;
+ font-size:0.9em;
+ line-height:18px;
+ margin-top:5px;
+ margin-bottom:5px;
+}
+
+.jtimeline-item:last-child .jtimeline-text {
+}
+
+.jtimeline-date-container {
+ position:relative;
+ padding-top:0px;
+}
+
+.jtimeline-date {
+ font-size:1em;
+ width:40px;
+ padding-top:2px;
+}
+
+.jtimeline-title-container {
+ display:flex;
+}
+
+.jtimeline-title {
+ font-size:1.4em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width:calc(100% - 60px);
+}
+
+.jtimeline-controls {
+ margin-left:5px;
+}
+
+.jtimeline-controls i {
+ font-size:16px;
+ width:16px;
+ height:16px;
+ line-height:24px;
+ color:#aaa;
+}
+
+.jtimeline-date small {
+ font-size:0.7em;
+}
+
+.jtimeline-date-bullet::after {
+ content:'';
+ width:12px;
+ height:12px;
+ border-radius:12px;
+ border:3px solid #00688B;
+ display: inline-block;
+ position:absolute;
+ top:4px;
+ right:-10px;
+ background-color:#fff;
+}
+
+.jtimeline-tags {
+ margin-top:15px;
+ margin-bottom:0px;
+ border-bottom:1px solid #fefefe;
+}
+
+.jtimeline-tags:empty {
+ display:none;
+}
+
+.jtimeline-tag {
+ padding:1px;
+ padding-right:10px;
+ padding-left:10px;
+ background-color:red;
+ color:#fff;
+ display:inline-block;
+ font-size:0.8em;
+ margin-bottom:5px;
+ margin-right:5px;
+}
+
+.jtimeline-message {
+ text-align:center;
+ padding:20px;
+ font-size:0.7em;
+}
+
+
diff --git a/web-tools/web/_static/jsuites/jsuites.layout.js b/web-tools/web/_static/jsuites/jsuites.layout.js
new file mode 100644
index 0000000..ad5c23d
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.layout.js
@@ -0,0 +1,1491 @@
+jSuites.login = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ url: window.location.href,
+ prepareRequest: null,
+ accessToken: null,
+ deviceToken: null,
+ facebookUrl: null,
+ facebookAuthentication: null,
+ maxHeight: null,
+ onload: null,
+ onsuccess: null,
+ onerror: null,
+ message: null,
+ logo: null,
+ newProfile: false,
+ newProfileUrl: false,
+ newProfileLogin: false,
+ fullscreen: false,
+ newPasswordValidation: null,
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Message console container
+ if (! obj.options.message) {
+ var messageElement = document.querySelector('.message');
+ if (messageElement) {
+ obj.options.message = messageElement;
+ }
+ }
+
+ // Action
+ var action = null;
+
+ // Container
+ var container = document.createElement('form');
+ el.appendChild(container);
+
+ // Logo
+ var divLogo = document.createElement('div');
+ divLogo.className = 'jlogin-logo'
+ container.appendChild(divLogo);
+
+ if (obj.options.logo) {
+ var logo = document.createElement('img');
+ logo.src = obj.options.logo;
+ divLogo.appendChild(logo);
+ }
+
+ // Code
+ var labelCode = document.createElement('label');
+ labelCode.innerHTML = 'Please enter here the code received';
+ var inputCode = document.createElement('input');
+ inputCode.type = 'number';
+ inputCode.id = 'code';
+ inputCode.setAttribute('maxlength', 6);
+ var divCode = document.createElement('div');
+ divCode.appendChild(labelCode);
+ divCode.appendChild(inputCode);
+
+ // Hash
+ var inputHash = document.createElement('input');
+ inputHash.type = 'hidden';
+ inputHash.name = 'h';
+ var divHash = document.createElement('div');
+ divHash.appendChild(inputHash);
+
+ // Recovery
+ var inputRecovery = document.createElement('input');
+ inputRecovery.type = 'hidden';
+ inputRecovery.name = 'recovery';
+ inputRecovery.value = '1';
+ var divRecovery = document.createElement('div');
+ divRecovery.appendChild(inputRecovery);
+
+ // Login
+ var labelLogin = document.createElement('label');
+ labelLogin.innerHTML = 'Login';
+ var inputLogin = document.createElement('input');
+ inputLogin.type = 'text';
+ inputLogin.name = 'login';
+ inputLogin.setAttribute('autocomplete', 'off');
+ inputLogin.onkeyup = function() {
+ this.value = this.value.toLowerCase().replace(/[^a-zA-Z0-9_+]+/gi, '');
+ }
+ var divLogin = document.createElement('div');
+ divLogin.appendChild(labelLogin);
+ divLogin.appendChild(inputLogin);
+
+ // Name
+ var labelName = document.createElement('label');
+ labelName.innerHTML = 'Name';
+ var inputName = document.createElement('input');
+ inputName.type = 'text';
+ inputName.name = 'name';
+ var divName = document.createElement('div');
+ divName.appendChild(labelName);
+ divName.appendChild(inputName);
+
+ // Email
+ var labelUsername = document.createElement('label');
+ labelUsername.innerHTML = 'E-mail';
+ var inputUsername = document.createElement('input');
+ inputUsername.type = 'text';
+ inputUsername.name = 'username';
+ inputUsername.setAttribute('autocomplete', 'new-username');
+ var divUsername = document.createElement('div');
+ divUsername.appendChild(labelUsername);
+ divUsername.appendChild(inputUsername);
+
+ // Password
+ var labelPassword = document.createElement('label');
+ labelPassword.innerHTML = 'Password';
+ var inputPassword = document.createElement('input');
+ inputPassword.type = 'password';
+ inputPassword.name = 'password';
+ inputPassword.setAttribute('autocomplete', 'new-password');
+ var divPassword = document.createElement('div');
+ divPassword.appendChild(labelPassword);
+ divPassword.appendChild(inputPassword);
+ divPassword.onkeydown = function(e) {
+ if (e.keyCode == 13) {
+ obj.execute();
+ }
+ }
+
+ // Repeat password
+ var labelRepeatPassword = document.createElement('label');
+ labelRepeatPassword.innerHTML = 'Repeat the new password';
+ var inputRepeatPassword = document.createElement('input');
+ inputRepeatPassword.type = 'password';
+ inputRepeatPassword.name = 'password';
+ var divRepeatPassword = document.createElement('div');
+ divRepeatPassword.appendChild(labelRepeatPassword);
+ divRepeatPassword.appendChild(inputRepeatPassword);
+
+ // Remember checkbox
+ var labelRemember = document.createElement('label');
+ labelRemember.innerHTML = 'Remember me on this device';
+ var inputRemember = document.createElement('input');
+ inputRemember.type = 'checkbox';
+ inputRemember.name = 'remember';
+ inputRemember.value = '1';
+ labelRemember.appendChild(inputRemember);
+ var divRememberButton = document.createElement('div');
+ divRememberButton.className = 'rememberButton';
+ divRememberButton.appendChild(labelRemember);
+
+ // Login button
+ var actionButton = document.createElement('input');
+ actionButton.type = 'button';
+ actionButton.value = 'Log In';
+ actionButton.onclick = function() {
+ obj.execute();
+ }
+ var divActionButton = document.createElement('div');
+ divActionButton.appendChild(actionButton);
+
+ // Cancel button
+ var cancelButton = document.createElement('div');
+ cancelButton.innerHTML = 'Cancel';
+ cancelButton.className = 'cancelButton';
+ cancelButton.onclick = function() {
+ obj.requestAccess();
+ }
+ var divCancelButton = document.createElement('div');
+ divCancelButton.appendChild(cancelButton);
+
+ // Captcha
+ var labelCaptcha = document.createElement('label');
+ labelCaptcha.innerHTML = 'Please type here the code below';
+ var inputCaptcha = document.createElement('input');
+ inputCaptcha.type = 'text';
+ inputCaptcha.name = 'captcha';
+ var imageCaptcha = document.createElement('img');
+ var divCaptcha = document.createElement('div');
+ divCaptcha.className = 'jlogin-captcha';
+ divCaptcha.appendChild(labelCaptcha);
+ divCaptcha.appendChild(inputCaptcha);
+ divCaptcha.appendChild(imageCaptcha);
+
+ // Facebook
+ var facebookButton = document.createElement('div');
+ facebookButton.innerHTML = 'Login with Facebook';
+ facebookButton.className = 'facebookButton';
+ var divFacebookButton = document.createElement('div');
+ divFacebookButton.appendChild(facebookButton);
+ divFacebookButton.onclick = function() {
+ obj.requestLoginViaFacebook();
+ }
+ // Forgot password
+ var inputRequest = document.createElement('span');
+ inputRequest.innerHTML = 'Request a new password';
+ var divRequestButton = document.createElement('div');
+ divRequestButton.className = 'requestButton';
+ divRequestButton.appendChild(inputRequest);
+ divRequestButton.onclick = function() {
+ obj.requestNewPassword();
+ }
+ // Create a new Profile
+ var inputNewProfile = document.createElement('span');
+ inputNewProfile.innerHTML = 'Create a new profile';
+ var divNewProfileButton = document.createElement('div');
+ divNewProfileButton.className = 'newProfileButton';
+ divNewProfileButton.appendChild(inputNewProfile);
+ divNewProfileButton.onclick = function() {
+ obj.newProfile();
+ }
+
+ el.className = 'jlogin';
+
+ if (obj.options.fullscreen == true) {
+ el.classList.add('jlogin-fullscreen');
+ }
+
+ /**
+ * Show message
+ */
+ obj.showMessage = function(data) {
+ var message = (typeof(data) == 'object') ? data.message : data;
+
+ if (typeof(obj.options.showMessage) == 'function') {
+ obj.options.showMessage(data);
+ } else {
+ jSuites.alert(data);
+ }
+ }
+
+ /**
+ * New profile
+ */
+ obj.newProfile = function() {
+ container.innerHTML = '';
+ container.appendChild(divLogo);
+ if (obj.options.newProfileLogin) {
+ container.appendChild(divLogin);
+ }
+ container.appendChild(divName);
+ container.appendChild(divUsername);
+ container.appendChild(divActionButton);
+ if (obj.options.facebookAuthentication == true) {
+ container.appendChild(divFacebookButton);
+ }
+ container.appendChild(divCancelButton);
+
+ // Reset inputs
+ inputLogin.value = '';
+ inputUsername.value = '';
+ inputPassword.value = '';
+
+ // Button
+ actionButton.value = 'Create new profile';
+
+ // Action
+ action = 'newProfile';
+ }
+
+ /**
+ * Request the email with the recovery instructions
+ */
+ obj.requestNewPassword = function() {
+ if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) {
+ var captcha = true;
+ }
+
+ container.innerHTML = '';
+ container.appendChild(divLogo);
+ container.appendChild(divRecovery);
+ container.appendChild(divUsername);
+ if (captcha) {
+ container.appendChild(divCaptcha);
+ }
+ container.appendChild(divActionButton);
+ container.appendChild(divCancelButton);
+ actionButton.value = 'Request a new password';
+ inputRecovery.value = 1;
+
+ // Action
+ action = 'requestNewPassword';
+ }
+
+ /**
+ * Confirm recovery code
+ */
+ obj.codeConfirmation = function() {
+ container.innerHTML = '';
+ container.appendChild(divLogo);
+ container.appendChild(divHash);
+ container.appendChild(divCode);
+ container.appendChild(divActionButton);
+ container.appendChild(divCancelButton);
+ actionButton.value = 'Confirm code';
+ inputRecovery.value = 2;
+
+ // Action
+ action = 'codeConfirmation';
+ }
+
+ /**
+ * Update my password
+ */
+ obj.changeMyPassword = function(hash) {
+ container.innerHTML = '';
+ container.appendChild(divLogo);
+ container.appendChild(divHash);
+ container.appendChild(divPassword);
+ container.appendChild(divRepeatPassword);
+ container.appendChild(divActionButton);
+ container.appendChild(divCancelButton);
+ actionButton.value = 'Change my password';
+ inputHash.value = hash;
+
+ // Action
+ action = 'changeMyPassword';
+ }
+
+ /**
+ * Request access default method
+ */
+ obj.requestAccess = function() {
+ container.innerHTML = '';
+ container.appendChild(divLogo);
+ container.appendChild(divUsername);
+ container.appendChild(divPassword);
+ container.appendChild(divActionButton);
+ if (obj.options.facebookAuthentication == true) {
+ container.appendChild(divFacebookButton);
+ }
+ container.appendChild(divRequestButton);
+ container.appendChild(divRememberButton);
+ container.appendChild(divRequestButton);
+ if (obj.options.newProfile == true) {
+ container.appendChild(divNewProfileButton);
+ }
+
+ // Button
+ actionButton.value = 'Login';
+
+ // Password
+ inputPassword.value = '';
+
+ // Email persistence
+ if (window.localStorage.getItem('username')) {
+ inputUsername.value = window.localStorage.getItem('username');
+ inputPassword.focus();
+ } else {
+ inputUsername.focus();
+ }
+
+ // Action
+ action = 'requestAccess';
+ }
+
+ /**
+ * Request login via facebook
+ */
+ obj.requestLoginViaFacebook = function() {
+ if (typeof(deviceNotificationToken) == 'undefined') {
+ FB.getLoginStatus(function(response) {
+ if (! response.status || response.status != 'connected') {
+ FB.login(function(response) {
+ if (response.authResponse) {
+ obj.execute({ f:response.authResponse.accessToken });
+ } else {
+ obj.showMessage('Not authorized by facebook');
+ }
+ }, {scope: 'public_profile,email'});
+ } else {
+ obj.execute({ f:response.authResponse.accessToken });
+ }
+ }, true);
+ } else {
+ jDestroy = function() {
+ fbLogin.removeEventListener('loadstart', jStart);
+ fbLogin.removeEventListener('loaderror', jError);
+ fbLogin.removeEventListener('exit', jExit);
+ fbLogin.close();
+ fbLogin = null;
+ }
+
+ jStart = function(event) {
+ var url = event.url;
+ if (url.indexOf("access_token") >= 0) {
+ setTimeout(function(){
+ var u = url.match(/=(.*?)&/);
+ if (u[1].length > 32) {
+ obj.execute({ f:u[1] });
+ }
+ jDestroy();
+ },500);
+ }
+
+ if (url.indexOf("error=access_denied") >= 0) {
+ setTimeout(jDestroy ,500);
+ // Not authorized by facebook
+ obj.showMessage('Not authorized by facebook');
+ }
+ }
+
+ jError = function(event) {
+ jDestroy();
+ }
+
+ jExit = function(event) {
+ jDestroy();
+ }
+
+ fbLogin = window.open(obj.options.facebookUrl, "_blank", "location=no,closebuttoncaption=Exit,disallowoverscroll=yes,toolbar=no");
+ fbLogin.addEventListener('loadstart', jStart);
+ fbLogin.addEventListener('loaderror', jError);
+ fbLogin.addEventListener('exit', jExit);
+ }
+
+ // Action
+ action = 'requestLoginViaFacebook';
+ }
+
+ // Perform request
+ obj.execute = function(data) {
+ // New profile
+ if (action == 'newProfile') {
+ var pattern = new RegExp(/^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/);
+ if (! inputUsername.value || ! pattern.test(inputUsername.value)) {
+ var message = 'Invalid e-mail address';
+ }
+
+ var pattern = new RegExp(/^[a-zA-Z0-9\_\-\.\s+]+$/);
+ if (! inputLogin.value || ! pattern.test(inputLogin.value)) {
+ var message = 'Invalid username, please use only characters and numbers';
+ }
+
+ if (message) {
+ obj.showMessage(message);
+ return false;
+ }
+ } else if (action == 'changeMyPassword') {
+ if (inputPassword.value.length < 3) {
+ var message = 'Password is too short';
+ } else if (inputPassword.value != inputRepeatPassword.value) {
+ var message = 'Password should match';
+ } else {
+ if (typeof(obj.options.newPasswordValidation) == 'function') {
+ var val = obj.options.newPasswordValidation(obj, inputPassword.value, inputPassword.value);
+ if (val != undefined) {
+ message = val;
+ }
+ }
+ }
+
+ if (message) {
+ obj.showMessage(message);
+ return false;
+ }
+ }
+
+ // Keep email
+ if (inputUsername.value != '') {
+ window.localStorage.setItem('username', inputUsername.value);
+ }
+
+ // Captcha
+ if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) {
+ if (inputCaptcha.value == '') {
+ obj.showMessage('Please enter the captch code below');
+ return false;
+ }
+ }
+
+ // Url
+ var url = obj.options.url;
+
+ // Device token
+ if (obj.options.deviceToken) {
+ url += '?token=' + obj.options.deviceToken;
+ }
+
+ // Callback
+ var onsuccess = function(result) {
+ if (result) {
+ // Successfully response
+ if (result.success == 1) {
+ // Recovery process
+ if (action == 'requestNewPassword') {
+ obj.codeConfirmation();
+ } else if (action == 'codeConfirmation') {
+ obj.requestAccess();
+ } else if (action == 'newProfile') {
+ obj.requestAccess();
+ // New profile
+ result.newProfile = true;
+ }
+
+ // Token
+ if (result.token) {
+ // Set token
+ obj.options.accessToken = result.token;
+ // Save token
+ window.localStorage.setItem('Access-Token', result.token);
+ }
+ }
+
+ // Show message
+ if (result.message) {
+ // Show message
+ obj.showMessage(result.message)
+ }
+
+ // Request captcha code
+ if (! result.data) {
+ if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) {
+ divCaptcha.remove();
+ }
+ } else {
+ container.insertBefore(divCaptcha, divActionButton);
+ imageCaptcha.setAttribute('src', 'data:image/png;base64,' + result.data);
+ }
+
+ // Give time to user see the message
+ if (result.hash) {
+ // Change password
+ obj.changeMyPassword(result.hash);
+ } else if (result.url) {
+ // App initialization
+ if (result.success == 1) {
+ if (typeof(obj.options.onsuccess) == 'function') {
+ obj.options.onsuccess(result);
+ } else {
+ if (result.message) {
+ setTimeout(function() { window.location.href = result.url; }, 2000);
+ } else {
+ window.location.href = result.url;
+ }
+ }
+ } else {
+ if (typeof(obj.options.onerror) == 'function') {
+ obj.options.onerror(result);
+ }
+ }
+ }
+ }
+ }
+
+ // Password
+ if (! data) {
+ var data = jSuites.form.getElements(el, true);
+ // Encode passworfd
+ if (data.password) {
+ data.password = jSuites.sha512(data.password);
+ }
+ // Recovery code
+ if (Array.prototype.indexOf.call(container.children, divCode) >= 0 && inputCode.value) {
+ data.h = jSuites.sha512(inputCode.value);
+ }
+ }
+
+ // Loading
+ el.classList.add('jlogin-loading');
+
+ // Url
+ var url = (action == 'newProfile' && obj.options.newProfileUrl) ? obj.options.newProfileUrl : obj.options.url;
+
+ // Remote call
+ jSuites.ajax({
+ url: url,
+ method: 'POST',
+ dataType: 'json',
+ data: data,
+ success: function(result) {
+ // Remove loading
+ el.classList.remove('jlogin-loading');
+ // Callback
+ onsuccess(result);
+ },
+ error: function(result) {
+ // Error
+ el.classList.remove('jlogin-loading');
+
+ if (typeof(obj.options.onerror) == 'function') {
+ obj.options.onerror(result);
+ }
+ }
+ });
+ }
+
+ var queryString = window.location.href.split('?');
+ if (queryString[1] && queryString[1].length == 130 && queryString[1].substr(0,2) == 'h=') {
+ obj.changeMyPassword(queryString[1].substr(2));
+ } else {
+ obj.requestAccess();
+ }
+
+ return obj;
+});
+
+jSuites.login.sha512 = jSuites.sha512;
+
+/**
+ * (c) jSuites template renderer
+ * https://github.com/paulhodel/jsuites
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Template renderer
+ */
+
+jSuites.template = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ url: null,
+ data: null,
+ filter: null,
+ pageNumber: 0,
+ numberOfPages: 0,
+ template: null,
+ render: null,
+ noRecordsFound: 'No records found',
+ // Searchable
+ search: null,
+ searchInput: true,
+ searchPlaceHolder: '',
+ searchValue: '',
+ // Remote search
+ remoteData: null,
+ // Pagination page number of items
+ pagination: null,
+ onload: null,
+ onchange: null,
+ onsearch: null,
+ }
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Reset content
+ el.innerHTML = '';
+
+ // Input search
+ if (obj.options.search && obj.options.searchInput == true) {
+ // Timer
+ var searchTimer = null;
+
+ // Search container
+ var searchContainer = document.createElement('div');
+ searchContainer.className = 'jtemplate-results';
+ obj.searchInput = document.createElement('input');
+ obj.searchInput.value = obj.options.searchValue;
+ obj.searchInput.onkeyup = function(e) {
+ // Clear current trigger
+ if (searchTimer) {
+ clearTimeout(searchTimer);
+ }
+ // Prepare search
+ searchTimer = setTimeout(function() {
+ obj.search(obj.searchInput.value.toLowerCase());
+ searchTimer = null;
+ }, 300)
+ }
+ searchContainer.appendChild(obj.searchInput);
+ el.appendChild(searchContainer);
+
+ if (obj.options.searchPlaceHolder) {
+ obj.searchInput.setAttribute('placeholder', obj.options.searchPlaceHolder);
+ }
+ }
+
+ // Pagination container
+ if (obj.options.pagination) {
+ var pagination = document.createElement('div');
+ pagination.className = 'jtemplate-pagination';
+ el.appendChild(pagination);
+ }
+
+ // Content
+ var container = document.createElement('div');
+ container.className = 'jtemplate-content options';
+ el.appendChild(container);
+
+ // Data container
+ var searchResults = null;
+
+ obj.updatePagination = function() {
+ // Reset pagination container
+ if (pagination) {
+ pagination.innerHTML = '';
+ }
+
+ // Create pagination
+ if (obj.options.pagination > 0 && obj.options.numberOfPages > 1) {
+ // Number of pages
+ var numberOfPages = obj.options.numberOfPages;
+
+ // Controllers
+ if (obj.options.pageNumber < 6) {
+ var startNumber = 1;
+ var finalNumber = numberOfPages < 10 ? numberOfPages : 10;
+ } else if (numberOfPages - obj.options.pageNumber < 5) {
+ var startNumber = numberOfPages - 9;
+ var finalNumber = numberOfPages;
+ if (startNumber < 1) {
+ startNumber = 1;
+ }
+ } else {
+ var startNumber = obj.options.pageNumber - 4;
+ var finalNumber = obj.options.pageNumber + 5;
+ }
+
+ // First
+ if (startNumber > 1) {
+ var paginationItem = document.createElement('div');
+ paginationItem.innerHTML = '<';
+ paginationItem.title = 1;
+ pagination.appendChild(paginationItem);
+ }
+
+ // Get page links
+ for (var i = startNumber; i <= finalNumber; i++) {
+ var paginationItem = document.createElement('div');
+ paginationItem.innerHTML = i;
+ pagination.appendChild(paginationItem);
+
+ if (obj.options.pageNumber == i - 1) {
+ paginationItem.style.fontWeight = 'bold';
+ }
+ }
+
+ // Last
+ if (finalNumber < numberOfPages) {
+ var paginationItem = document.createElement('div');
+ paginationItem.innerHTML = '>';
+ paginationItem.title = numberOfPages - 1;
+ pagination.appendChild(paginationItem);
+ }
+ }
+ }
+
+ /**
+ * Append data to the template and add to the DOMContainer
+ * @param data
+ * @param contentDOMContainer
+ */
+ obj.setContent = function(a, b) {
+ var c = obj.options.template[Object.keys(obj.options.template)[0]](a);
+ if ((c instanceof Element || c instanceof HTMLDocument)) {
+ b.appendChild(c);
+ } else {
+ b.innerHTML = c;
+ }
+ }
+
+ obj.addItem = function(data, beginOfDataSet) {
+ // Append itens
+ var content = document.createElement('div');
+ // Append data
+ if (beginOfDataSet) {
+ obj.options.data.unshift(data);
+ } else {
+ obj.options.data.push(data);
+ }
+ // If is empty remove indication
+ if (container.classList.contains('jtemplate-empty')) {
+ container.classList.remove('jtemplate-empty');
+ container.innerHTML = '';
+ }
+ // Get content
+ obj.setContent(data, content);
+ // Add animation
+ jSuites.animation.fadeIn(content.children[0]);
+ // Add and do the animation
+ if (beginOfDataSet) {
+ container.prepend(content.children[0]);
+ } else {
+ container.append(content.children[0]);
+ }
+ // Onchange method
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, obj.options.data);
+ }
+ }
+
+ obj.removeItem = function(element) {
+ if (Array.prototype.indexOf.call(container.children, element) > -1) {
+ // Remove data from array
+ var index = obj.options.data.indexOf(element.dataReference);
+ if (index > -1) {
+ obj.options.data.splice(index, 1);
+ }
+ // Remove element from DOM
+ jSuites.animation.fadeOut(element, function() {
+ element.parentNode.removeChild(element);
+
+ if (! container.innerHTML) {
+ container.classList.add('jtemplate-empty');
+ container.innerHTML = obj.options.noRecordsFound;
+ }
+ });
+ } else {
+ console.error('Element not found');
+ }
+ }
+
+ obj.setData = function(data) {
+ if (data) {
+ obj.options.pageNumber = 1;
+ obj.options.searchValue = '';
+ // Set data
+ obj.options.data = data;
+ // Reset any search results
+ searchResults = null;
+
+ // Render new data
+ obj.render();
+
+ // Onchange method
+ if (typeof(obj.options.onchange) == 'function') {
+ obj.options.onchange(el, obj.options.data);
+ }
+ }
+ }
+
+ obj.appendData = function(data, pageNumber) {
+ if (pageNumber) {
+ obj.options.pageNumber = pageNumber;
+ }
+
+ var execute = function(data) {
+ // Concat data
+ obj.options.data.concat(data);
+ // Number of pages
+ if (obj.options.pagination > 0) {
+ obj.options.numberOfPages = Math.ceil(obj.options.data.length / obj.options.pagination);
+ }
+ var startNumber = 0;
+ var finalNumber = data.length;
+ // Append itens
+ var content = document.createElement('div');
+ for (var i = startNumber; i < finalNumber; i++) {
+ obj.setContent(data[i], content)
+ content.children[0].dataReference = data[i]; // TODO: data[i] or i?
+ container.appendChild(content.children[0]);
+ }
+ }
+
+ if (obj.options.url && obj.options.remoteData == true) {
+ // URL
+ var url = obj.options.url;
+ // Data
+ var ajaxData = {};
+ // Options for backend search
+ if (obj.options.remoteData) {
+ // Search value
+ if (obj.options.searchValue) {
+ ajaxData.q = obj.options.searchValue;
+ }
+ // Page number
+ if (obj.options.pageNumber) {
+ ajaxData.p = obj.options.pageNumber;
+ }
+ // Number items per page
+ if (obj.options.pagination) {
+ ajaxData.t = obj.options.pagination;
+ }
+ }
+ // Remote loading
+ jSuites.ajax({
+ url: url,
+ method: 'GET',
+ data: ajaxData,
+ dataType: 'json',
+ success: function(data) {
+ execute(data);
+ }
+ });
+ } else {
+ if (! obj.options.data) {
+ console.log('TEMPLATE: no data or external url defined');
+ } else {
+ execute(data);
+ }
+ }
+ }
+
+ obj.renderTemplate = function() {
+ // Data container
+ var data = searchResults ? searchResults : obj.options.data;
+
+ // Reset pagination
+ obj.updatePagination();
+
+ if (! data.length) {
+ container.innerHTML = obj.options.noRecordsFound;
+ container.classList.add('jtemplate-empty');
+ } else {
+ // Reset content
+ container.classList.remove('jtemplate-empty');
+
+ // Create pagination
+ if (obj.options.pagination && data.length > obj.options.pagination) {
+ var startNumber = (obj.options.pagination * obj.options.pageNumber);
+ var finalNumber = (obj.options.pagination * obj.options.pageNumber) + obj.options.pagination;
+
+ if (data.length < finalNumber) {
+ var finalNumber = data.length;
+ }
+ } else {
+ var startNumber = 0;
+ var finalNumber = data.length;
+ }
+
+ // Append itens
+ var content = document.createElement('div');
+ for (var i = startNumber; i < finalNumber; i++) {
+ // Get content
+ obj.setContent(data[i], content);
+ content.children[0].dataReference = data[i];
+ container.appendChild(content.children[0]);
+ }
+ }
+ }
+
+ obj.render = function(pageNumber, forceLoad) {
+ // Update page number
+ if (pageNumber != undefined) {
+ obj.options.pageNumber = pageNumber;
+ } else {
+ if (! obj.options.pageNumber && obj.options.pagination > 0) {
+ obj.options.pageNumber = 0;
+ }
+ }
+
+ // Render data into template
+ var execute = function() {
+ // Render new content
+ if (typeof(obj.options.render) == 'function') {
+ container.innerHTML = obj.options.render(obj);
+ } else {
+ container.innerHTML = '';
+ }
+
+ // Load data
+ obj.renderTemplate();
+
+ // Onload
+ if (typeof(obj.options.onload) == 'function') {
+ obj.options.onload(el, obj);
+ }
+ }
+
+ if (obj.options.url && (obj.options.remoteData == true || forceLoad)) {
+ // URL
+ var url = obj.options.url;
+ // Data
+ var ajaxData = {};
+ // Options for backend search
+ if (obj.options.remoteData) {
+ // Search value
+ if (obj.options.searchValue) {
+ ajaxData.q = obj.options.searchValue;
+ }
+ // Page number
+ if (obj.options.pageNumber) {
+ ajaxData.p = obj.options.pageNumber;
+ }
+ // Number items per page
+ if (obj.options.pagination) {
+ ajaxData.t = obj.options.pagination;
+ }
+ }
+ // Remote loading
+ jSuites.ajax({
+ url: url,
+ method: 'GET',
+ dataType: 'json',
+ data: ajaxData,
+ success: function(data) {
+ // Search and keep data in the client side
+ if (data.hasOwnProperty("total")) {
+ obj.options.numberOfPages = Math.ceil(data.total / obj.options.pagination);
+ obj.options.data = data.data;
+ } else {
+ // Number of pages
+ if (obj.options.pagination > 0) {
+ obj.options.numberOfPages = Math.ceil(data.length / obj.options.pagination);
+ }
+ obj.options.data = data;
+ }
+
+ // Load data for the user
+ execute();
+ }
+ });
+ } else {
+ if (! obj.options.data) {
+ console.log('TEMPLATE: no data or external url defined');
+ } else {
+ // Number of pages
+ if (obj.options.pagination > 0) {
+ if (searchResults) {
+ obj.options.numberOfPages = Math.ceil(searchResults.length / obj.options.pagination);
+ } else {
+ obj.options.numberOfPages = Math.ceil(obj.options.data.length / obj.options.pagination);
+ }
+ }
+ // Load data for the user
+ execute();
+ }
+ }
+ }
+
+ obj.search = function(query) {
+ obj.options.pageNumber = 0;
+ obj.options.searchValue = query ? query : '';
+
+ // Filter data
+ if (obj.options.remoteData == true || ! query) {
+ searchResults = null;
+ } else {
+ var test = function(o, query) {
+ for (var key in o) {
+ var value = o[key];
+
+ if ((''+value).toLowerCase().search(query) >= 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (typeof(obj.options.filter) == 'function') {
+ searchResults = obj.options.filter(obj.options.data, query);
+ } else {
+ searchResults = obj.options.data.filter(function(item) {
+ return test(item, query);
+ });
+ }
+ }
+
+ obj.render();
+
+ if (typeof(obj.options.onsearch) == 'function') {
+ obj.options.onsearch(el, obj, query);
+ }
+ }
+
+ obj.refresh = function() {
+ obj.render();
+ }
+
+ obj.reload = function() {
+ obj.render(0, true);
+ }
+
+ el.addEventListener('mousedown', function(e) {
+ if (e.target.parentNode.classList.contains('jtemplate-pagination')) {
+ var index = e.target.innerText;
+ if (index == '<') {
+ obj.render(0);
+ } else if (index == '>') {
+ obj.render(e.target.getAttribute('title'));
+ } else {
+ obj.render(parseInt(index)-1);
+ }
+ e.preventDefault();
+ }
+ });
+
+ el.template = obj;
+
+ // Render data
+ obj.render(0, true);
+
+ return obj;
+});
+
+/**
+ * (c) jSuites Timeline
+ * https://github.com/paulhodel/jsuites
+ *
+ * @author: Paul Hodel <paul.hodel@gmail.com>
+ * @description: Timeline
+ */
+
+jSuites.timeline = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Two digits
+ var two = function(value) {
+ value = '' + value;
+ if (value.length == 1) {
+ value = '0' + value;
+ }
+ return value;
+ }
+
+ // Default date format
+ if (! options.date) {
+ var date = new Date();
+ var y = date.getFullYear();
+ var m = two(date.getMonth() + 1);
+ date = y + '-' + m;
+ }
+
+ // Default configurations
+ var defaults = {
+ url: null,
+ data: [],
+ date: date,
+ months: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
+ monthsFull: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
+ onaction: null,
+ text: {
+ noInformation: '<div class="jtimeline-message">No information for this period</div>',
+ }
+ };
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // Add class
+ el.classList.add('jtimeline');
+
+ // Header
+ var timelineHeader = document.createElement('div');
+ timelineHeader.className = 'jtimeline-header';
+
+ var timelineLabel = document.createElement('div');
+ timelineLabel.className = 'jtimeline-label';
+
+ var timelineNavigation = document.createElement('div');
+ timelineNavigation.className = 'jtimeline-navigation';
+
+ // Labels
+ var timelineMonth = document.createElement('div');
+ timelineMonth.className = 'jtimeline-month';
+ timelineMonth.innerHTML = '';
+ timelineLabel.appendChild(timelineMonth);
+
+ var timelineYear = document.createElement('div');
+ timelineYear.className = 'jtimeline-year';
+ timelineYear.innerHTML = '';
+ timelineLabel.appendChild(timelineYear);
+
+ // Navigation
+ var timelinePrev = document.createElement('div');
+ timelinePrev.className = 'jtimeline-prev';
+ timelinePrev.innerHTML = '<i class="material-icons">keyboard_arrow_left</i>';
+ timelineNavigation.appendChild(timelinePrev);
+
+ var timelineNext = document.createElement('div');
+ timelineNext.className = 'jtimeline-next';
+ timelineNext.innerHTML = '<i class="material-icons">keyboard_arrow_right</i>';
+ timelineNavigation.appendChild(timelineNext);
+
+ timelineHeader.appendChild(timelineLabel);
+ timelineHeader.appendChild(timelineNavigation);
+
+ // Data container
+ var timelineContainer = document.createElement('div');
+ timelineContainer.className = 'jtimeline-container';
+
+ // Append headers
+ el.appendChild(timelineHeader);
+ el.appendChild(timelineContainer);
+
+ // Date
+ if (obj.options.date.length > 7) {
+ obj.options.date = obj.options.date.substr(0, 7)
+ }
+
+ // Action
+ var action = function(o) {
+ // Get item
+ var item = o.parentNode.parentNode.parentNode.parentNode;
+ // Get id
+ var id = item.getAttribute('data-id');
+
+ }
+
+ obj.setData = function(rows) {
+ var data = [];
+ for (var i = 0; i < rows.length; i++) {
+ var d = rows[i].date.substr(0,7);
+
+ // Create the object if not exists
+ if (! data[d]) {
+ data[d] = [];
+ }
+
+ // Create array
+ data[d].push(rows[i]);
+ };
+ obj.options.data = data;
+ obj.render(obj.options.date);
+ }
+
+ obj.add = function(data) {
+ var date = data.date.substr(0,7);
+
+ // Create the object if not exists
+ if (! obj.options.data[date]) {
+ obj.options.data[date] = [];
+ }
+
+ // Format date
+ data.date = data.date.substr(0,10);
+
+ // Append data
+ obj.options.data[date].push(data);
+
+ // Reorder
+ obj.options.data[date] = obj.options.data[date].order();
+
+ // Render
+ obj.render(date);
+ }
+
+ obj.remove = function(item) {
+ var index = item.getAttribute('data-index');
+ var date = item.getAttribute('data-date');
+
+ jSuites.animation.fadeOut(item, function() {
+ item.remove();
+ });
+
+ obj.options.data[date].splice(index, 1);
+ }
+
+ obj.reload = function() {
+ var date = obj.options.date
+ obj.render(date);
+ }
+
+ obj.render = function(date) {
+ // Filter
+ if (date.length > 7) {
+ var date = date.substr(0,7);
+ }
+
+ // Update current date
+ obj.options.date = date;
+
+ // Reset data
+ timelineContainer.innerHTML = '';
+
+ // Days
+ var timelineDays = [];
+
+ // Itens
+ if (! obj.options.data[date]) {
+ timelineContainer.innerHTML = obj.options.text.noInformation;
+ } else {
+ for (var i = 0; i < obj.options.data[date].length; i++) {
+ var v = obj.options.data[date][i];
+ var d = v.date.split('-');
+
+ // Item container
+ var timelineItem = document.createElement('div');
+ timelineItem.className = 'jtimeline-item';
+ timelineItem.setAttribute('data-id', v.id);
+ timelineItem.setAttribute('data-index', i);
+ timelineItem.setAttribute('data-date', date);
+
+ // Date
+ var timelineDateContainer = document.createElement('div');
+ timelineDateContainer.className = 'jtimeline-date-container';
+
+ var timelineDate = document.createElement('div');
+ if (! timelineDays[d[2]]) {
+ timelineDate.className = 'jtimeline-date jtimeline-date-bullet';
+ timelineDate.innerHTML = d[2];
+ } else {
+ timelineDate.className = 'jtimeline-date';
+ timelineDate.innerHTML = '';
+ }
+ timelineDateContainer.appendChild(timelineDate);
+
+ var timelineContent = document.createElement('div');
+ timelineContent.className = 'jtimeline-content';
+
+ // Title
+ if (! v.title) {
+ v.title = v.subtitle ? v.subtitle : 'Information';
+ }
+
+ var timelineTitleContainer = document.createElement('div');
+ timelineTitleContainer.className = 'jtimeline-title-container';
+ timelineContent.appendChild(timelineTitleContainer);
+
+ var timelineTitle = document.createElement('div');
+ timelineTitle.className = 'jtimeline-title';
+ timelineTitle.innerHTML = v.title;
+ timelineTitleContainer.appendChild(timelineTitle);
+
+ var timelineControls = document.createElement('div');
+ timelineControls.className = 'jtimeline-controls';
+ timelineTitleContainer.appendChild(timelineControls);
+
+ var timelineEdit = document.createElement('i');
+ timelineEdit.className = 'material-icons timeline-edit';
+ timelineEdit.innerHTML = 'edit';
+ timelineEdit.onclick = function() {
+ if (typeof(obj.options.onaction) == 'function') {
+ obj.options.onaction(obj, this);
+ }
+ }
+ if (v.author == 1) {
+ timelineControls.appendChild(timelineEdit);
+ }
+
+ var timelineSubtitle = document.createElement('div');
+ timelineSubtitle.className = 'jtimeline-subtitle';
+ timelineSubtitle.innerHTML = v.subtitle ? v.subtitle : '';
+ timelineContent.appendChild(timelineSubtitle);
+
+ // Text
+ var timelineText = document.createElement('div');
+ timelineText.className = 'jtimeline-text';
+ timelineText.innerHTML = v.text;
+ timelineContent.appendChild(timelineText);
+
+ // Tag
+ var timelineTags = document.createElement('div');
+ timelineTags.className = 'jtimeline-tags';
+ timelineContent.appendChild(timelineTags);
+
+ if (v.tags) {
+ var createTag = function(name, color) {
+ var timelineTag = document.createElement('div');
+ timelineTag.className = 'jtimeline-tag';
+ timelineTag.innerHTML = name;
+ if (color) {
+ timelineTag.style.backgroundColor = color;
+ }
+ return timelineTag;
+ }
+
+ if (typeof(v.tags) == 'string') {
+ var t = createTag(v.tags);
+ timelineTags.appendChild(t);
+ } else {
+ for (var j = 0; j < v.tags.length; j++) {
+ var t = createTag(v.tags[j].text, v.tags[j].color);
+ timelineTags.appendChild(t);
+ }
+ }
+ }
+
+ // Day
+ timelineDays[d[2]] = true;
+
+ // Append Item
+ timelineItem.appendChild(timelineDateContainer);
+ timelineItem.appendChild(timelineContent);
+ timelineContainer.appendChild(timelineItem);
+ };
+ }
+
+ // Update labels
+ var d = date.split('-');
+ timelineYear.innerHTML = d[0];
+ timelineMonth.innerHTML = obj.options.monthsFull[parseInt(d[1]) - 1];
+ }
+
+ obj.next = function() {
+ // Update current date
+ var d = obj.options.date.split('-');
+ // Next month
+ d[1]++;
+ // Next year
+ if (d[1] > 12) {
+ d[0]++;
+ d[1] = 1;
+ }
+ date = d[0] + '-' + (d[1] < 10 ? '0' + d[1] : d[1]);
+
+ // Animation
+ jSuites.animation.slideLeft(timelineContainer, 0, function() {
+ obj.render(date);
+ jSuites.animation.slideRight(timelineContainer, 1);
+ });
+ }
+
+ obj.prev = function() {
+ // Update current date
+ var d = obj.options.date.split('-');
+ // Next month
+ d[1]--;
+ // Next year
+ if (d[1] < 1) {
+ d[0]--;
+ d[1] = 12;
+ }
+ date = d[0] + '-' + (d[1] < 10 ? '0' + d[1] : d[1]);
+
+ // Animation
+ jSuites.animation.slideRight(timelineContainer, 0, function() {
+ obj.render(date);
+ jSuites.animation.slideLeft(timelineContainer, 1);
+ });
+ }
+
+ obj.load = function() {
+ // Init
+ if (obj.options.url) {
+ jSuites.ajax({
+ url: obj.options.url,
+ type: 'GET',
+ dataType:'json',
+ success: function(data) {
+ // Timeline data
+ obj.setData(data);
+ }
+ });
+ } else {
+ // Timeline data
+ obj.setData(obj.options.data);
+ }
+ }
+
+ obj.reload = function() {
+ obj.load();
+ }
+
+ obj.load();
+
+ var timelineMouseUpControls = function(e) {
+ if (e.target.classList.contains('jtimeline-next') || e.target.parentNode.classList.contains('jtimeline-next')) {
+ obj.next();
+ } else if (e.target.classList.contains('jtimeline-prev') || e.target.parentNode.classList.contains('jtimeline-prev')) {
+ obj.prev();
+ }
+ }
+
+ if ('ontouchend' in document.documentElement === true) {
+ el.addEventListener("touchend", timelineMouseUpControls);
+ } else {
+ el.addEventListener("mouseup", timelineMouseUpControls);
+ }
+
+ // Add global events
+ el.addEventListener("swipeleft", function(e) {
+ obj.next();
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ el.addEventListener("swiperight", function(e) {
+ obj.prev();
+ e.preventDefault();
+ e.stopPropagation();
+ });
+
+ // Orderby
+ Array.prototype.order = function() {
+ return this.slice(0).sort(function(a, b) {
+ var valueA = a.date;
+ var valueB = b.date;
+
+ return (valueA > valueB) ? 1 : (valueA < valueB) ? -1 : 0;
+ });
+ }
+
+ el.timeline = obj;
+
+ return obj;
+});
diff --git a/web-tools/web/_static/jsuites/jsuites.mobile.css b/web-tools/web/_static/jsuites/jsuites.mobile.css
new file mode 100644
index 0000000..62f84a6
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.mobile.css
@@ -0,0 +1,1015 @@
+
+/**
+ * (c) jSuites Javascript Web Components
+ *
+ * Author: Paul Hodel <paul.hodel@gmail.com>
+ * Website: https://bossanova.uk/jsuites/
+ * Description: Create amazing web based applications.
+ *
+ * MIT License
+ *
+ */
+
+.japp {
+ height: 100%;
+ box-sizing: border-box;
+ overflow: scroll;
+ background-color: #fafafa;
+ line-height: 1.4;
+ font-size: 16px;
+ font-family:-apple-system,SF UI Text,Helvetica Neue,Helvetica,Arial,sans-serif !important;
+}
+
+.japp a {
+ text-decoration: none;
+}
+
+.japp input, .japp textarea, .japp select, .japp div {
+ font-family:-apple-system,SF UI Text,Helvetica Neue,Helvetica,Arial,sans-serif !important;
+}
+
+.japp .red {
+ color: red;
+ border-color: 1px solid red;
+}
+
+.japp .link {
+ color: var(--active-color);
+ cursor: pointer;
+}
+
+.japp button {
+ border-radius: 4px;
+ width: 100%;
+ border: 1px solid var(--active-color);
+ color: var(--active-color);
+ background-color: transparent;
+ padding: 4px;
+ outline: none;
+}
+
+.japp button:active {
+ border: 1px solid #000;
+ color: #000;
+}
+
+.japp.warning::before {
+ content: 'No internet connection';
+ background-color: red;
+ color: #fff;
+ padding: 2px;
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ z-index: 10;
+ width: 100%;
+ font-size: 0.55em;
+ text-align: center;
+}
+
+japp.jwarning .page {
+ padding-top: 60px;
+}
+
+/** Navbar **/
+
+.japp .navbar {
+ position:fixed;
+ top: 0;
+ width: 100%;
+ z-index: 1;
+ margin: 0;
+ -webkit-backface-visibility: hidden;
+ -webkit-transform: translate3d(0,0,0);
+ -webkit-box-sizing: border-box;
+ backface-visibility: hidden;
+ box-sizing: border-box;
+ transform: translate3d(0,0,0);
+ height: 44px;
+ background-color: #fff;
+ box-shadow: 0 1px 2px rgba(0,0,0,.1);
+}
+
+.japp.jwarning .navbar {
+ top:16px;
+}
+
+.japp .navbar-container {
+ padding: 0 8px;
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align:middle;
+
+ display: flex;
+
+ -webkit-flex-flow: row wrap;
+ justify-content: space-between;
+ align-items:center;
+}
+
+.japp .navbar-container div {
+ text-align:center;
+}
+
+.japp .navbar-container div.title {
+ display: flex;
+}
+
+.japp .navbar-container div.title div
+{
+ line-height:24px;
+}
+
+.japp .navbar-container div.icon {
+ width:24px;
+}
+
+.japp .navbar-container div i {
+ display:block;
+}
+
+.japp .navbar-container div img {
+ height:28px;
+ display:block;
+}
+
+.japp .navbar-container div.title div img {
+ border-radius:12px;
+ width:24px;
+ height:24px;
+ margin-right:6px;
+}
+
+.japp .navbar .icon {
+ color:var(--active-color);
+}
+
+.japp .title {
+ font-size:1.2em;
+}
+
+.japp .block {
+ padding:15px;
+ color: #6d6d72;
+ font-size:0.9em;
+ box-sizing: border-box;
+}
+
+.japp .block-title {
+ text-transform: uppercase;
+ color: #6d6d72;
+ margin: 25px 15px 10px;
+ line-height: 17px;
+ position: relative;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ line-height: 1;
+ font-size:0.9em;
+}
+
+.japp .block-strong {
+ background-color:#fff;
+ color: #000;
+}
+
+.japp .block-border {
+ border-top:1px solid #ddd;
+ border-bottom:1px solid #ddd;
+}
+
+.japp .block-footer {
+ text-transform: uppercase;
+ padding:15px;
+ color: #6d6d72;
+ font-size:0.7em;
+}
+
+.japp .block-collapse {
+ max-height:100px;
+ overflow-y:hidden;
+}
+
+.japp .block-instruction {
+ text-transform: uppercase;
+ padding:15px;
+ color: #6d6d72;
+ font-size:0.7em;
+ text-align:center;
+}
+
+.japp .pages {
+ position: absolute;
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: flex-start;
+ height: 100%;
+ width: 100%;
+}
+
+.japp .page {
+ padding-top: 45px;
+ padding-bottom: 45px;
+ min-height: 100%;
+ min-width: 100%;
+ box-sizing: border-box;
+ overflow-y: auto;
+ /*will-change: scroll-position;
+ -webkit-overflow-scrolling: touch;
+ -webkit-transform: translateZ(0px);
+ -webkit-transform: translate3d(0,0,0);
+ -webkit-perspective: 1000;*/
+}
+
+.japp .panel {
+ position:fixed;
+ top: 0;
+ left: 0;
+ margin: 0;
+ width:60vw;
+ max-width:220px;
+ height:100vh;
+ background: #fff;
+ z-index: 2;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ box-shadow: 0 -1px 2px rgba(0,0,0,.1);
+ padding:4px;
+}
+
+.japp .panel-left {
+ -webkit-box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
+ box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
+}
+
+.japp .panel a {
+ color:var(--active-color);
+}
+
+
+/** Options **/
+
+.japp .options
+{
+ background-color:#fff;
+ border-top:1px solid #e6e6e8;
+ border-bottom:1px solid #e6e6e8;
+ padding-left:15px;
+ margin-top:10px;
+}
+
+.japp .options:empty
+{
+ display:none;
+}
+
+.japp .options .option
+{
+ padding-top:10px;
+ padding-bottom:10px;
+ text-transform:uppercase;
+ font-size:1em;
+ border-bottom:1px solid #e6e6e8;
+ overflow-x:hidden;
+
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align:middle;
+
+ display: -webkit-box;
+ display: -moz-box;
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+
+ -webkit-flex-flow: row nowrap;
+ justify-content: space-between;
+ align-items:center;
+ flex-wrap:nowrap;
+}
+
+.japp .options .option:last-child
+{
+ border-bottom:0px;
+}
+
+.japp .options label
+{
+ width:100%;
+}
+
+.japp .options input[type='text'], .japp .options textarea
+{
+ outline:none;
+ border:1px solid transparent;
+ font-size:1em;
+ margin:0px;
+ padding:0px;
+ width:100%;
+ box-sizing:border-box;
+}
+
+.japp .options textarea
+{
+ height:100px;
+}
+
+.japp .options input[type='checkbox'], .japp .options input[type='radio']
+{
+ visibility: hidden;
+}
+
+.japp .options input[type='checkbox'] ~ i, .japp .options input[type='radio'] ~ i
+{
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxeiIgZmlsbD0iIzAwN2FmZiIvPjwvc3ZnPg==');
+ background-repeat: no-repeat;
+ content:'';
+ visibility: hidden;
+ margin-right:10px;
+ line-height:24px;
+ width:24px;
+ height:24px;
+}
+
+.japp .options input[type='checkbox']:checked ~ i, .japp .options input[type='radio']:checked ~ i
+{
+ visibility: visible;
+}
+
+.japp .options .jdropdown {
+ display: block;
+}
+
+.japp .options .jdropdown .jdropdown-header {
+ border: 0px;
+ padding: 0px;
+ border-bottom: 1px solid #e6e6e8;
+ text-transform: uppercase;
+ outline: none;
+}
+
+.japp .options .jdropdown:last-child .jdropdown-header {
+ border-bottom: 0px;
+}
+
+.japp .options .jdropdown-searchbar.jdropdown-focus .jdropdown-header {
+ border:0px;
+ padding: 5px;
+}
+
+.japp .options .jcalendar-input {
+ background-position: top 50% right 8px;
+}
+
+.japp .options .icon {
+ float:left;
+ margin-right:10px;
+ max-width:40px;
+ max-height:40px;
+ border-radius:20px;
+ color:#929292;
+}
+
+.japp .options .option .option-actions {
+ display:flex;
+ transform: translateX(100%);
+ width:0px;
+}
+
+.japp .options .option .option-actions > div {
+ padding-right:5px;
+}
+
+.japp .options .option .option-actions > div > i {
+ width:40px;
+ height:40px;
+ color:#fff;
+ font-size:24px;
+ line-height:40px;
+ text-align:center;
+ border-radius:30px;
+ background-color:red;
+}
+
+.japp .options .option .option-actions.small > div > i
+{
+ color:#000;
+ width:24px;
+ height:24px;
+ font-size:24px;
+ line-height:24px;
+ border-radius:24px;
+ background-color:transparent;
+}
+
+.japp .options .option-title {
+ display:block;
+ padding-top:10px;
+ padding-bottom:10px;
+ text-transform:uppercase;
+ font-size:1em;
+ vertical-align:center;
+}
+
+.japp .options .option-title::after {
+ content:'\e313';
+ font-family: 'material icons';
+ font-size:24px;
+ margin-right:10px;
+ float:right;
+ width:24px;
+ height:24px;
+ line-height:24px;
+}
+
+.japp .options .option-title.selected::after
+{
+ content:'\e316';
+}
+
+.japp .options .option-title.selected ~ div {
+ display:block;
+}
+
+.japp .options .option-group {
+ border-top:1px solid #e6e6e8;
+ background-color:#fff;
+ display:none;
+}
+
+.japp .options .option-link:after {
+ content:'\e315';
+ font-family: 'material icons';
+ color:var(--active-color);
+ font-size:24px;
+ margin-right:10px;
+ float:right;
+ width:24px;
+ height:24px;
+ line-height:24px;
+ display:block;
+}
+
+.japp .options .option-header {
+ padding-left:10px;
+ padding-right:10px;
+ flex-grow:10;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.japp .options .option .option-name {
+ font-size:1em;
+ text-overflow: ellipsis;
+ width: 100%;
+ overflow: hidden;
+}
+
+.japp .options .option .option-small {
+ font-size:0.7em;
+ color: #6d6d72;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ display:block;
+}
+
+.japp .options .option .option-image img {
+ width:40px;
+ height:40px;
+ border-radius:20px;
+ display:block;
+}
+
+.japp .options .option .option-image-small img {
+ width:24px;
+ height:auto;
+ border-radius:50px;
+ display:block;
+}
+
+.japp .options .option .option-image .option-badge {
+ position: absolute;
+ background-color: red;
+ color: #fff;
+ width: 16px;
+ height: 16px;
+ line-height: 16px;
+ border-radius: 16px;
+ text-align: center;
+ font-size: 7px;
+ margin: 28px;
+}
+
+.japp .options .option .option-image-small .option-badge {
+ position: absolute;
+ background-color: red;
+ color: #fff;
+ width: 16px;
+ height: 16px;
+ line-height: 16px;
+ border-radius: 16px;
+ text-align: center;
+ font-size: 7px;
+ margin: 12px;
+}
+
+.japp .options .option .option-badge.solid {
+ background-color: red;
+ color: red;
+}
+
+.japp .options .option .option-badge.solid-green {
+ background-color: green;
+ color: green;
+}
+
+.japp .options .option .option-badge:empty {
+ display:none;
+}
+
+.japp .options .option .option-date {
+ float:right;
+ font-size:0.6em;
+ color:#888;
+ margin-right:15px;
+ white-space: nowrap;
+}
+
+.japp .options .option .option-right {
+ margin-right:15px;
+}
+
+.japp .options .option .option-badget {
+ background-color:red;
+ border-radius:12px;
+ width:24px;
+ height:24px;
+ line-height:24px;
+ font-size:0.7em;
+ color:#fff;
+ text-align:center;
+}
+
+.japp .options .option .option-badget:empty {
+ display:none;
+}
+
+.japp .options input::-webkit-input-placeholder
+{
+ text-transform:uppercase;
+}
+
+.japp .options input::-moz-placeholder
+{
+ text-transform:uppercase;
+}
+
+.japp .options input:-ms-input-placeholder
+{
+ text-transform:uppercase;
+}
+
+.japp .options input:-moz-placeholder
+{
+ text-transform:uppercase;
+}
+
+/** Actionsheet **/
+
+.jactionsheet
+{
+ position:fixed;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ min-height:100%;
+ z-index:10;
+
+ background-color:rgba(0,0,0,0.5);
+ -webkit-transition-duration: .2s;
+ transition-duration: .2s;
+ display: flex;
+ -ms-flex-align: baseline;
+ -webkit-align-items: baseline;
+ -webkit-box-align: baseline;
+
+ align-items: baseline;
+}
+
+.jactionsheet .jactionsheet-content
+{
+ width:100%;
+ align-self: flex-end;
+}
+
+.jactionsheet .jactionsheet-title
+{
+ font-size:1em;
+ font-weight:bold;
+ padding:8px;
+}
+
+.jactionsheet .jactionsheet-message
+{
+ padding:4px;
+}
+
+.jactionsheet .jactionsheet-group
+{
+ box-sizing: border-box;
+ margin:10px;
+ background-color:#fff;
+ border-radius:5px;
+}
+
+.jactionsheet .jactionsheet-group > div
+{
+ font-size:1.4em;
+ font-weight:bold;
+ padding:4px;
+ border-top:1px solid #ccc;
+ text-align:center;
+ width:100%;
+ box-sizing: border-box;
+}
+.jactionsheet .jactionsheet-group > div:first-child
+{
+ border-top:0px;
+}
+
+.jactionsheet .jactionsheet-group input
+{
+ border:0px;
+ margin:0px;
+ background-color:transparent;
+ color:var(--active-color);
+ width:100%;
+ outline:none;
+ font-size:1em;
+}
+
+.jactionsheet .jactionsheet-group input.jactionsheet-cancel
+{
+ color:red;
+}
+
+/** Badge **/
+
+.japp .jbadge
+{
+ position:relative;
+ display:inline-block;
+ top:-12px;
+ left:-12px;
+}
+
+.japp .jbadge > div
+{
+ background-color:red;
+ color:#fff;
+ width:16px;
+ height:16px;
+ line-height:16px;
+ border-radius:16px;
+ text-align:center;
+ font-size:8px;
+ position:absolute;
+}
+
+.japp .jbadge > div:empty
+{
+ display:none;
+}
+
+/** Progressbar **/
+
+
+.japp .progressbar-container {
+ margin: 15px;
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 5px;
+}
+
+.japp .progressbar {
+ width:100%;
+ border:1px solid var(--active-color);
+ border-radius:1px;
+}
+
+.japp .progressbar-title {
+ margin-bottom:2px;
+ text-transform:uppercase;
+ display:flex;
+ justify-content:space-between;
+}
+
+.japp .progressbar div {
+ background-color:var(--active-color);
+ height:4px;
+ width:0%;
+}
+
+
+/** Topsearch **/
+
+.japp .top-search {
+ margin: 0px;
+ padding: 10px;
+ border-bottom: 1px solid #ddd;
+}
+
+.japp .top-search input {
+ background-color: #e6e6e6;
+ border: 0px;
+ border-radius: 4px;
+ outline: none;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='gray'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-position: 5px center;
+ width: 100%;
+ padding: 8px;
+ padding-left: 32px;
+}
+
+/** Range **/
+
+.japp .range
+{
+ -webkit-appearance: none;
+ margin: 18px 0;
+ width: 100%;
+}
+
+.japp .range:focus
+{
+ outline: none;
+}
+
+.japp .range::-webkit-slider-runnable-track
+{
+ width: 100%;
+ height: 4px;
+ cursor: pointer;
+ animation: 0.2s;
+ background: #ccc;
+ border-radius: 1.3px;
+}
+
+.japp .range::-webkit-slider-thumb
+{
+ -webkit-appearance:none;
+ appearance:none;
+ width:24px;
+ height:24px;
+ background:#fff;
+ cursor:pointer;
+ border-radius:24px;
+ margin-top:-10px;
+ border:0px;
+ box-shadow:0px 1px 3px 1px #bbb;
+}
+
+.japp .range::-moz-range-track
+{
+ width:100%;
+ cursor:pointer;
+ animation:0.2s;
+ background:#ccc;
+ border-radius:1.3px;
+}
+
+.japp .range::-moz-range-thumb
+{
+ width:24px;
+ height:24px;
+ background:#fff;
+ cursor:pointer;
+ border-radius:24px;
+ border:0px;
+ box-shadow:0px 1px 3px 1px #bbb;
+}
+
+.japp .range::-ms-track
+{
+ width: 100%;
+ cursor: pointer;
+ animation: 0.2s;
+ background: transparent;
+ border-color: transparent;
+ border-width: 16px 0;
+ color: transparent;
+ border-radius:1.3px;
+}
+
+.japp .range::-ms-fill-lower
+{
+ background:#ccc;
+ height:5px;
+}
+
+.japp .range::-ms-fill-upper
+{
+ background:#ccc;
+ height:5px;
+}
+
+.japp .range::-ms-thumb {
+ width:24px;
+ height:24px;
+ background:#fff;
+ cursor:pointer;
+ border-radius:24px;
+ border:0px;
+ box-shadow:0px 1px 3px 1px #bbb;
+}
+
+.japp .range:focus::-ms-fill-lower
+{
+ background: #ccc;
+}
+
+.japp .range:focus::-ms-fill-upper
+{
+ background: #ccc;
+}
+
+/** Placeholders **/
+
+.japp *::placeholder
+{
+ color: #cccccc;
+ opacity: 1;
+}
+
+.japp *:-ms-input-placeholder
+{
+ color: #cccccc;
+}
+
+.japp *::-ms-input-placeholder
+{
+ color: #cccccc;
+}
+
+.japp *::-webkit-input-placeholder
+{
+ color: #cccccc;
+}
+
+@supports (-webkit-overflow-scrolling: touch) {
+ .app .options input:checked:before {
+ top:-12px;
+ }
+}
+
+@media only screen and (max-device-width : 800px)
+{
+ .jsuites * {
+ -webkit-tap-highlight-color: transparent;
+ -webkit-touch-callout: none;
+ }
+
+ body.jsuites {
+ margin: 0px;
+ padding: 0px;
+ width: 100%;
+ height: 100%;
+ min-height: 100%;
+ line-height: 1.4;
+ font-family: -apple-system,SF UI Text,Helvetica Neue,Helvetica,Arial,sans-serif !important;
+ background-color: #fff;
+ }
+
+ .jsuites input, .jsuites select, .jsuites textarea, .jsuites div {
+ font-family:-apple-system,SF UI Text,Helvetica Neue,Helvetica,Arial,sans-serif !important;
+ }
+}
+
+.app .jtemplate-empty {
+ text-align:center;
+ padding-top:10px;
+ padding-bottom:10px;
+ margin-right:10px;
+}
+
+/**
+ * Dialog v1.0.1
+ * Author: paul.hodel@gmail.com
+ * https://github.com/paulhodel/jtools
+ */
+
+.jdialog
+{
+ position:fixed;
+ left: 0;
+ top: 0;
+ width: 100%;
+ min-height:100%;
+ z-index:10;
+
+ background-color:rgba(0,0,0,0.5);
+ -webkit-transition-duration: .1s;
+ transition-duration: .1s;
+ display: flex;
+ -ms-flex-align: center;
+ -webkit-align-items: center;
+ -webkit-box-align: center;
+
+ align-items: center;
+}
+
+.jdialog .jdialog-container
+{
+ width:100%;
+ max-width:280px;
+ box-sizing: border-box;
+ margin:0 auto;
+ vertical-align:middle;
+ background-color:#fff;
+ border-radius:10px;
+
+ opacity: 0;
+ transition: opacity .2s;
+ -webkit-transition: opacity .2s;
+}
+
+.jdialog .jdialog-header
+{
+ padding:10px;
+ text-align:center;
+}
+
+.jdialog .jdialog-header .jdialog-title
+{
+ font-size:1em;
+ font-weight:bold;
+ padding:8px;
+}
+
+.jdialog .jdialog-header .jdialog-message
+{
+ padding: 4px;
+}
+
+.jdialog .jdialog-footer
+{
+ border-top: 1px solid #ccc;
+ display: flex;
+ flex-wrap: wrap;
+ align-content: stretch;
+ align-items: center;
+ text-align: center;
+}
+
+.jdialog .jdialog-footer > div
+{
+ padding:4px;
+ border-left:1px solid #ccc;
+ text-align:center;
+ flex: 1;
+}
+.jdialog .jdialog-footer > div:first-child
+{
+ border-left:0px;
+}
+
+.jdialog .jdialog-footer input
+{
+ border: 0px;
+ margin: 0px;
+ background-color: transparent;
+ color: var(--active-color);
+ width: 100%;
+ outline: none;
+}
+
+.jrefresh {
+ background-image: url("data:image/svg+xml,%3Csvg class='lds-typing' width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid'%3E%3Ccircle cx='27.5' cy='38.1294' r='5' fill='%23df1317'%3E%3Canimate attributeName='cy' calcMode='spline' keySplines='0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5' repeatCount='indefinite' values='62.5;37.5;62.5;62.5' keyTimes='0;0.25;0.5;1' dur='1s' begin='-0.5s'%3E%3C/animate%3E%3C/circle%3E%3Ccircle cx='42.5' cy='38.9606' r='5' fill='%23e4934b'%3E%3Canimate attributeName='cy' calcMode='spline' keySplines='0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5' repeatCount='indefinite' values='62.5;37.5;62.5;62.5' keyTimes='0;0.25;0.5;1' dur='1s' begin='-0.375s'%3E%3C/animate%3E%3C/circle%3E%3Ccircle cx='57.5' cy='48.6466' r='5' fill='%23e2bb8b'%3E%3Canimate attributeName='cy' calcMode='spline' keySplines='0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5' repeatCount='indefinite' values='62.5;37.5;62.5;62.5' keyTimes='0;0.25;0.5;1' dur='1s' begin='-0.25s'%3E%3C/animate%3E%3C/circle%3E%3Ccircle cx='72.5' cy='62.5' r='5' fill='%23e1e7e7'%3E%3Canimate attributeName='cy' calcMode='spline' keySplines='0 0.5 0.5 1;0.5 0 1 0.5;0.5 0.5 0.5 0.5' repeatCount='indefinite' values='62.5;37.5;62.5;62.5' keyTimes='0;0.25;0.5;1' dur='1s' begin='-0.125s'%3E%3C/animate%3E%3C/circle%3E%3C/svg%3E");
+ background-repeat: no-repeat;
+ background-size: 70px;
+ background-position: center;
+ backgrounnd-color: transparent;
+ width: 100%;
+ height: 70px;
+}
+
+.jrefresh.holding {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
+ background-size: 24px;
+}
+
+.jrefresh.ready {
+ transform: rotate(-180deg);
+ transition: transform 150ms ease;
+}
+
+
+
diff --git a/web-tools/web/_static/jsuites/jsuites.mobile.js b/web-tools/web/_static/jsuites/jsuites.mobile.js
new file mode 100644
index 0000000..a6beee8
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.mobile.js
@@ -0,0 +1,793 @@
+jSuites.app = (function(el, options) {
+ var obj = {};
+ obj.options = {};
+
+ // Default configuration
+ var defaults = {
+ path: 'views',
+ onbeforechangepage: null,
+ onchangepage: null,
+ oncreatepage: null,
+ onloadpage: null,
+ toolbar: null,
+ }
+
+ // Loop through our object
+ for (var property in defaults) {
+ if (options && options.hasOwnProperty(property)) {
+ obj.options[property] = options[property];
+ } else {
+ obj.options[property] = defaults[property];
+ }
+ }
+
+ // App
+ el.classList.add('japp');
+
+ obj.setToolbar = function(toolbar) {
+ if (toolbar) {
+ obj.options.toolbar = toolbar;
+ }
+ var toolbar = document.createElement('div');
+ obj.toolbar = jSuites.toolbar(toolbar, {
+ app: obj,
+ items: obj.options.toolbar,
+ });
+ el.appendChild(toolbar);
+ }
+
+ /**
+ * Pages
+ */
+ obj.pages = function() {
+ /**
+ * Create or access a page
+ */
+ var component = function(route, o, callback) {
+ // Page options
+ if (o && typeof(o) == 'object') {
+ var options = o;
+ } else {
+ var options = {};
+ if (! callback && typeof(o) == 'function') {
+ callback = o;
+ }
+ }
+
+ // If exists just open
+ if (component.container[route]) {
+ component.show(component.container[route], options, callback);
+ } else {
+ // Create a new page
+ if (! route) {
+ console.error('JSUITES: Error, no route provided');
+ } else {
+ // Closed
+ options.closed = options.closed ? 1 : 0;
+ // Keep Route
+ options.route = route;
+
+ // New page url
+ if (! options.url) {
+ options.url = obj.options.path + route + '.html';
+ }
+
+ // Create new page
+ component.create(options, callback);
+ }
+ }
+ }
+
+ /**
+ * Create a new page
+ */
+ component.create = function(o, callback) {
+ // Create page
+ var page = document.createElement('div');
+ page.classList.add('page');
+
+ // Container
+ component.container[o.route] = page;
+
+ // Always hidden
+ page.style.display = 'none';
+
+ // Keep options
+ page.options = o ? o : {};
+
+ if (! component.current) {
+ pages.appendChild(page);
+ } else {
+ pages.insertBefore(page, component.current.nextSibling);
+ }
+
+ jSuites.ajax({
+ url: o.url,
+ method: 'GET',
+ dataType: 'html',
+ success: function(result) {
+ // Create page overwrite
+ var ret = null;
+ if (typeof(obj.options.oncreatepage) == 'function') {
+ ret = obj.options.oncreatepage(obj, page, result);
+ }
+
+ // Push to refresh controls
+ if (typeof(page.options.onpush) == 'function') {
+ jSuites.refresh(page, page.options.onpush);
+ }
+
+ // Ignore create page actions
+ if (ret !== false) {
+ // Open page
+ page.innerHTML = result;
+ // Get javascript
+ parseScript(page);
+ }
+
+ // Global onload callback
+ if (typeof(obj.options.onloadpage) == 'function') {
+ obj.options.onloadpage(page);
+ }
+
+ // Specific online callback
+ if (typeof(o.onload) == 'function') {
+ o.onload(page);
+ }
+
+ // Show page
+ if (! page.options.closed) {
+ component.show(page, o, callback);
+ }
+ }
+ });
+
+ return page;
+ }
+
+ component.show = function(page, o, callback) {
+ var pageIsReady = function() {
+ // New page
+ if (typeof(obj.options.onchangepage) == 'function') {
+ obj.options.onchangepage(obj, component.current, page, o);
+ }
+
+ // Enter event
+ if (typeof(page.options.onenter) == 'function') {
+ page.options.onenter(obj, page, component.current);
+ }
+
+ // Callback
+ if (typeof(callback) == 'function') {
+ callback(obj, page);
+ }
+
+ // Current page
+ component.current = page;
+ }
+
+ if (component.current) {
+ if (component.current != page) {
+ // Keep scroll in the top
+ window.scrollTo({ top: 0 });
+
+ // Show page
+ page.style.display = '';
+
+ var a = Array.prototype.indexOf.call(pages.children, component.current);
+ var b = Array.prototype.indexOf.call(pages.children, page);
+
+ // Before leave the page
+ if (typeof(obj.options.onbeforechangepage) == 'function') {
+ var ret = obj.options.onbeforechangepage(obj, component.current, page, o);
+ if (ret === false) {
+ return false;
+ }
+ }
+
+ // Leave event
+ if (typeof(page.options.onleave) == 'function') {
+ page.options.onleave(obj, component.current);
+ }
+
+ jSuites.animation.slideLeft(pages, (a < b ? 0 : 1), function() {
+ if (component.current != page) {
+ component.current.style.display = 'none';
+
+ // Page is ready
+ pageIsReady();
+ }
+ });
+ }
+ } else {
+ // Show
+ page.style.display = '';
+
+ // Page is ready
+ pageIsReady();
+ }
+
+ // Select toolbar item
+ if (page.options.toolbarItem) {
+ obj.toolbar.selectItem(page.options.toolbarItem);
+ }
+
+ // Add history
+ if (! o || ! o.ignoreHistory) {
+ // Add history
+ window.history.pushState({ route: page.options.route }, page.options.title, page.options.route);
+ }
+ }
+
+ /**
+ * Get a page by route
+ */
+ component.get = function(route) {
+ if (component.container[route]) {
+ return component.container[route];
+ }
+ }
+
+ /**
+ * Destroy a page
+ */
+ component.destroy = function() {
+ // TODO: create a destroy method
+ }
+
+ /**
+ * Page container controller
+ */
+ component.container = {};
+
+ /**
+ * Pages DOM container
+ */
+ var pages = el.querySelector('.pages');
+ if (! pages) {
+ pages = document.createElement('div');
+ pages.className = 'pages';
+ // Append page container to the application
+ el.appendChild(pages);
+ }
+
+ return component;
+ }();
+
+ /**
+ * Panel methods
+ */
+ obj.panel = function() {
+ var panel = null;
+
+ var component = function(route, o) {
+ if (! panel) {
+ // Create element
+ panel = document.createElement('div');
+ panel.classList.add('panel');
+ panel.classList.add('panel-left');
+ panel.style.display = 'none';
+
+ // Bind to the app
+ el.appendChild(panel);
+ }
+
+ // Remote content
+ if (route) {
+ // URL
+ if (! o) {
+ o = {};
+ }
+ if (! o.url) {
+ o.url = obj.options.path + route + '.html';
+ }
+ // Route
+ o.route = route;
+ // Panel
+ panel.options = o;
+
+ // Request remote data
+ jSuites.ajax({
+ url: o.url,
+ method: 'GET',
+ dataType: 'html',
+ success: function(result) {
+ // Create page overwrite
+ var ret = null;
+ if (typeof(obj.options.oncreatepage) == 'function') {
+ ret = obj.options.oncreatepage(obj, panel, result);
+ }
+
+ // Ignore create page actions
+ if (ret !== false) {
+ // Open page
+ panel.innerHTML = result;
+ // Get javascript
+ parseScript(page);
+ }
+ }
+ });
+ } else {
+ component.show();
+ }
+ }
+
+ component.show = function() {
+ // Show panel
+ if (panel && panel.style.display == 'none') {
+ panel.style.display = '';
+ // Add animation
+ if (panel.classList.contains('panel-left')) {
+ jSuites.animation.slideLeft(panel, 1);
+ } else {
+ jSuites.animation.slideRight(panel, 1);
+ }
+ }
+ }
+
+ component.hide = function() {
+ if (panel && panel.style.display == '') {
+ // Animation
+ if (panel.classList.contains('panel-left')) {
+ jSuites.animation.slideLeft(panel, 0, function() {
+ panel.style.display = 'none';
+ });
+ } else {
+ jSuites.animation.slideRight(panel, 0, function() {
+ panel.animation.style.display = 'none';
+ });
+ }
+ }
+ }
+
+ component.get = function() {
+ return panel;
+ }
+
+ component.destroy = function() {
+ el.removeChild(panel);
+ panel = null;
+ }
+
+ return component;
+ }();
+
+ obj.actionsheet = function() {
+ // Actionsheet container
+ var actionsheet = el.querySelector('.actionsheet');
+ if (! actionsheet) {
+ var actionsheet = document.createElement('div');
+ actionsheet.className = 'jactionsheet';
+ actionsheet.style.display = 'none';
+
+ var actionContent = document.createElement('div');
+ actionContent.className = 'jactionsheet-content';
+ actionsheet.appendChild(actionContent);
+ // Append actionsheet container to the application
+ el.appendChild(actionsheet);
+ }
+
+ var component = function(options) {
+ if (options) {
+ obj.actionsheet.options = options;
+ }
+
+ // Reset container
+ actionContent.innerHTML = '';
+
+ // Create new elements
+ for (var i = 0; i < obj.actionsheet.options.length; i++) {
+ var actionGroup = document.createElement('div');
+ actionGroup.className = 'jactionsheet-group';
+
+ for (var j = 0; j < obj.actionsheet.options[i].length; j++) {
+ var v = obj.actionsheet.options[i][j];
+ var actionItem = document.createElement('div');
+ var actionInput = document.createElement('input');
+ actionInput.type = 'button';
+ actionInput.value = v.title;
+ if (v.className) {
+ actionInput.className = v.className;
+ }
+ if (v.onclick) {
+ actionInput.event = v.onclick;
+ actionInput.onclick = function() {
+ this.event(obj, component, this);
+ }
+ }
+ if (v.action == 'cancel') {
+ actionInput.style.color = 'red';
+ }
+ actionItem.appendChild(actionInput);
+ actionGroup.appendChild(actionItem);
+ }
+
+ actionContent.appendChild(actionGroup);
+ }
+
+ // Show
+ actionsheet.style.display = '';
+
+ // Animation
+ jSuites.animation.slideBottom(actionContent, true);
+ }
+
+ component.close = function() {
+ if (actionsheet.style.display != 'none') {
+ // Remove any existing actionsheet
+ jSuites.animation.slideBottom(actionContent, false, function() {
+ actionsheet.style.display = 'none';
+ });
+ }
+ }
+
+ component.get = function() {
+ return actionsheet;
+ }
+
+ return component;
+ }();
+
+ /*
+ * Parse javascript from an element
+ */
+ var parseScript = function(element) {
+ // Get javascript
+ var script = element.getElementsByTagName('script');
+ // Run possible inline scripts
+ for (var i = 0; i < script.length; i++) {
+ // Get type
+ var type = script[i].getAttribute('type');
+ if (! type || type == 'text/javascript') {
+ eval(script[i].innerHTML);
+ }
+ }
+ }
+
+ var controlSwipeLeft = function(e) {
+ var element = jSuites.findElement(e.target, 'option');
+
+ if (element && element.querySelector('.option-actions')) {
+ element.scrollTo({
+ left: 100,
+ behavior: 'smooth'
+ });
+ } else {
+ obj.panel.hide();
+ }
+ }
+
+ var controlSwipeRight = function(e) {
+ var element = jSuites.findElement(e.target, 'option');
+ if (element && element.querySelector('.option-actions')) {
+ element.scrollTo({
+ left: 0,
+ behavior: 'smooth'
+ });
+ } else {
+ obj.panel.show();
+ }
+ }
+
+ var actionElement = null;
+
+ var actionDown = function(e) {
+ // Grouped options
+ if (e.target.classList.contains('option-title')) {
+ if (e.target.classList.contains('selected')) {
+ e.target.classList.remove('selected');
+ } else {
+ e.target.classList.add('selected');
+ }
+ }
+
+ // App links
+ actionElement = jSuites.findElement(e.target, function(e) {
+ return e.tagName == 'A' && e.getAttribute('href') ? e : false;
+ });
+
+ if (actionElement) {
+ var link = actionElement.getAttribute('href');
+ if (link == '#back') {
+ window.history.back();
+ } else if (link == '#panel') {
+ obj.panel();
+ } else {
+ if (actionElement.classList.contains('link')) {
+ actionElement = null;
+ } else {
+ obj.pages(link);
+ }
+ }
+ }
+ }
+
+ var actionUp = function(e) {
+ obj.actionsheet.close();
+
+ if (actionElement) {
+ e.preventDefault();
+ actionElement = null;
+ }
+ }
+
+ el.addEventListener('swipeleft', controlSwipeLeft);
+ el.addEventListener('swiperight', controlSwipeRight);
+
+ if ('ontouchstart' in document.documentElement === true) {
+ document.addEventListener('touchstart', actionDown);
+ document.addEventListener('touchend', actionUp);
+ } else {
+ document.addEventListener('mousedown', actionDown);
+ document.addEventListener('mouseup', actionUp);
+ }
+
+ window.onpopstate = function(e) {
+ if (e.state && e.state.route) {
+ if (obj.pages.get(e.state.route)) {
+ obj.pages(e.state.route, { ignoreHistory: true });
+ }
+ }
+ }
+
+ if (obj.options.toolbar) {
+ obj.setToolbar();
+ }
+
+ el.app = obj;
+
+ return obj;
+});
+
+jSuites.dialog = (function() {
+ var obj = {};
+ obj.options = {};
+
+ var dialog = null;
+ var dialogTitle = null;
+ var dialogHeader = null;
+ var dialogMessage = null;
+ var dialogFooter = null;
+ var dialogContainer = null;
+ var dialogConfirm = null;
+ var dialogConfirmButton = null;
+ var dialogCancel = null;
+ var dialogCancelButton = null;
+
+ obj.open = function(options) {
+ if (! jSuites.dialog.hasEvents) {
+ obj.init();
+
+ jSuites.dialog.hasEvents = true;
+ }
+ obj.options = options;
+
+ if (obj.options.title) {
+ dialogTitle.innerHTML = obj.options.title;
+ }
+
+ if (obj.options.message) {
+ dialogMessage.innerHTML = obj.options.message;
+ }
+
+ if (! obj.options.confirmLabel) {
+ obj.options.confirmLabel = 'OK';
+ }
+ dialogConfirmButton.value = obj.options.confirmLabel;
+
+ if (! obj.options.cancelLabel) {
+ obj.options.cancelLabel = 'Cancel';
+ }
+ dialogCancelButton.value = obj.options.cancelLabel;
+
+ if (obj.options.type == 'confirm') {
+ dialogCancelButton.parentNode.style.display = '';
+ } else {
+ dialogCancelButton.parentNode.style.display = 'none';
+ }
+
+ // Append element to the app
+ dialog.style.opacity = 100;
+
+ // Append to the page
+ if (jSuites.el) {
+ jSuites.el.appendChild(dialog);
+ } else {
+ document.body.appendChild(dialog);
+ }
+
+ // Focus
+ dialog.focus();
+
+ // Show
+ setTimeout(function() {
+ dialogContainer.style.opacity = 100;
+ }, 0);
+ }
+
+ obj.close = function() {
+ dialog.style.opacity = 0;
+ dialogContainer.style.opacity = 0;
+ setTimeout(function() {
+ dialog.remove();
+ }, 100);
+ }
+
+ obj.init = function() {
+ dialog = document.createElement('div');
+ dialog.setAttribute('tabindex', '901');
+ dialog.className = 'jdialog';
+ dialog.id = 'dialog';
+
+ dialogHeader = document.createElement('div');
+ dialogHeader.className = 'jdialog-header';
+
+ dialogTitle = document.createElement('div');
+ dialogTitle.className = 'jdialog-title';
+ dialogHeader.appendChild(dialogTitle);
+
+ dialogMessage = document.createElement('div');
+ dialogMessage.className = 'jdialog-message';
+ dialogHeader.appendChild(dialogMessage);
+
+ dialogFooter = document.createElement('div');
+ dialogFooter.className = 'jdialog-footer';
+
+ dialogContainer = document.createElement('div');
+ dialogContainer.className = 'jdialog-container';
+ dialogContainer.appendChild(dialogHeader);
+ dialogContainer.appendChild(dialogFooter);
+
+ // Confirm
+ dialogConfirm = document.createElement('div');
+ dialogConfirmButton = document.createElement('input');
+ dialogConfirmButton.value = obj.options.confirmLabel;
+ dialogConfirmButton.type = 'button';
+ dialogConfirmButton.onclick = function() {
+ if (typeof(obj.options.onconfirm) == 'function') {
+ obj.options.onconfirm();
+ }
+ obj.close();
+ };
+ dialogConfirm.appendChild(dialogConfirmButton);
+ dialogFooter.appendChild(dialogConfirm);
+
+ // Cancel
+ dialogCancel = document.createElement('div');
+ dialogCancelButton = document.createElement('input');
+ dialogCancelButton.value = obj.options.cancelLabel;
+ dialogCancelButton.type = 'button';
+ dialogCancelButton.onclick = function() {
+ if (typeof(obj.options.oncancel) == 'function') {
+ obj.options.oncancel();
+ }
+ obj.close();
+ }
+ dialogCancel.appendChild(dialogCancelButton);
+ dialogFooter.appendChild(dialogCancel);
+
+ // Dialog
+ dialog.appendChild(dialogContainer);
+
+ document.addEventListener('keydown', function(e) {
+ if (e.which == 13) {
+ if (typeof(obj.options.onconfirm) == 'function') {
+ jSuites.dialog.options.onconfirm();
+ }
+ obj.close();
+ } else if (e.which == 27) {
+ obj.close();
+ }
+ });
+ }
+
+ return obj;
+})();
+
+jSuites.confirm = (function(message, onconfirm) {
+ if (jSuites.getWindowWidth() < 800) {
+ jSuites.dialog.open({
+ type: 'confirm',
+ message: message,
+ title: 'Confirmation',
+ onconfirm: onconfirm,
+ });
+ } else {
+ if (confirm(message)) {
+ onconfirm();
+ }
+ }
+});
+
+
+jSuites.refresh = (function(el, options) {
+ // Controls
+ var touchPosition = null;
+ var pushToRefresh = null;
+
+ // Page touch move
+ var pageTouchMove = function(e, page) {
+ if (typeof(page.options.onpush) == 'function') {
+ if (page.scrollTop < 5) {
+ if (! touchPosition) {
+ touchPosition = {};
+ touchPosition.x = e.touches[0].clientX;
+ touchPosition.y = e.touches[0].clientY;
+ }
+
+ var height = e.touches[0].clientY - touchPosition.y;
+ if (height > 70) {
+ if (! pushToRefresh.classList.contains('ready')) {
+ pushToRefresh.classList.add('ready');
+ }
+ } else {
+ if (pushToRefresh.classList.contains('ready')) {
+ pushToRefresh.classList.remove('ready');
+ }
+ pushToRefresh.style.height = height + 'px';
+
+ if (height > 20) {
+ if (! pushToRefresh.classList.contains('holding')) {
+ pushToRefresh.classList.add('holding');
+ page.insertBefore(pushToRefresh, page.firstChild);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Page touch end
+ var pageTouchEnd = function(e, page) {
+ if (typeof(page.options.onpush) == 'function') {
+ // Remove holding
+ pushToRefresh.classList.remove('holding');
+ // Refresh or not refresh
+ if (! pushToRefresh.classList.contains('ready')) {
+ // Reset and not refresh
+ pushToRefresh.style.height = '';
+ obj.hide();
+ } else {
+ pushToRefresh.classList.remove('ready');
+ // Loading indication
+ setTimeout(function() {
+ obj.hide();
+ }, 1000);
+
+ // Refresh
+ if (typeof(page.options.onpush) == 'function') {
+ page.options.onpush(page);
+ }
+ }
+ }
+ }
+
+ var obj = function(element, callback) {
+ if (! pushToRefresh) {
+ pushToRefresh = document.createElement('div');
+ pushToRefresh.className = 'jrefresh';
+ }
+
+ element.addEventListener('touchmove', function(e) {
+ pageTouchMove(e, element);
+ });
+ element.addEventListener('touchend', function(e) {
+ pageTouchEnd(e, element);
+ });
+ if (! element.options) {
+ element.options = {};
+ }
+ if (typeof(callback) == 'function') {
+ element.options.onpush = callback;
+ }
+ }
+
+ obj.hide = function() {
+ if (pushToRefresh.parentNode) {
+ pushToRefresh.parentNode.removeChild(pushToRefresh);
+ }
+ touchPosition = null;
+ }
+
+ return obj;
+})();
diff --git a/web-tools/web/_static/jsuites/jsuites.webcomponents.js b/web-tools/web/_static/jsuites/jsuites.webcomponents.js
new file mode 100644
index 0000000..de3b1b6
--- /dev/null
+++ b/web-tools/web/_static/jsuites/jsuites.webcomponents.js
@@ -0,0 +1,502 @@
+
+/**
+ * (c) jSuites Javascript Web Components (v3.2)
+ *
+ * Author: Paul Hodel <paul.hodel@gmail.com>
+ * Website: https://bossanova.uk/jsuites/
+ * Description: Create amazing web based applications.
+ *
+ * MIT License
+ *
+ */
+
+class JsuitesCalendar extends HTMLElement {
+ constructor() {
+ // always call super() first
+ super();
+ }
+
+ init(o) {
+ // Create element
+ this.input = document.createElement('input');
+ // Append to the DOM
+ o.appendChild(this.input);
+ // Place holder
+ var placeholder = o.getAttribute('placeholder');
+ // Place holder
+ var format = o.getAttribute('format');
+ // Place holder
+ var time = o.getAttribute('time');
+ // Initial value
+ var value = o.getAttribute('value');
+ if (value) {
+ this.input.value = value;
+ o.value = value;
+ }
+ // Component
+ jSuites.calendar(this.input, {
+ value: value ? value : null,
+ placeholder: placeholder ? placeholder : null,
+ format: format ? format : 'YYYY-MM-DD',
+ time: time ? true : false,
+ onchange: function(el, val) {
+ // Change value of the element
+ el.setAttribute('value', val);
+ o.setAttribute('value', val);
+ o.value = val;
+ // Basic HTML event
+ var s = o.getAttribute('onchange');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onchange");
+ el.parentNode.dispatchEvent(e);
+ },
+ onclose: function(el) {
+ // Basic HTML event
+ var s = o.getAttribute('onclose');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onclose");
+ el.parentNode.dispatchEvent(e);
+ }
+ });
+ }
+
+ connectedCallback() {
+ if (! this.input) {
+ this.init(this);
+ }
+ }
+
+ disconnectedCallback() {
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ }
+}
+
+window.customElements.define('jsuites-calendar', JsuitesCalendar);
+
+class JsuitesColor extends HTMLElement {
+ constructor() {
+ // always call super() first
+ super();
+ }
+
+ init(o) {
+ // Create element
+ this.input = document.createElement('input');
+ // Append to the DOM
+ o.appendChild(this.input);
+ // Place holder
+ var placeholder = o.getAttribute('placeholder');
+ // Initial value
+ var value = o.getAttribute('value');
+ if (value) {
+ o.value = value;
+ }
+ // Component
+ jSuites.color(this.input, {
+ value: value ? value : null,
+ placeholder: placeholder ? placeholder : null,
+ onchange: function(el, color) {
+ // Change value of the element
+ o.setAttribute('value', color);
+ o.value = color;
+ // Basic HTML event
+ var s = o.getAttribute('onchange');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onchange");
+ el.parentNode.dispatchEvent(e);
+ },
+ onclose: function(el) {
+ // Basic HTML event
+ var s = o.getAttribute('onclose');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onclose");
+ el.parentNode.dispatchEvent(e);
+ }
+ });
+ }
+
+ connectedCallback() {
+ if (! this.input) {
+ this.init(this);
+ }
+ }
+
+ disconnectedCallback() {
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ }
+}
+
+window.customElements.define('jsuites-color', JsuitesColor);
+
+class JsuitesContextmenu extends HTMLElement {
+ constructor() {
+ // always call super() first
+ super();
+ }
+
+ init(o) {
+ this.el = jSuites.contextmenu(o, {
+ items: null,
+ onclick: function(a) {
+ a.close();
+ }
+ });
+ }
+
+ connectedCallback() {
+ if (! this.el) {
+ this.init(this);
+ }
+ }
+
+ disconnectedCallback() {
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ }
+}
+
+window.customElements.define('jsuites-contextmenu', JsuitesContextmenu);
+
+class JsuitesEditor extends HTMLElement {
+ constructor() {
+ // always call super() first
+ super();
+ }
+
+ init(o) {
+ this.el = document.createElement('div');
+
+ // Options
+ var options = {};
+ // Initial values
+ var toolbar = o.getAttribute('toolbar');
+ if (toolbar) {
+ options.toolbar = toolbar;
+ }
+
+ // Events
+ options.onload = function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onload');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onload");
+ el.dispatchEvent(e);
+ }
+
+ options.onclick = function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onclick');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onclick");
+ el.dispatchEvent(e);
+ }
+
+ options.onfocus = function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onfocus');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onfocus");
+ el.dispatchEvent(e);
+ }
+
+ options.onblur = function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onblur');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onblur");
+ el.dispatchEvent(e);
+ }
+
+ options.onclose = function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onclose');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onclose");
+ el.dispatchEvent(e);
+ }
+
+ setTimeout(function() {
+ jSuites.editor(o, options);
+ }, 0);
+ }
+
+ connectedCallback() {
+ if (! this.el) {
+ this.init(this);
+ }
+ }
+
+ disconnectedCallback() {
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ }
+}
+
+window.customElements.define('jsuites-editor', JsuitesEditor);
+
+class JsuitesModal extends HTMLElement {
+ constructor() {
+ // always call super() first
+ super();
+ }
+
+ init(o) {
+ this.el = document.createElement('div');
+
+ // Options
+ var options = {};
+ // Initial values
+ var title = o.getAttribute('title');
+ if (title) {
+ options.title = title;
+ }
+ var width = o.getAttribute('width');
+ if (width) {
+ options.width = parseInt(width) + 'px';
+ }
+ var height = o.getAttribute('height');
+ if (height) {
+ options.height = parseInt(height) + 'px';
+ }
+ var closed = o.getAttribute('closed');
+ if (closed) {
+ options.closed = closed;
+ }
+
+ // Events
+ options.onopen = function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onopen');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onopen");
+ el.dispatchEvent(e);
+ }
+
+ options.onclose = function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onclose');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onclose");
+ el.dispatchEvent(e);
+ }
+
+ setTimeout(function() {
+ jSuites.modal(o, options);
+ }, 0);
+ }
+
+ connectedCallback() {
+ if (! this.el) {
+ this.init(this);
+ }
+ }
+
+ disconnectedCallback() {
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ }
+}
+
+window.customElements.define('jsuites-modal', JsuitesModal);
+
+class JsuitesRating extends HTMLElement {
+ constructor() {
+ // always call super() first
+ super();
+ }
+
+ init(o) {
+ // Initial values
+ var value = o.getAttribute('value') ? o.getAttribute('value') : null;
+ var number = o.getAttribute('number') ? o.getAttribute('number') : 5;
+ var tooltip = o.getAttribute('tooltip') ? o.getAttribute('tooltip') : null;
+ if (tooltip) {
+ tooltip = tooltip.split(',');
+ } else {
+ tooltip = [ 'Very bad', 'Bad', 'Average', 'Good', 'Very good' ];
+ }
+
+ jSuites.rating(o, {
+ value: value,
+ number: number,
+ tooltip: tooltip,
+ onchange: function(el, v) {
+ // Change value of the element
+ o.setAttribute('value', v);
+ o.value = v;
+ // Basic HTML event
+ var s = o.getAttribute('onchange');
+ if (s) {
+ eval(s);
+ }
+ // Trigger event
+ var e = new CustomEvent("onchange");
+ el.dispatchEvent(e);
+ }
+ });
+
+ // Initiated
+ this.initiated = true;
+ }
+
+ connectedCallback() {
+ if (! this.initiated) {
+ this.init(this);
+ }
+ }
+
+ disconnectedCallback() {
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ }
+}
+
+window.customElements.define('jsuites-rating', JsuitesRating);
+
+class JsuitesTags extends HTMLElement {
+ constructor() {
+ // always call super() first
+ super();
+ }
+
+ init(o) {
+ // Initial values
+ var value = o.getAttribute('value') ? o.getAttribute('value') : null;
+ var limit = o.getAttribute('limit') ? o.getAttribute('limit') : null;
+ var search = o.getAttribute('search') ? o.getAttribute('search') : null;
+ var placeholder = o.getAttribute('placeholder') ? o.getAttribute('placeholder') : null;
+
+ jSuites.tags(o, {
+ value: value,
+ limit: limit,
+ search: search,
+ placeholder: placeholder,
+ onbeforechange: function(el, obj, v) {
+ // Basic HTML event
+ var s = o.getAttribute('onbeforechange');
+ if (s) {
+ var newValue = eval(s);
+ if (newValue != null) {
+ return newValue;
+ }
+ } else {
+ // Trigger event
+ var e = new CustomEvent("onbeforechange");
+ el.dispatchEvent(e);
+ }
+ },
+ onchange: function(el, obj, v) {
+ var newValue = obj.getValue();
+ // Change value of the element
+ o.setAttribute('value', newValue);
+ o.value = newValue;
+ // Basic HTML event
+ var s = o.getAttribute('onchange');
+ if (s) {
+ eval(s);
+ } else {
+ // Trigger event
+ var e = new CustomEvent("onchange");
+ el.dispatchEvent(e);
+ }
+ },
+ onfocus: function(el, obj, v) {
+ // Basic HTML event
+ var s = o.getAttribute('onfocus');
+ if (s) {
+ eval(s);
+ } else {
+ // Trigger event
+ var e = new CustomEvent("onfocus");
+ el.dispatchEvent(e);
+ }
+ },
+ onblur: function(el, obj, v) {
+ var newValue = obj.getValue();
+ // Change value of the element
+ o.setAttribute('value', newValue);
+ o.value = newValue;
+ // Basic HTML event
+ var s = o.getAttribute('onblur');
+ if (s) {
+ eval(s);
+ } else {
+ // Trigger event
+ var e = new CustomEvent("onblur");
+ el.dispatchEvent(e);
+ }
+ },
+ onload: function(el, obj) {
+ // Basic HTML event
+ var s = o.getAttribute('onload');
+ if (s) {
+ eval(s);
+ } else {
+ // Trigger event
+ var e = new CustomEvent("onload");
+ el.dispatchEvent(e);
+ }
+ }
+ });
+
+ // Initiated
+ this.initiated = true;
+ }
+
+ connectedCallback() {
+ if (! this.initiated) {
+ this.init(this);
+ }
+ }
+
+ disconnectedCallback() {
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ }
+}
+
+window.customElements.define('jsuites-tags', JsuitesTags);
+
+