From f73f2356820468344757dbb9d7f3ec73ece7bf66 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 13 Feb 2023 20:43:51 +0100 Subject: Updating. Signed-off-by: Daniel Baumann --- web/_static/jsuites/jsuites.basic.css | 2155 +++++ web/_static/jsuites/jsuites.basic.js | 9416 ++++++++++++++++++++ web/_static/jsuites/jsuites.css | 2724 ++++++ web/_static/jsuites/jsuites.js | 11452 +++++++++++++++++++++++++ web/_static/jsuites/jsuites.layout.css | 2306 +++++ web/_static/jsuites/jsuites.layout.js | 3456 ++++++++ web/_static/jsuites/jsuites.mobile.css | 1012 +++ web/_static/jsuites/jsuites.mobile.js | 1016 +++ web/_static/jsuites/jsuites.webcomponents.js | 501 ++ 9 files changed, 34038 insertions(+) create mode 100644 web/_static/jsuites/jsuites.basic.css create mode 100644 web/_static/jsuites/jsuites.basic.js create mode 100644 web/_static/jsuites/jsuites.css create mode 100644 web/_static/jsuites/jsuites.js create mode 100644 web/_static/jsuites/jsuites.layout.css create mode 100644 web/_static/jsuites/jsuites.layout.js create mode 100644 web/_static/jsuites/jsuites.mobile.css create mode 100644 web/_static/jsuites/jsuites.mobile.js create mode 100644 web/_static/jsuites/jsuites.webcomponents.js (limited to 'web/_static/jsuites') diff --git a/web/_static/jsuites/jsuites.basic.css b/web/_static/jsuites/jsuites.basic.css new file mode 100644 index 0000000..71e1a8d --- /dev/null +++ b/web/_static/jsuites/jsuites.basic.css @@ -0,0 +1,2155 @@ + +/** + * (c) jSuites Javascript Web Components + * + * Website: https://jsuites.net + * 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 { + position: relative; + box-sizing: border-box; + background-size: initial; + height: 33px; + min-height: initial; + padding: 6px; + padding-right: 30px; +} + +.jupload.input:before { + content: "save"; + font-size: 18px; + font-family: "Material Icons"; + color: #000; + position: absolute; + right: 5px; +} + +.jupload img { + width: 100%; +} + +.jupload.input img { + width: initial; + max-width: 100%; + height: 100%; +} + +.jupload[data-multiple] { + padding: 10px; +} + +.jupload[data-multiple] img { + height: 70px; + width: 100px; + object-fit: cover; + margin-right: 5px; + margin-bottom: 5px; +} + +.jupload { + border: 1px dotted #eee; + cursor: pointer; + box-sizing: border-box; + width: 100%; + height: 100%; + min-height: 180px; +} + +.jupload:not(.input):before { + content: "\e2c3"; + font-family: "Material Icons"; + font-size: 90px; + color: #eee; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.jupload-item { + padding-right: 22px; + border-radius: 1px; + display: inline-block; + position: relative; +} + +.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 { + position: relative; + animation: slide-left-in 0.4s forwards; +} + +.slide-left-out { + position: relative; + animation: slide-left-out 0.4s forwards; +} + +.slide-right-in { + position: relative; + animation: slide-right-in 0.4s forwards; +} + +.slide-right-out { + position: relative; + animation: slide-right-out 0.4s forwards; +} + +.slide-top-in { + position: relative; + animation: slide-top-in 0.4s forwards; +} + +.slide-top-out { + position: relative; + animation: slide-top-out 0.2s forwards; +} + +.slide-bottom-in { + position: relative; + animation: slide-bottom-in 0.4s forwards; +} + +.slide-bottom-out { + position: relative; + animation: slide-bottom-out 0.1s forwards; +} + +.spin { + animation: spin 2s infinite linear; +} + +/** 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% { left: -100%; } + 100% { left: 0%; } +} + +@-webkit-keyframes slide-left-in { + 0% { left: -100%; } + 100% { left: 0%; } +} + +@keyframes slide-left-out { + 0% { left: 0%; } + 100% { left: -100%; } +} + +@-webkit-keyframes slide-left-out { + 0% { left: 0%; } + 100% { left: -100%; } +} + +/** Keyframes Right to Left **/ +@keyframes slide-right-in { + 0% { left: 100%; } + 100% { left: 0%; } +} + +@-webkit-keyframes slide-right-in +{ + 0% { left: 100%; } + 100% { left: 0%; } +} + +@keyframes slide-right-out { + 0% { left: 0%; } + 100% { left: 100%; } +} + +@-webkit-keyframes slide-right-out { + 0% { left: 0%; } + 100% { left: 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(359deg); + } +} + +@keyframes spin { + from { + transform:rotate(0deg); + } + to { + transform:rotate(359deg); + } +} + +.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; + min-width: 260px; +} + +.jcolor-controls { + display: flex; + padding: 10px; + border-bottom: 1px solid #eee; + margin-bottom: 5px; +} + +.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: collapse; + box-sizing: border-box; +} + +.jcolor-focus { + display:block; +} + +.jcolor table { + width:100%; + height:100%; + min-height: 160px; +} + +.jcolor td { + padding: 7px; +} + +.jcolor-selected { + 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: 290px; + 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 */ +} + +.jcolor-content .jtabs-content { + padding: 7px; +} + +.jcolor-grid tr:first-child > td:first-child { + border-top-left-radius: 3px; +} + +.jcolor-grid tr:first-child > td:last-child { + border-top-right-radius: 3px; +} + +.jcolor-grid tr:last-child > td:first-child { + border-bottom-left-radius: 3px; +} + +.jcolor-grid tr:last-child > td:last-child { + border-bottom-right-radius: 3px; +} + +.jcolor-hsl { + box-sizing: border-box; +} + +.jcolor-hsl > div { + height: 100%; + position: relative; +} + +.jcolor-hsl canvas { + display: block; + border-radius: 4px; + -webkit-user-drag: none; +} + +.jcolor-point { + height: 5px; + width: 5px; + background-color: #000; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 50%; +} + +.jcolor-sliders { + padding: 10px 20px 10px 10px; +} + +.jcolor-sliders input { + -webkit-appearance: none; + + height: 12px; + width: 80%; + + background: #d3d3d3; + opacity: 1; + + border-radius: 30px; + outline: none; +} + +.jcolor-sliders-input-subcontainer { + display: flex; + justify-content: space-between; + align-items: center; +} + +.jcolor-sliders-input-container { + margin-top: 4px; + line-height: 0.8em; + text-align: left; +} + +.jcolor-sliders-input-container > label { + font-size: 10px; + text-transform: uppercase; + color: #bbbbbd; +} + +.jcolor-sliders-input-subcontainer > input { + border: 0px; + padding: 1px; +} + +.jcolor-sliders-input-container input::-webkit-slider-thumb { + -webkit-appearance: none; + height: 12px; + width: 12px; + border-radius: 50%; + background: #000; + border: 2px solid #fff; + cursor: pointer; +} + +.jcolor-sliders-input-container input::-moz-range-thumb { + -webkit-appearance: none; + height: 12px; + width: 12px; + border-radius: 50%; + background: #000; + border: 2px solid #fff; + cursor: pointer; +} + +.jcolor-sliders-final-color { + padding: 6px; + user-select: all; + margin-top: 10px; + text-align: center; +} + +.jcolor-sliders-final-color > div:nth-child(2) { + width: 71px; + text-transform: uppercase; +} + +.jcolor .jtabs .jtabs-headers-container .jtabs-controls { + display: none !important; +} + +.jcolor .jtabs .jtabs-headers-container { + display: flex !important; + justify-content: center; + padding: 4px; +} + +.jcolor .jtabs-headers > div:not(.jtabs-border) { + padding: 2px !important; + padding-left: 15px !important; + padding-right: 15px !important; + font-size: 0.8em; +} + +.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' !important; + 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; +} + +@media only screen and (max-width: 420px) { + .jcontextmenu { + top: initial !important; + left: 0px !important; + bottom: 0px !important; + width: 100vw; + height: 260px; + overflow: scroll; + animation: slide-bottom-in 0.4s forwards; + } + .jcontextmenu div { + width: 100%; + text-align: center; + border-bottom: 1px solid #ccc; + padding: 15px; + } + .jcontextmenu > div::before { + display: none; + } + .jcontextmenu a { + font-size: 1.4em; + text-transform: uppercase; + } + .jcontextmenu span { + display: none; + } + .jcontextmenu span { + display: none; + } + .jcontextmenu hr { + display: none; + } +} + +.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[disabled] { + opacity: 0.5; + pointer-events: 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-icon +{ + margin-right:10px; + font-size: 30px; + margin-left: -5px; +} + +.jdropdown-icon-small +{ + font-size: 24px; + margin-left: 0px; +} + +.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; + text-align: left; +} + +.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 !important; + left:0px !important; + width:100% !important; + height:100% !important; + background-color:#fafafa; + padding:0px; + z-index:9001; + overflow-y:scroll; + will-change: scroll-position; + -webkit-overflow-scrolling: touch; +} + +.jdropdown-searchbar.jdropdown-focus .jdropdown-container-header +{ + position: fixed; + top: 0px; + left: 0px; + z-index: 9002; + padding:10px; + background-color:#fff; + box-shadow: 0 1px 2px rgba(0,0,0,.1); + max-height: 24px; + width: 100%; +} + +.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 +{ + margin-top: 40px; + 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-width : 800px) +{ + .jdropdown-list { + width:100% !important; + border:0px; + padding:0px; + } + + .jdropdown-list .jdropdown-container { + min-width:100%; + } + + .jdropdown-searchbar.jdropdown-focus .jdropdown-description { + text-transform: uppercase; + } +} + +.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; +} + +.jdropdown-item[data-disabled] { + opacity: 0.5; + pointer-events: none; +} + +.jeditor-container { + border:1px solid #ccc; + box-sizing: border-box; +} + +.jeditor-dragging { + border:1px dashed #000; +} + +.jeditor-container.jeditor-padding { + padding:10px; +} + +.jeditor { + outline:none; + word-break: break-word; + +} + +.jeditor[data-placeholder]:empty:before { + content: attr(data-placeholder); + color: lightgray; +} + +.jeditor-container.jeditor-padding .jeditor { + min-height:100px; + margin-bottom:10px; + padding:10px; +} + +/** Snippet **/ + +.jsnippet { + margin-top:15px; + cursor:pointer; + border: 1px solid #ccc; + 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: 'close'; + font-family: 'Material icons'; + font-size: 24px; + width: 24px; + height: 24px; + line-height: 24px; + cursor: pointer; + text-shadow: 0px 0px 2px #fff; + position: absolute; + top: 12px; + right: 12px; +} + +.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; +} + +.jeditor img.resizing { + -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; + outline: #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; +} + +.jeditor-toolbar { + width: fit-content; + max-width: 100%; + box-sizing: border-box; +} + +.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; + bottom: 0px; +} + +.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; + + 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-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-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; + margin: 0px; + width: initial; + } + .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; + position: relative; +} + +.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; + top: 0; + 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; + max-height: 200px; + scrollbar-width: thin; + scrollbar-color: #333 transparent; +} + +.jpicker-content::-webkit-scrollbar { + width: 8px; +} + +.jpicker-content::-webkit-scrollbar-track { + background: #eee; +} + +.jpicker-content::-webkit-scrollbar-thumb { + background: #888; +} + +.jpicker-content > div { + padding: 6px; + padding-left: 15px; + padding-right: 15px; +} + +.jpicker-focus > .jpicker-content { + display: block; +} + +.jpicker-content > div:hover { + background-color:#efefef; +} + +.jpicker-content > div:empty { + opacity: 0; +} + +.jpicker-header > i, .jpicker-header > div { + display: block; +} + +.jpicker-focus > .jpicker-content.jpicker-columns { + display: flex !important ; + justify-content: center; + flex-wrap: wrap; +} + +.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; + background-color: #f1f1f1; + cursor: pointer; + white-space: nowrap; + text-align: center; +} + +.jtabs .jtabs-headers > div.jtabs-selected { + background-color: #e8e8e8; + color: #000; +} + +.jtabs .jtabs-headers > div > div { + color: #555; + width: 100%; + overflow: hidden; +} + +.jtabs .jtabs-headers i { + display: block; + margin: auto; +} + +.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"); +} + +/** Modern skin **/ + +.jtabs.jtabs-modern .jtabs-headers > div:not(.jtabs-border) { + padding: 4px; + padding-left: 10px; + padding-right: 10px; + background-color: #fff; +} + +.jtabs.jtabs-modern .jtabs-headers > .jtabs-selected { + color: #000; +} + +.jtabs.jtabs-modern .jtabs-headers > .jtabs-selected .material-icons { + color: #000; +} + +.jtabs.jtabs-modern .jtabs-headers { + background: #EEEEEF !important; + padding: 2px; + border-radius: 4px; +} + +.jtabs.jtabs-modern .jtabs-headers .jtabs-border { + border-color: #EEEEEF !important; +} + +.jtabs.jtabs-modern .jtabs-border { + background-color: rgba(194, 197, 188, 0.884); +} + +.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; + font-size: 13px; +} + +.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: 18px; + padding: 0px; + margin-left: 4px; + margin-right: 4px; + background-color: #ddd; +} + +.jtoolbar .jtoolbar-label { + padding-left: 8px; + padding-right: 8px; +} + + + +.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: 8px; + background-position: top 50% right 0px; + display: flex; + align-items: center; +} + +.jtoolbar .jpicker-content > div { + padding: 6px; +} + +.jtoolbar-active { + background-color:#eee; +} + +.jtoolbar .fa { + width: 18px; + height: 18px; + display: block; + line-height: 18px; + font-size: 14px; +} + +.jtoolbar .material-icons { + font-size: 18px; + width: 24px; + height: 24px; + display: block; + line-height: 24px; + transform: rotate(0.03deg); + text-align: center; +} + +.jtoolbar .jtoolbar-arrow { + background-repeat: no-repeat; + background-position: center; + 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 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z'/%3E%3C/svg%3E"); + width: 24px; + height: 16px; + margin-left: 4px; + border-left: 1px solid #f2f2f2; +} + +.jtoolbar-floating { + 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; +} + +.jtoolbar-floating .jtoolbar-divisor { + display: none; +} + +.jtoolbar-floating > div { + display: block; +} + +.jtoolbar-arrow-selected .jtoolbar-floating { + display: flex; + flex-wrap: wrap; +} + + diff --git a/web/_static/jsuites/jsuites.basic.js b/web/_static/jsuites/jsuites.basic.js new file mode 100644 index 0000000..bcc33d7 --- /dev/null +++ b/web/_static/jsuites/jsuites.basic.js @@ -0,0 +1,9416 @@ +/** + * (c) jSuites Javascript Web Components + * + * Website: https://jsuites.net + * 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 = {} + var version = '4.9.11'; + + var find = function(DOMElement, component) { + if (DOMElement[component.type] && DOMElement[component.type] == component) { + return true; + } + if (DOMElement.parentNode) { + return find(DOMElement.parentNode, component); + } + return false; + } + + var isOpened = function(e) { + if (jSuites.current.length > 0) { + for (var i = 0; i < jSuites.current.length; i++) { + if (jSuites.current[i] && ! find(e.target, jSuites.current[i])) { + jSuites.current[i].close(); + } + } + } + } + + obj.init = function() { + document.addEventListener("click", isOpened); + + obj.version = version; + } + + obj.tracking = function(component, state) { + if (state == true) { + jSuites.current = jSuites.current.filter(function(v) { + return v !== null; + }); + + // Start after all events + setTimeout(function() { + jSuites.current.push(component); + }, 0); + + } else { + var index = jSuites.current.indexOf(component); + if (index >= 0) { + jSuites.current[index] = null; + } + } + } + + /** + * Get or set a property from a JSON from a string. + */ + obj.path = function(str, val) { + str = str.split('.'); + if (str.length) { + var o = this; + var p = null; + while (str.length > 1) { + // Get the property + p = str.shift(); + // Check if the property exists + if (o.hasOwnProperty(p)) { + o = o[p]; + } else { + // Property does not exists + if (val === undefined) { + return undefined; + } else { + // Create the property + o[p] = {}; + // Next property + o = o[p]; + } + } + } + // Get the property + p = str.shift(); + // Set or get the value + if (val !== undefined) { + o[p] = val; + // Success + return true; + } else { + // Return the value + return o[p]; + } + } + // Something went wrong + return false; + } + + // Update dictionary + obj.setDictionary = function(d) { + obj.dictionary = d; + + // Translations + var t = null; + for (var i = 0; i < jSuites.calendar.weekdays.length; i++) { + t = jSuites.translate(jSuites.calendar.weekdays[i]); + if (jSuites.calendar.weekdays[i]) { + jSuites.calendar.weekdays[i] = t; + jSuites.calendar.weekdaysShort[i] = t.substr(0,3); + } + } + for (var i = 0; i < jSuites.calendar.months.length; i++) { + t = jSuites.translate(jSuites.calendar.months[i]); + if (t) { + jSuites.calendar.months[i] = t; + jSuites.calendar.monthsShort[i] = t.substr(0,3); + } + } + } + + // Dictionary + obj.dictionary = {}; + + // Translate + obj.translate = function(t) { + return obj.dictionary[t] || t; + } + + // Array of opened components + obj.current = []; + + return obj; +}(); + +/** + * Global jsuites event + */ +if (typeof(document) !== "undefined") { + jSuites.init(); +} + +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'); + } else if (options.dataType == 'blob') { + httpRequest.responseType = "blob"; + } else if (options.dataType == 'html') { + httpRequest.setRequestHeader('Content-Type', 'text/html'); + } + } + + // 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 { + if (options.dataType == 'blob') { + var result = httpRequest.response; + } 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, httpRequest.status); + } + } + + // 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); + // Deprected: Last one? + if (! jSuites.ajax.requests.length) { + // Object event + if (options.complete && typeof(options.complete) == 'function') { + options.complete(result); + } + } + // Group requests + if (options.group) { + if (jSuites.ajax.oncomplete && typeof(jSuites.ajax.oncomplete[options.group]) == 'function') { + if (! jSuites.ajax.pending(options.group)) { + jSuites.ajax.oncomplete[options.group](); + jSuites.ajax.oncomplete[options.group] = null; + } + } + } + // Multiple requests controller + 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); + } + } + } + } + } + + // Keep the options + httpRequest.options = options; + // 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.pending = function(group) { + var n = 0; + var o = jSuites.ajax.requests; + if (o && o.length) { + for (var i = 0; i < o.length; i++) { + if (! group || group == o[i].options.group) { + n++ + } + } + } + return n; +} + +jSuites.ajax.oncomplete = {}; +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.style.display = ''; + 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.style.display = 'none'; + element.classList.remove('fade-out'); + if (typeof(done) == 'function') { + done(); + } + }, 1000); +} + +jSuites.calendar = (function(el, options) { + // Already created, update options + if (el.calendar) { + return el.calendar.setOptions(options, true); + } + + // New instance + var obj = { type:'calendar' }; + obj.options = {}; + + // Date + obj.date = null; + + /** + * Update options + */ + obj.setOptions = function(options, reset) { + // 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: jSuites.calendar.monthsShort, + monthsFull: jSuites.calendar.months, + weekdays: jSuites.calendar.weekdays, + weekdays_short: jSuites.calendar.weekdays, + textDone: jSuites.translate('Done'), + textReset: jSuites.translate('Reset'), + textUpdate: jSuites.translate('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, + // Data type + dataType: null, + } + + for (var i = 0; i < defaults.weekdays_short.length; i++) { + defaults.weekdays_short[i] = defaults.weekdays_short[i].substr(0,1); + } + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Reset button + if (obj.options.resetButton == false) { + calendarReset.style.display = 'none'; + } else { + calendarReset.style.display = ''; + } + + // Readonly + if (obj.options.readonly) { + el.setAttribute('readonly', 'readonly'); + } else { + el.removeAttribute('readonly'); + } + + // Placeholder + if (obj.options.placeholder) { + el.setAttribute('placeholder', obj.options.placeholder); + } else { + el.removeAttribute('placeholder'); + } + + if (jSuites.isNumeric(obj.options.value) && obj.options.value > 0) { + obj.options.value = jSuites.calendar.numToDate(obj.options.value); + // Data type numberic + obj.options.dataType = 'numeric'; + } + + // Texts + calendarReset.innerHTML = obj.options.textReset; + calendarConfirm.innerHTML = obj.options.textDone; + calendarControlsUpdateButton.innerHTML = obj.options.textUpdate; + + // Define mask + el.setAttribute('data-mask', obj.options.format.toLowerCase()); + + // Value + if (! obj.options.value && obj.options.today) { + var value = jSuites.calendar.now(); + } else { + var value = obj.options.value; + } + + // Set internal date + if (value) { + // Force the update + obj.options.value = null; + // New value + obj.setValue(value); + } + + return obj; + } + + /** + * Open the calendar + */ + obj.open = function (value) { + if (! calendar.classList.contains('jcalendar-focus')) { + if (! calendar.classList.contains('jcalendar-inline')) { + // Current + jSuites.calendar.current = obj; + // Start tracking + jSuites.tracking(obj, true); + // Create the days + obj.getDays(); + // Render months + 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]; + } + + // Show calendar + calendar.classList.add('jcalendar-focus'); + + // Get the position of the corner helper + if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen) { + calendar.classList.add('jcalendar-fullsize'); + // Animation + jSuites.animation.slideBottom(calendarContent, 1); + } else { + calendar.classList.remove('jcalendar-fullsize'); + + 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) { + var d = -1 * (rect.height + rectContent.height + 2); + if (d + rect.top < 0) { + d = -1 * (rect.top + rect.height); + } + calendarContainer.style.top = d + 'px'; + } else { + calendarContainer.style.top = 2 + 'px'; + } + + if (window.innerWidth < rect.left + rectContent.width) { + var d = window.innerWidth - (rect.left + rectContent.width + 20); + calendarContainer.style.left = d + 'px'; + } else { + calendarContainer.style.left = '0px'; + } + } + } + + // Events + if (typeof(obj.options.onopen) == 'function') { + obj.options.onopen(el); + } + } + } + } + + obj.close = function (ignoreEvents, update) { + if (calendar.classList.contains('jcalendar-focus')) { + 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'); + // Stop tracking + jSuites.tracking(obj, false); + // Current + jSuites.calendar.current = null; + } + + 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(); + } + } + + /** + * Set today + */ + obj.setToday = function() { + // Today + var value = new Date().toISOString().substr(0, 10); + // Change value + obj.setValue(value); + // Value + return value; + } + + obj.setValue = function(val) { + if (! val) { + val = '' + val; + } + // Values + var newValue = val; + var oldValue = obj.options.value; + + if (oldValue != newValue) { + // Set label + if (! newValue) { + obj.date = null; + var val = ''; + } else { + 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; + + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, newValue, oldValue); + } + + // Lemonade JS + if (el.value != val) { + el.value = val; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + 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, v) { + if (element.classList.contains('jcalendar-disabled')) { + // Do nothing + } else { + var elements = calendar.querySelector('.jcalendar-selected'); + if (elements) { + elements.classList.remove('jcalendar-selected'); + } + element.classList.add('jcalendar-selected'); + + if (element.classList.contains('jcalendar-set-month')) { + obj.date[1] = v; + } else { + obj.date[2] = element.innerText; + } + + if (! obj.options.time) { + obj.close(); + } else { + obj.date[3] = calendarSelectHour.value; + obj.date[4] = calendarSelectMin.value; + } + } + + // Update + updateActions(); + } + + /** + * Set to blank + */ + obj.reset = function() { + // Close calendar + obj.setValue(''); + obj.date = null; + 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; + + // Value + var value = obj.options.value; + + // Current date + var date = new Date(); + var currentYear = parseInt(date.getFullYear()); + var currentMonth = parseInt(date.getMonth()) + 1; + var selectedYear = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : currentYear; + var selectedMonth = obj.date && jSuites.isNumeric(obj.date[1]) ? obj.date[1] : currentMonth; + + // Update title + calendarLabelYear.innerHTML = obj.date[0]; + calendarLabelMonth.innerHTML = months[selectedMonth-1]; + + // Table + var table = document.createElement('table'); + table.setAttribute('width', '100%'); + + // Row + var row = null; + + // Calendar table + for (var i = 0; i < 12; i++) { + if (! (i % 4)) { + // Reset cells container + var row = document.createElement('tr'); + row.setAttribute('align', 'center'); + table.appendChild(row); + } + + // Create cell + var cell = document.createElement('td'); + cell.classList.add('jcalendar-set-month'); + cell.setAttribute('data-value', i+1); + cell.innerText = months[i]; + + if (obj.options.validRange) { + var current = selectedYear + '-' + jSuites.two(i+1); + if (! obj.options.validRange[0] || current >= obj.options.validRange[0].substr(0,7)) { + var test1 = true; + } else { + var test1 = false; + } + + if (! obj.options.validRange[1] || current <= obj.options.validRange[1].substr(0,7)) { + var test2 = true; + } else { + var test2 = false; + } + + if (! (test1 && test2)) { + cell.classList.add('jcalendar-disabled'); + } + } + + if (i+1 == selectedMonth) { + cell.classList.add('jcalendar-selected'); + } + + if (currentYear == selectedYear && i+1 == currentMonth) { + cell.style.fontWeight = 'bold'; + } + + row.appendChild(cell); + } + + calendarBody.innerHTML = ''; + calendarBody.children[0].children[0].appendChild(table); + + // Update + updateActions(); + } + + obj.getYears = function() { + // Mode + obj.options.mode = 'years'; + + // Current date + var date = new Date(); + var currentYear = date.getFullYear(); + var selectedYear = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear()); + + // Array of years + var y = []; + for (var i = 0; i < 25; i++) { + y[i] = parseInt(obj.date[0]) + (i - 12); + } + + // Assembling the year tables + var table = document.createElement('table'); + table.setAttribute('width', '100%'); + + for (var i = 0; i < 25; i++) { + if (! (i % 5)) { + // Reset cells container + var row = document.createElement('tr'); + row.setAttribute('align', 'center'); + table.appendChild(row); + } + + // Create cell + var cell = document.createElement('td'); + cell.classList.add('jcalendar-set-year'); + cell.innerText = y[i]; + + if (selectedYear == y[i]) { + cell.classList.add('jcalendar-selected'); + } + + if (currentYear == y[i]) { + cell.style.fontWeight = 'bold'; + } + + row.appendChild(cell); + } + + calendarBody.innerHTML = ''; + calendarBody.firstChild.firstChild.appendChild(table); + + // Update + updateActions(); + } + + 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 element = jSuites.findElement(e.target, 'jcalendar-container'); + if (element) { + var action = e.target.className; + + // Object id + if (action == 'jcalendar-prev') { + obj.prev(); + } else if (action == 'jcalendar-next') { + obj.next(); + } else if (action == 'jcalendar-month') { + obj.getMonths(); + } else if (action == 'jcalendar-year') { + obj.getYears(); + } else if (action == 'jcalendar-set-year') { + obj.date[0] = e.target.innerText; + if (obj.options.type == 'year-month-picker') { + obj.getMonths(); + } else { + obj.getDays(); + } + } else if (e.target.classList.contains('jcalendar-set-month')) { + var month = parseInt(e.target.getAttribute('data-value')); + if (obj.options.type == 'year-month-picker') { + obj.update(e.target, month); + } else { + obj.date[1] = month; + obj.getDays(); + } + } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update' || action == 'jcalendar-close') { + obj.close(); + } else if (action == 'jcalendar-backdrop') { + obj.close(false, false); + } else if (action == 'jcalendar-reset') { + obj.reset(); + } else if (e.target.classList.contains('jcalendar-set-day') && e.target.innerText) { + obj.update(e.target); + } + } else { + obj.close(); + } + } + + 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) { + obj.setValue(test); + } + } + } + + // 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'); + } + + // Event + if (typeof(obj.options.onupdate) == 'function') { + obj.options.onupdate(el, obj.getValue()); + } + } + + var calendar = null; + var calendarReset = null; + var calendarConfirm = null; + var calendarContainer = null; + var calendarContent = null; + var calendarLabelYear = null; + var calendarLabelMonth = null; + var calendarTable = null; + var calendarBody = null; + + var calendarControls = null; + var calendarControlsTime = null; + var calendarControlsUpdate = null; + var calendarControlsUpdateButton = null; + var calendarSelectHour = null; + var calendarSelectMin = null; + + var init = function() { + // Get value from initial element if that is an input + if (el.tagName == 'INPUT' && el.value) { + options.value = el.value; + } + + // Calendar DOM elements + calendarReset = document.createElement('div'); + calendarReset.className = 'jcalendar-reset'; + + calendarConfirm = document.createElement('div'); + calendarConfirm.className = 'jcalendar-confirm'; + + calendarControls = document.createElement('div'); + calendarControls.className = 'jcalendar-controls' + calendarControls.style.borderBottom = '1px solid #ddd'; + calendarControls.appendChild(calendarReset); + calendarControls.appendChild(calendarConfirm); + + calendarContainer = document.createElement('div'); + calendarContainer.className = 'jcalendar-container'; + + calendarContent = document.createElement('div'); + calendarContent.className = 'jcalendar-content'; + calendarContainer.appendChild(calendarContent); + + // Main element + if (el.tagName == 'DIV') { + calendar = el; + calendar.classList.add('jcalendar-inline'); + } else { + // Add controls to the screen + calendarContent.appendChild(calendarControls); + + calendar = document.createElement('div'); + calendar.className = 'jcalendar'; + } + calendar.classList.add('jcalendar-container'); + 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 + calendarLabelYear = document.createElement('span'); + calendarLabelYear.className = 'jcalendar-year'; + 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 calendarHeader = document.createElement('thead'); + var calendarHeaderRow = document.createElement('tr'); + calendarHeaderRow.appendChild(calendarHeaderPrev); + calendarHeaderRow.appendChild(calendarHeaderTitle); + calendarHeaderRow.appendChild(calendarHeaderNext); + calendarHeader.appendChild(calendarHeaderRow); + + calendarTable = document.createElement('table'); + calendarBody = document.createElement('tbody'); + calendarTable.setAttribute('cellpadding', '0'); + calendarTable.setAttribute('cellspacing', '0'); + calendarTable.appendChild(calendarHeader); + calendarTable.appendChild(calendarBody); + calendarTableContainer.appendChild(calendarTable); + + 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); + } + + 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'; + + calendarControlsTime = document.createElement('div'); + calendarControlsTime.className = 'jcalendar-time'; + calendarControlsTime.style.maxWidth = '140px'; + calendarControlsTime.appendChild(calendarSelectHour); + calendarControlsTime.appendChild(calendarSelectMin); + + calendarControlsUpdateButton = document.createElement('button'); + calendarControlsUpdateButton.setAttribute('type', 'button'); + calendarControlsUpdateButton.className = 'jcalendar-update'; + + 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); + + // 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(); + }); + + el.onmouseup = function() { + obj.open(); + } + + if ('ontouchend' in document.documentElement === true) { + calendar.addEventListener("touchend", mouseUpControls); + } else { + calendar.addEventListener("mouseup", mouseUpControls); + } + + // Global controls + if (! jSuites.calendar.hasEvents) { + // Execute only one time + jSuites.calendar.hasEvents = true; + // Enter and Esc + document.addEventListener("keydown", jSuites.calendar.keydown); + } + + // Set configuration + obj.setOptions(options); + + // Append element to the DOM + if (el.tagName == 'INPUT') { + el.parentNode.insertBefore(calendar, el.nextSibling); + // Add properties + el.setAttribute('autocomplete', 'off'); + // 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]; + } + } + + // Default opened + if (obj.options.opened == true) { + obj.open(); + } + + // Change method + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Keep object available from the node + el.calendar = calendar.calendar = obj; + } + + init(); + + return obj; +}); + +jSuites.calendar.keydown = function(e) { + var calendar = null; + if (calendar = jSuites.calendar.current) { + if (e.which == 13) { + // ENTER + calendar.close(false, true); + } else if (e.which == 27) { + // ESC + calendar.close(false, false); + } + } +} + +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 (Array.isArray(date)) { + var y = date[0]; + var m = date[1]; + var d = date[2]; + var h = date[3]; + var i = date[4]; + var s = date[5]; + } else { + 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"); + if (d >= 0) { + d = v1.substr(d,2); + if (parseInt(d) != d || d > 31) { + test = 0; + } + } else { + d = '01'; + } + + // 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 ''; +} + +/** + * Date to number + */ +jSuites.calendar.dateToNum = function(a, b) { + a = new Date(a); + if (! b) { + b = '1899-12-30 ' + a.getHours() + ':' + a.getMinutes() + ':' + a.getSeconds(); + } + b = new Date(b); + var v = a.getTime() - b.getTime(); + return Math.round(v / 86400000); +} + +/** + * Number to date + */ +jSuites.calendar.numToDate = function(value) { + var d = new Date(Math.round((value - 25569)*86400*1000)); + return d.getFullYear() + "-" + jSuites.two(d.getMonth()+1) + "-" + jSuites.two(d.getDate()) + ' 00:00:00'; +} + +// Helper to convert date into string +jSuites.calendar.getDateString = function(value, options) { + if (! options) { + var options = {}; + } + + // Labels + if (options && typeof(options) == 'object') { + var format = options.format; + } else { + var format = options; + } + + if (! format) { + format = 'YYYY-MM-DD'; + } + + // Convert to number of hours + if (typeof(value) == 'number' && format.indexOf('[h]') >= 0) { + var result = parseFloat(24 * Number(value)); + if (format.indexOf('mm') >= 0) { + var h = (''+result).split('.'); + if (h[1]) { + var d = 60 * parseFloat('0.' + h[1]) + d = parseFloat(d.toFixed(2)); + } else { + var d = 0; + } + result = parseInt(h[0]) + ':' + jSuites.two(d); + } + return result; + } + + // Date instance + if (value instanceof Date) { + value = jSuites.calendar.now(value); + } else if (value && jSuites.isNumeric(value)) { + value = jSuites.calendar.numToDate(value); + } + + // Tokens + var tokens = [ 'DAY', 'WD', 'DDDD', 'DDD', 'DD', 'D', 'Q', 'HH24', 'HH12', 'HH', 'H', 'AM/PM', 'MI', 'SS', 'MS', 'YYYY', 'YYY', 'YY', 'Y', 'MONTH', 'MON', 'MMMMM', 'MMMM', 'MMM', 'MM', 'M', '.' ]; + + // Expression to extract all tokens from the string + var e = new RegExp(tokens.join('|'), 'gi'); + // Extract + var t = format.match(e); + + // Compatibility with excel + for (var i = 0; i < t.length; i++) { + if (t[i].toUpperCase() == 'MM') { + // Not a month, correct to minutes + if (t[i-1] && t[i-1].toUpperCase().indexOf('H') >= 0) { + t[i] = 'mi'; + } else if (t[i-2] && t[i-2].toUpperCase().indexOf('H') >= 0) { + t[i] = 'mi'; + } else if (t[i+1] && t[i+1].toUpperCase().indexOf('S') >= 0) { + t[i] = 'mi'; + } else if (t[i+2] && t[i+2].toUpperCase().indexOf('S') >= 0) { + t[i] = 'mi'; + } + } + } + + // Object + var o = { + tokens: t + } + + // Value + if (value) { + var d = ''+value; + var splitStr = (d.indexOf('T') !== -1) ? 'T' : ' '; + d = d.split(splitStr); + + var h = 0; + var m = 0; + var s = 0; + + if (d[1]) { + h = d[1].split(':'); + m = h[1] ? h[1] : 0; + s = h[2] ? h[2] : 0; + h = h[0] ? h[0] : 0; + } + + 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) { + + // Data + o.data = [ d[0], d[1], d[2], h, m, s ]; + + // Value + o.value = []; + + // Calendar instance + var calendar = new Date(o.data[0], o.data[1]-1, o.data[2], o.data[3], o.data[4], o.data[5]); + + // Get method + var get = function(i) { + // Token + var t = this.tokens[i]; + // Case token + var s = t.toUpperCase(); + var v = null; + + if (s === 'YYYY') { + v = this.data[0]; + } else if (s === 'YYY') { + v = this.data[0].substring(1,4); + } else if (s === 'YY') { + v = this.data[0].substring(2,4); + } else if (s === 'Y') { + v = this.data[0].substring(3,4); + } else if (t === 'MON') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0,3).toUpperCase(); + } else if (t === 'mon') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0,3).toLowerCase(); + } else if (t === 'MONTH') { + v = jSuites.calendar.months[calendar.getMonth()].toUpperCase(); + } else if (t === 'month') { + v = jSuites.calendar.months[calendar.getMonth()].toLowerCase(); + } else if (s === 'MMMMM') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0, 1); + } else if (s === 'MMMM' || t === 'Month') { + v = jSuites.calendar.months[calendar.getMonth()]; + } else if (s === 'MMM' || t == 'Mon') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0,3); + } else if (s === 'MM') { + v = jSuites.two(this.data[1]); + } else if (s === 'M') { + v = calendar.getMonth()+1; + } else if (t === 'DAY') { + v = jSuites.calendar.weekdays[calendar.getDay()].toUpperCase(); + } else if (t === 'day') { + v = jSuites.calendar.weekdays[calendar.getDay()].toLowerCase(); + } else if (s === 'DDDD' || t == 'Day') { + v = jSuites.calendar.weekdays[calendar.getDay()]; + } else if (s === 'DDD') { + v = jSuites.calendar.weekdays[calendar.getDay()].substr(0,3); + } else if (s === 'DD') { + v = jSuites.two(this.data[2]); + } else if (s === 'D') { + v = this.data[2]; + } else if (s === 'Q') { + v = Math.floor((calendar.getMonth() + 3) / 3); + } else if (s === 'HH24' || s === 'HH') { + v = jSuites.two(this.data[3]); + } else if (s === 'HH12') { + if (this.data[3] > 12) { + v = jSuites.two(this.data[3] - 12); + } else { + v = jSuites.two(this.data[3]); + } + } else if (s === 'H') { + v = this.data[3]; + } else if (s === 'MI') { + v = jSuites.two(this.data[4]); + } else if (s === 'SS') { + v = jSuites.two(this.data[5]); + } else if (s === 'MS') { + v = calendar.getMilliseconds(); + } else if (s === 'AM/PM') { + if (this.data[3] >= 12) { + v = 'PM'; + } else { + v = 'AM'; + } + } else if (s === 'WD') { + v = jSuites.calendar.weekdays[calendar.getDay()]; + } + + if (v === null) { + this.value[i] = this.tokens[i]; + } else { + this.value[i] = v; + } + } + + for (var i = 0; i < o.tokens.length; i++) { + get.call(o, i); + } + // Put pieces together + value = o.value.join(''); + } else { + value = ''; + } + } + + return value; +} + +// Jsuites calendar labels +jSuites.calendar.weekdays = [ 'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday' ]; +jSuites.calendar.months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; +jSuites.calendar.weekdaysShort = [ 'Sun','Mon','Tue','Wed','Thu','Fri','Sat' ]; +jSuites.calendar.monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + + +jSuites.color = (function(el, options) { + // Already created, update options + if (el.color) { + return el.color.setOptions(options, true); + } + + // New instance + var obj = { type: 'color' }; + obj.options = {}; + + var container = null; + var backdrop = null; + var content = null; + var resetButton = null; + var closeButton = null; + var tabs = null; + var jsuitesTabs = null; + + /** + * Update options + */ + obj.setOptions = function(options, reset) { + /** + * @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, + opened: false, + } + + if (! options) { + options = {}; + } + + if (options && ! options.palette) { + // Default pallete + options.palette = jSuites.palette(); + } + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Update the text of the controls, if they have already been created + if (resetButton) { + resetButton.innerHTML = obj.options.resetLabel; + } + if (closeButton) { + closeButton.innerHTML = obj.options.doneLabel; + } + + // Update the pallete + if (obj.options.palette && jsuitesTabs) { + jsuitesTabs.updateContent(0, table()); + } + + // Value + if (typeof obj.options.value === 'string') { + el.value = obj.options.value; + } + + // Placeholder + if (obj.options.placeholder) { + el.setAttribute('placeholder', obj.options.placeholder); + } else { + if (el.getAttribute('placeholder')) { + el.removeAttribute('placeholder'); + } + } + + return obj; + } + + /** + * Open color pallete + */ + obj.open = function() { + if (! container.classList.contains('jcolor-focus')) { + // Start tracking + jSuites.tracking(obj, true); + + // 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'; + } + } + } + + if (typeof(obj.options.onopen) == 'function') { + obj.options.onopen(el); + } + + jsuitesTabs.setBorder(jsuitesTabs.getActive()); + + // Update sliders + if (obj.options.value) { + var rgb = HexToRgb(obj.options.value); + + rgbInputs.forEach(function(rgbInput, index) { + rgbInput.value = rgb[index]; + rgbInput.dispatchEvent(new Event('input')); + }); + } + } + } + + /** + * Close color pallete + */ + obj.close = function(ignoreEvents) { + if (container.classList.contains('jcolor-focus')) { + // Remove focus + container.classList.remove('jcolor-focus'); + // Make sure backdrop is hidden + backdrop.style.display = ''; + // Call related events + if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { + obj.options.onclose(el); + } + // Stop the object + jSuites.tracking(obj, false); + } + + return obj.options.value; + } + + /** + * Set value + */ + obj.setValue = function(color) { + if (! color) { + color = ''; + } + + if (color != obj.options.value) { + obj.options.value = color; + slidersResult = 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'); + } + + // Onchange + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, color); + } + + // Changes + if (el.value != obj.options.value) { + // Set input value + el.value = obj.options.value; + // Element onchange native + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + + if (obj.options.closeOnChange == true) { + obj.close(); + } + } + } + + /** + * Get value + */ + obj.getValue = function() { + return obj.options.value; + } + + var backdropClickControl = false; + + // Converts a number in decimal to hexadecimal + var decToHex = function(num) { + var hex = num.toString(16); + return hex.length === 1 ? "0" + hex : hex; + } + + // Converts a color in rgb to hexadecimal + var rgbToHex = function(r, g, b) { + return "#" + decToHex(r) + decToHex(g) + decToHex(b); + } + + // Converts a number in hexadecimal to decimal + var hexToDec = function(hex) { + return parseInt('0x' + hex); + } + + // Converts a color in hexadecimal to rgb + var HexToRgb = function(hex) { + return [hexToDec(hex.substr(1, 2)), hexToDec(hex.substr(3, 2)), hexToDec(hex.substr(5, 2))] + } + + var table = function() { + // Content of the first tab + var tableContainer = document.createElement('div'); + tableContainer.className = 'jcolor-grid'; + + // Cells + obj.values = []; + + // Table pallete + var t = document.createElement('table'); + t.setAttribute('cellpadding', '7'); + t.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.length < 7 && 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; + } + t.appendChild(tr); + } + + // Append to the table + tableContainer.appendChild(t); + + // Select color + tableContainer.addEventListener("mousedown", function(e) { + if (e.target.tagName == 'TD') { + var value = e.target.getAttribute('data-value'); + if (value) { + obj.setValue(value); + } + } + }); + + return tableContainer; + } + + // Canvas where the image will be rendered + var canvas = document.createElement('canvas'); + canvas.width = 200; + canvas.height = 160; + var context = canvas.getContext("2d"); + + var resizeCanvas = function() { + // Specifications necessary to correctly obtain colors later in certain positions + var m = tabs.firstChild.getBoundingClientRect(); + canvas.width = m.width - 14; + gradient() + } + + var gradient = function() { + var g = context.createLinearGradient(0, 0, canvas.width, 0); + // Create color gradient + g.addColorStop(0, "rgb(255,0,0)"); + g.addColorStop(0.15, "rgb(255,0,255)"); + g.addColorStop(0.33, "rgb(0,0,255)"); + g.addColorStop(0.49, "rgb(0,255,255)"); + g.addColorStop(0.67, "rgb(0,255,0)"); + g.addColorStop(0.84, "rgb(255,255,0)"); + g.addColorStop(1, "rgb(255,0,0)"); + context.fillStyle = g; + context.fillRect(0, 0, canvas.width, canvas.height); + g = context.createLinearGradient(0, 0, 0, canvas.height); + g.addColorStop(0, "rgba(255,255,255,1)"); + g.addColorStop(0.5, "rgba(255,255,255,0)"); + g.addColorStop(0.5, "rgba(0,0,0,0)"); + g.addColorStop(1, "rgba(0,0,0,1)"); + context.fillStyle = g; + context.fillRect(0, 0, canvas.width, canvas.height); + } + + var hsl = function() { + var element = document.createElement('div'); + element.className = "jcolor-hsl"; + + var point = document.createElement('div'); + point.className = 'jcolor-point'; + + var div = document.createElement('div'); + div.appendChild(canvas); + div.appendChild(point); + element.appendChild(div); + + // Moves the marquee point to the specified position + var update = function(buttons, x, y) { + if (buttons === 1) { + var rect = element.getBoundingClientRect(); + var left = x - rect.left; + var top = y - rect.top; + if (left < 0) { + left = 0; + } + if (top < 0) { + top = 0; + } + if (left > rect.width) { + left = rect.width; + } + if (top > rect.height) { + top = rect.height; + } + point.style.left = left + 'px'; + point.style.top = top + 'px'; + var pixel = context.getImageData(left, top, 1, 1).data; + slidersResult = rgbToHex(pixel[0], pixel[1], pixel[2]); + } + } + + // Applies the point's motion function to the div that contains it + element.addEventListener('mousedown', function(e) { + update(e.buttons, e.clientX, e.clientY); + }); + + element.addEventListener('mousemove', function(e) { + update(e.buttons, e.clientX, e.clientY); + }); + + element.addEventListener('touchmove', function(e) { + update(1, e.changedTouches[0].clientX, e.changedTouches[0].clientY); + }); + + return element; + } + + var slidersResult = ''; + + var rgbInputs = []; + + var changeInputColors = function() { + if (slidersResult !== '') { + for (var j = 0; j < rgbInputs.length; j++) { + var currentColor = HexToRgb(slidersResult); + + currentColor[j] = 0; + + var newGradient = 'linear-gradient(90deg, rgb('; + newGradient += currentColor.join(', '); + newGradient += '), rgb('; + + currentColor[j] = 255; + + newGradient += currentColor.join(', '); + newGradient += '))'; + + rgbInputs[j].style.backgroundImage = newGradient; + } + } + } + + var sliders = function() { + // Content of the third tab + var slidersElement = document.createElement('div'); + slidersElement.className = 'jcolor-sliders'; + + var slidersBody = document.createElement('div'); + + // Creates a range-type input with the specified name + var createSliderInput = function(name) { + var inputContainer = document.createElement('div'); + inputContainer.className = 'jcolor-sliders-input-container'; + + var label = document.createElement('label'); + label.innerText = name; + + var subContainer = document.createElement('div'); + subContainer.className = 'jcolor-sliders-input-subcontainer'; + + var input = document.createElement('input'); + input.type = 'range'; + input.min = 0; + input.max = 255; + input.value = 0; + + inputContainer.appendChild(label); + subContainer.appendChild(input); + + var value = document.createElement('div'); + value.innerText = input.value; + + input.addEventListener('input', function() { + value.innerText = input.value; + }); + + subContainer.appendChild(value); + inputContainer.appendChild(subContainer); + + slidersBody.appendChild(inputContainer); + + return input; + } + + // Creates red, green and blue inputs + rgbInputs = [ + createSliderInput('Red'), + createSliderInput('Green'), + createSliderInput('Blue'), + ]; + + slidersElement.appendChild(slidersBody); + + // Element that prints the current color + var slidersResultColor = document.createElement('div'); + slidersResultColor.className = 'jcolor-sliders-final-color'; + + var resultElement = document.createElement('div'); + resultElement.style.visibility = 'hidden'; + resultElement.innerText = 'a'; + slidersResultColor.appendChild(resultElement) + + // Update the element that prints the current color + var updateResult = function() { + var resultColor = rgbToHex(parseInt(rgbInputs[0].value), parseInt(rgbInputs[1].value), parseInt(rgbInputs[2].value)); + + resultElement.innerText = resultColor; + resultElement.style.color = resultColor; + resultElement.style.removeProperty('visibility'); + + slidersResult = resultColor; + } + + // Apply the update function to color inputs + rgbInputs.forEach(function(rgbInput) { + rgbInput.addEventListener('input', function() { + updateResult(); + changeInputColors(); + }); + }); + + slidersElement.appendChild(slidersResultColor); + + return slidersElement; + } + + var init = function() { + // Initial options + obj.setOptions(options); + + // Add a proper input tag when the element is an input + if (el.tagName == 'INPUT') { + el.classList.add('jcolor-input'); + el.readOnly = true; + } + + // Table container + container = document.createElement('div'); + container.className = 'jcolor'; + + // Table container + backdrop = document.createElement('div'); + backdrop.className = 'jcolor-backdrop'; + container.appendChild(backdrop); + + // Content + content = document.createElement('div'); + content.className = 'jcolor-content'; + + // Controls + var controls = document.createElement('div'); + controls.className = 'jcolor-controls'; + content.appendChild(controls); + + // Reset button + resetButton = document.createElement('div'); + resetButton.className = 'jcolor-reset'; + resetButton.innerHTML = obj.options.resetLabel; + resetButton.onclick = function(e) { + obj.setValue(''); + obj.close(); + } + controls.appendChild(resetButton); + + // Close button + closeButton = document.createElement('div'); + closeButton.className = 'jcolor-close'; + closeButton.innerHTML = obj.options.doneLabel; + closeButton.onclick = function(e) { + if (jsuitesTabs.getActive() > 0) { + obj.setValue(slidersResult); + } + obj.close(); + } + controls.appendChild(closeButton); + + // Element that will be used to create the tabs + tabs = document.createElement('div'); + content.appendChild(tabs); + + // Starts the jSuites tabs component + jsuitesTabs = jSuites.tabs(tabs, { + animation: true, + data: [ + { + title: 'Grid', + contentElement: table(), + }, + { + title: 'Spectrum', + contentElement: hsl(), + }, + { + title: 'Sliders', + contentElement: sliders(), + } + ], + onchange: function(element, instance, index) { + if (index === 1) { + resizeCanvas(); + } else { + var color = slidersResult !== '' ? slidersResult : obj.getValue(); + + if (index === 2 && color) { + var rgb = HexToRgb(color); + + rgbInputs.forEach(function(rgbInput, index) { + rgbInput.value = rgb[index]; + rgbInput.dispatchEvent(new Event('input')); + }); + } + } + }, + palette: 'modern', + }); + + container.appendChild(content); + + // Insert picker after the element + if (el.tagName == 'INPUT') { + el.parentNode.insertBefore(container, el.nextSibling); + } else { + el.appendChild(container); + } + + /** + * If element is focus open the picker + */ + el.addEventListener("mouseup", function(e) { + obj.open(); + }); + + backdrop.addEventListener("mousedown", function(e) { + backdropClickControl = true; + }); + + backdrop.addEventListener("mouseup", function(e) { + if (backdropClickControl) { + obj.close(); + backdropClickControl = false; + } + }); + + // If the picker is open on the spectrum tab, it changes the canvas size when the window size is changed + window.addEventListener('resize', function() { + if (container.classList.contains('jcolor-focus') && jsuitesTabs.getActive() == 1) { + resizeCanvas(); + } + }); + + // Default opened + if (obj.options.opened == true) { + obj.open(); + } + + // Change + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Keep object available from the node + el.color = obj; + + // Container shortcut + container.color = obj; + } + + init(); + + 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.tooltip) { + itemContainer.setAttribute('title', item.tooltip); + } + + 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("mousedown", function(e) { + e.preventDefault(); + }); + itemContainer.addEventListener("mouseup", function() { + // Execute method + this.method(this); + }); + } + itemContainer.appendChild(itemText); + + if (item.submenu) { + var itemIconSubmenu = document.createElement('span'); + itemIconSubmenu.innerHTML = "►"; + 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) { + obj.close(); + }); + + 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) { + // Already created, update options + if (el.dropdown) { + return el.dropdown.setOptions(options, true); + } + + // New instance + var obj = { type: 'dropdown' }; + obj.options = {}; + + // Success + var success = function(data, val) { + // Set data + if (data && data.length) { + // Sort + if (obj.options.sortResults !== false) { + if(typeof obj.options.sortResults == "function") { + data.sort(obj.options.sortResults); + } else { + data.sort(sortData); + } + } + + obj.setData(data); + + // Onload method + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj, data, val); + } + } + + // Set value + if (val) { + applyValue(val); + } + + // Component value + if (val === undefined || val === null) { + obj.options.value = ''; + } + el.value = obj.options.value; + + // Open dropdown + if (obj.options.opened == true) { + obj.open(); + } + } + + + // Default sort + var sortData = function(itemA, itemB) { + var testA, testB; + if(typeof itemA == "string") { + testA = itemA; + } else { + if(itemA.text) { + testA = itemA.text; + } else if(itemA.name) { + testA = itemA.name; + } + } + + if(typeof itemB == "string") { + testB = itemB; + } else { + if(itemB.text) { + testB = itemB.text; + } else if(itemB.name) { + testB = itemB.name; + } + } + + if(typeof testA == "string" || typeof testB == "string") { + if(typeof testA != "string") { testA = ""+testA; } + if(typeof testB != "string") { testB = ""+testB; } + return testA.localeCompare(testB); + } else { + return testA - testB; + } + } + + /** + * Reset the options for the dropdown + */ + var resetValue = function() { + // Reset value container + obj.value = {}; + // 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 options + obj.options.value = ''; + } + + /** + * Apply values to the dropdown + */ + var applyValue = function(values) { + // Reset the current values + resetValue(); + + // Read values + if (values !== null) { + if (! values) { + if (typeof(obj.value['']) !== 'undefined') { + obj.value[''] = ''; + } + } else { + if (! Array.isArray(values)) { + values = ('' + values).split(';'); + } + for (var i = 0; i < values.length; i++) { + obj.value[values[i]] = ''; + } + } + } + + // Update the DOM + for (var i = 0; i < obj.items.length; i++) { + if (typeof(obj.value[Value(i)]) !== 'undefined') { + if (obj.items[i].element) { + obj.items[i].element.classList.add('jdropdown-selected') + } + obj.items[i].selected = true; + + // Keep label + obj.value[Value(i)] = Text(i); + } + } + + // Global value + obj.options.value = Object.keys(obj.value).join(';'); + + // Update labels + obj.header.value = obj.getText(); + } + + // Get the value of one item + var Value = function(k, v) { + // Legacy purposes + if (! obj.options.format) { + var property = 'value'; + } else { + var property = 'id'; + } + + if (obj.items[k]) { + if (v !== undefined) { + return obj.items[k].data[property] = v; + } else { + return obj.items[k].data[property]; + } + } + + return ''; + } + + // Get the label of one item + var Text = function(k, v) { + // Legacy purposes + if (! obj.options.format) { + var property = 'text'; + } else { + var property = 'name'; + } + + if (obj.items[k]) { + if (v !== undefined) { + return obj.items[k].data[property] = v; + } else { + return obj.items[k].data[property]; + } + } + + return ''; + } + + var getValue = function() { + return Object.keys(obj.value); + } + + var getText = function() { + var data = []; + var k = Object.keys(obj.value); + for (var i = 0; i < k.length; i++) { + data.push(obj.value[k[i]]); + } + return data; + } + + obj.setOptions = function(options, reset) { + if (! options) { + options = {}; + } + + // Default configuration + var defaults = { + url: null, + data: [], + format: 0, + 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, + onbeforeinsert: null, + sortResults: false, + autofocus: false, + } + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Force autocomplete search + if (obj.options.remoteSearch == true || obj.options.type === 'searchbar') { + obj.options.autocomplete = true; + } + + // New options + if (obj.options.newOptions == true) { + obj.header.classList.add('jdropdown-add'); + } else { + obj.header.classList.remove('jdropdown-add'); + } + + // Autocomplete + if (obj.options.autocomplete == true) { + obj.header.removeAttribute('readonly'); + } else { + obj.header.setAttribute('readonly', 'readonly'); + } + + // Place holder + if (obj.options.placeholder) { + obj.header.setAttribute('placeholder', obj.options.placeholder); + } else { + obj.header.removeAttribute('placeholder'); + } + + // Remove specific dropdown typing to add again + el.classList.remove('jdropdown-searchbar'); + el.classList.remove('jdropdown-picker'); + el.classList.remove('jdropdown-list'); + + 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) { + if (obj.options.autocomplete) { + el.classList.add('jdropdown-searchbar'); + obj.options.type = 'searchbar'; + } else { + 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; + } else { + el.style.removeProperty('width'); + el.style.removeProperty('min-width'); + } + + el.classList.add('jdropdown-default'); + obj.options.type = 'default'; + } + } + + // Close button + if (obj.options.type == 'searchbar') { + containerHeader.appendChild(closeButton); + } else { + container.insertBefore(closeButton, container.firstChild); + } + + // Load the content + if (obj.options.url && ! options.data) { + jSuites.ajax({ + url: obj.options.url, + method: 'GET', + dataType: 'json', + success: function(data) { + if (data) { + success(data, obj.options.value); + } + } + }); + } else { + success(obj.options.data, obj.options.value); + } + + // Return the instance + return obj; + } + + // Helpers + var containerHeader = null; + var container = null; + var content = null; + var closeButton = null; + var resetButton = null; + var backdrop = null; + + var keyTimer = null; + + /** + * Init dropdown + */ + var init = function() { + // Do not accept null + if (! options) { + 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; + } + + // Place holder + if (! options.placeholder && el.getAttribute('placeholder')) { + options.placeholder = el.getAttribute('placeholder'); + } + + // Value container + obj.value = {}; + // Containers + obj.items = []; + obj.groups = []; + // Search options + obj.search = ''; + obj.results = null; + + // Create dropdown + el.classList.add('jdropdown'); + + // Header container + containerHeader = document.createElement('div'); + containerHeader.className = 'jdropdown-container-header'; + + // Header + obj.header = document.createElement('input'); + obj.header.className = 'jdropdown-header'; + obj.header.type = 'text'; + obj.header.setAttribute('autocomplete', 'off'); + obj.header.onfocus = function() { + if (typeof(obj.options.onfocus) == 'function') { + obj.options.onfocus(el); + } + } + + obj.header.onblur = function() { + if (typeof(obj.options.onblur) == 'function') { + obj.options.onblur(el); + } + } + + obj.header.onkeyup = function(e) { + if (obj.options.autocomplete == true && ! 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 { + if (! obj.options.autocomplete) { + obj.next(e.key); + } + } + } + + // Global controls + if (! jSuites.dropdown.hasEvents) { + // Execute only one time + jSuites.dropdown.hasEvents = true; + // Enter and Esc + document.addEventListener("keydown", jSuites.dropdown.keydown); + } + + // Container + container = document.createElement('div'); + container.className = 'jdropdown-container'; + + // Dropdown content + content = document.createElement('div'); + content.className = 'jdropdown-content'; + + // Close button + closeButton = document.createElement('div'); + closeButton.className = 'jdropdown-close'; + closeButton.innerHTML = 'Done'; + + // Reset button + resetButton = document.createElement('div'); + resetButton.className = 'jdropdown-reset'; + resetButton.innerHTML = 'x'; + resetButton.onclick = function() { + obj.reset(); + obj.close(); + } + + // Create backdrop + backdrop = document.createElement('div'); + backdrop.className = 'jdropdown-backdrop'; + + // Append elements + containerHeader.appendChild(obj.header); + + container.appendChild(content); + el.appendChild(containerHeader); + el.appendChild(container); + el.appendChild(backdrop); + + // Set the otiptions + obj.setOptions(options); + + if ('ontouchsend' in document.documentElement === true) { + el.addEventListener('touchsend', jSuites.dropdown.mouseup); + } else { + el.addEventListener('mouseup', jSuites.dropdown.mouseup); + } + + // Lazyloading + if (obj.options.lazyLoading == true) { + jSuites.lazyLoading(content, { + loadUp: obj.loadUp, + loadDown: obj.loadDown, + }); + } + + content.onwheel = function(e) { + e.stopPropagation(); + } + + // Change method + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(obj.options.multiple ? true : false); + } else { + obj.setValue(val); + } + } + + // Keep object available from the node + el.dropdown = obj; + } + + /** + * Get the current remote source of data URL + */ + obj.getUrl = function() { + return obj.options.url; + } + + /** + * Set the new data from a remote source + * @param {string} url - url from the remote source + * @param {function} callback - callback when the data is loaded + */ + obj.setUrl = function(url, callback) { + obj.options.url = url; + + jSuites.ajax({ + url: obj.options.url, + method: 'GET', + dataType: 'json', + success: function(data) { + obj.setData(data); + // Callback + if (typeof(callback) == 'function') { + callback(obj); + } + } + }); + } + + /** + * Set ID for one item + */ + obj.setId = function(item, v) { + // Legacy purposes + if (! obj.options.format) { + var property = 'value'; + } else { + var property = 'id'; + } + + if (typeof(item) == 'object') { + item[property] = v; + } else { + obj.items[item].data[property] = v; + } + } + + /** + * Add a new item + * @param {string} title - title of the new item + * @param {string} id - value/id of the new item + */ + obj.add = function(title, id) { + if (! title) { + var current = obj.options.autocomplete == true ? obj.header.value : ''; + var title = prompt(jSuites.translate('Add A New Option'), current); + if (! title) { + return false; + } + } + + // Id + if (! id) { + id = jSuites.guid(); + } + + // Create new item + if (! obj.options.format) { + var item = { + value: id, + text: title, + } + } else { + var item = { + id: id, + name: title, + } + } + + // Callback + if (typeof(obj.options.onbeforeinsert) == 'function') { + var ret = obj.options.onbeforeinsert(obj, item); + if (ret === false) { + return false; + } else if (ret) { + item = ret; + } + } + + // Add item to the main list + obj.options.data.push(item); + + // Create DOM + 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, item, newItem); + } + + // Show content + if (content.style.display == 'none') { + content.style.display = ''; + } + + // Search? + if (obj.results) { + obj.results.push(newItem); + } + + return item; + } + + /** + * Create a new item + */ + obj.createItem = function(data, group, groupName) { + // Keep the correct source of data + if (! obj.options.format) { + if (! data.value && data.id !== undefined) { + data.value = data.id; + //delete data.id; + } + if (! data.text && data.name !== undefined) { + data.text = data.name; + //delete data.name; + } + } else { + if (! data.id && data.value !== undefined) { + data.id = data.value; + //delete data.value; + } + if (! data.name && data.text !== undefined) { + data.name = data.text + //delete data.text; + } + } + + // Create item + var item = {}; + item.element = document.createElement('div'); + item.element.className = 'jdropdown-item'; + item.element.indexValue = obj.items.length; + item.data = data; + + // Groupd DOM + if (group) { + item.group = group; + } + + // Id + if (data.id) { + item.element.setAttribute('id', data.id); + } + + // Disabled + if (data.disabled == true) { + item.element.setAttribute('data-disabled', true); + } + + // Tooltip + if (data.tooltip) { + item.element.setAttribute('title', data.tooltip); + } + + // 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.icon) { + var icon = document.createElement('span'); + icon.className = "jdropdown-icon material-icons"; + icon.innerText = data.icon; + if (! data.title) { + icon.classList.add('jdropdown-icon-small'); + } + if (data.color) { + icon.style.color = data.color; + } + item.element.appendChild(icon); + } else if (data.color) { + var color = document.createElement('div'); + color.className = 'jdropdown-color'; + color.style.backgroundColor = data.color; + item.element.appendChild(color); + } + + // Set content + if (! obj.options.format) { + var text = data.text; + } else { + var text = data.name; + } + + var node = document.createElement('div'); + node.className = 'jdropdown-description'; + node.innerHTML = text || ' '; + + // Title + if (data.title) { + var title = document.createElement('div'); + title.className = 'jdropdown-title'; + title.innerText = data.title; + node.appendChild(title); + } + + // Set content + if (! obj.options.format) { + var val = data.value; + } else { + var val = data.id; + } + + // Value + if (obj.value[val]) { + 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) { + // 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); + } + } + + // Number of items counter + var counter = 0; + + // 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 || counter < 200) { + groupContent.appendChild(item.element); + counter++; + } + } + // 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 || counter < 200) { + content.appendChild(item.element); + counter++; + } + } + } + } + } + + 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 + if (! obj.options.format) { + data[i] = { + value: data[i], + text: data[i] + } + } else { + data[i] = { + id: data[i], + name: data[i] + } + } + } + } + + // Reset current value + resetValue(); + + // Make sure the content container is blank + content.innerHTML = ''; + + // Reset + obj.header.value = ''; + + // Reset items and values + obj.items = []; + + // Append data + obj.appendData(data); + + // Update data + obj.options.data = data; + } + } + + obj.getData = function() { + return obj.options.data; + } + + /** + * Get position of the item + */ + obj.getPosition = function(val) { + for (var i = 0; i < obj.items.length; i++) { + if (Value(i) == val) { + return i; + } + } + return false; + } + + /** + * Get dropdown current text + */ + obj.getText = function(asArray) { + // Get value + var v = getText(); + // Return value + if (asArray) { + return v; + } else { + return v.join('; '); + } + } + + /** + * Get dropdown current value + */ + obj.getValue = function(asArray) { + // Get value + var v = getValue(); + // Return value + if (asArray) { + return v; + } else { + return v.join(';'); + } + } + + /** + * Change event + */ + var change = function(oldValue) { + // Events + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, obj, oldValue, obj.options.value); + } + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + /** + * Set value + */ + obj.setValue = function(newValue) { + // Current value + var oldValue = obj.getValue(); + // New value + if (Array.isArray(newValue)) { + newValue = newValue.join(';') + } + + if (oldValue !== newValue) { + // Set value + applyValue(newValue); + + // Change + change(oldValue); + } + } + + obj.resetSelected = function() { + obj.setValue(null); + } + + obj.selectIndex = function(index, force) { + // Make sure is a number + var index = parseInt(index); + + // Only select those existing elements + if (obj.items && obj.items[index] && (force === true || obj.items[index].data.disabled !== true)) { + // Reset cursor to a new position + obj.setCursor(index, false); + + // Behaviour + if (! obj.options.multiple) { + // Update value + if (obj.items[index].selected) { + obj.setValue(null); + } else { + obj.setValue(Value(index)); + } + + // Close component + obj.close(); + } else { + // Old value + var oldValue = obj.options.value; + + // Toggle option + if (obj.items[index].selected) { + obj.items[index].element.classList.remove('jdropdown-selected'); + obj.items[index].selected = false; + + delete obj.value[Value(index)]; + } else { + // Select element + obj.items[index].element.classList.add('jdropdown-selected'); + obj.items[index].selected = true; + + // Set value + obj.value[Value(index)] = Text(index); + } + + // Global value + obj.options.value = Object.keys(obj.value).join(';'); + + // Update labels for multiple dropdown + if (obj.options.autocomplete == false) { + obj.header.value = getText().join('; '); + } + + // Events + change(oldValue); + } + } + } + + obj.selectItem = function(item) { + obj.selectIndex(item.indexValue); + } + + var exists = function(k, result) { + for (var j = 0; j < result.length; j++) { + if (! obj.options.format) { + if (result[j].value == k) { + return true; + } + } else { + if (result[j].id == k) { + return true; + } + } + } + return false; + } + + obj.find = function(str) { + if (obj.search == str.trim()) { + return false; + } + + // Search term + obj.search = str; + + // Reset index + obj.setCursor(); + + // Remove nodes from all groups + if (obj.groups.length) { + for (var i = 0; i < obj.groups.length; i++) { + obj.groups[i].lastChild.innerHTML = ''; + } + } + + // Remove all nodes + content.innerHTML = ''; + + // Remove current items in the remote search + if (obj.options.remoteSearch == true) { + // Reset results + obj.results = null; + // URL + var url = obj.options.url + (obj.options.url.indexOf('?') > 0 ? '&' : '?') + 'q=' + str; + // Remote search + jSuites.ajax({ + url: url, + method: 'GET', + dataType: 'json', + success: function(result) { + // Reset items + obj.items = []; + + // Add the current selected items to the results in case they are not there + var current = Object.keys(obj.value); + if (current.length) { + for (var i = 0; i < current.length; i++) { + if (! exists(current[i], result)) { + if (! obj.options.format) { + result.unshift({ value: current[i], text: obj.value[current[i]] }); + } else { + result.unshift({ id: current[i], name: obj.value[current[i]] }); + } + } + } + } + // Append data + obj.appendData(result); + // Show or hide results + if (! result.length) { + content.style.display = 'none'; + } else { + content.style.display = ''; + } + } + }); + } else { + // Search terms + str = new RegExp(str, 'gi'); + + // Reset search + var results = []; + + // Append options + for (var i = 0; i < obj.items.length; i++) { + // Item label + var label = Text(i); + // Item title + var title = obj.items[i].data.title || ''; + // Group name + var groupName = obj.items[i].data.group || ''; + // Synonym + var synonym = obj.items[i].data.synonym || ''; + if (synonym) { + synonym = synonym.join(' '); + } + + if (str == null || obj.items[i].selected == true || label.match(str) || title.match(str) || groupName.match(str) || synonym.match(str)) { + results.push(obj.items[i]); + } + } + + if (! results.length) { + content.style.display = 'none'; + + // Results + obj.results = null; + } else { + content.style.display = ''; + + // Results + obj.results = results; + + // Show 200 items at once + var number = 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.lastChild.appendChild(obj.results[i].element); + } else { + content.appendChild(obj.results[i].element); + } + } + } + } + + // Auto focus + if (obj.options.autofocus == true) { + obj.first(); + } + } + + obj.open = function() { + // Focus + if (! el.classList.contains('jdropdown-focus')) { + // Current dropdown + jSuites.dropdown.current = obj; + + // Start tracking + jSuites.tracking(obj, true); + + // 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 = getValue(); + if (k[0]) { + var cursor = obj.getPosition(k[0]); + if (cursor !== false) { + 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 (el.classList.contains('jdropdown-focus')) { + // Update labels + obj.header.value = obj.getText(); + // Remove cursor + obj.setCursor(); + // 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'); + // Start tracking + jSuites.tracking(obj, false); + // Current dropdown + jSuites.dropdown.current = null; + } + + 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 { + index = parseInt(index); + + // Cursor only for visible items + if (obj.items[index].element.parentNode) { + 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 available item + */ + obj.first = function() { + if (obj.options.lazyLoading === true) { + obj.loadFirst(); + } + + var items = content.querySelectorAll('.jdropdown-item'); + if (items.length) { + var newIndex = items[0].indexValue; + obj.setCursor(newIndex); + } + } + + /** + * Last available item + */ + obj.last = function() { + if (obj.options.lazyLoading === true) { + obj.loadLast(); + } + + var items = content.querySelectorAll('.jdropdown-item'); + if (items.length) { + var newIndex = items[items.length-1].indexValue; + obj.setCursor(newIndex); + } + } + + obj.next = function(letter) { + var newIndex = null; + + if (letter) { + if (letter.length == 1) { + // Current index + var current = obj.currentIndex || -1; + // Letter + letter = letter.toLowerCase(); + + var e = null; + var l = null; + var items = content.querySelectorAll('.jdropdown-item'); + if (items.length) { + for (var i = 0; i < items.length; i++) { + if (items[i].indexValue > current) { + if (e = obj.items[items[i].indexValue]) { + if (l = e.element.innerText[0]) { + l = l.toLowerCase(); + if (letter == l) { + newIndex = items[i].indexValue; + break; + } + } + } + } + } + obj.setCursor(newIndex); + } + } + } else { + if (obj.currentIndex == undefined || obj.currentIndex == null) { + obj.first(); + } else { + var element = obj.items[obj.currentIndex].element; + + var next = element.nextElementSibling; + if (next) { + if (next.classList.contains('jdropdown-group')) { + next = next.lastChild.firstChild; + } + newIndex = next.indexValue; + } else { + if (element.parentNode.classList.contains('jdropdown-group-items')) { + if (next = element.parentNode.parentNode.nextElementSibling) { + if (next.classList.contains('jdropdown-group')) { + next = next.lastChild.firstChild; + } else if (next.classList.contains('jdropdown-item')) { + newIndex = next.indexValue; + } else { + next = null; + } + } + + if (next) { + newIndex = next.indexValue; + } + } + } + + if (newIndex !== null) { + obj.setCursor(newIndex); + } + } + } + } + + obj.prev = function() { + var newIndex = null; + + if (obj.currentIndex === null) { + obj.first(); + } else { + var element = obj.items[obj.currentIndex].element; + + var prev = element.previousElementSibling; + if (prev) { + if (prev.classList.contains('jdropdown-group')) { + prev = prev.lastChild.lastChild; + } + newIndex = prev.indexValue; + } else { + if (element.parentNode.classList.contains('jdropdown-group-items')) { + if (prev = element.parentNode.parentNode.previousElementSibling) { + if (prev.classList.contains('jdropdown-group')) { + prev = prev.lastChild.lastChild; + } else if (prev.classList.contains('jdropdown-item')) { + newIndex = prev.indexValue; + } else { + prev = null + } + } + + if (prev) { + newIndex = prev.indexValue; + } + } + } + } + + if (newIndex !== null) { + obj.setCursor(newIndex); + } + } + + obj.loadFirst = function() { + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + // Show 200 items at once + var number = results.length || 0; + + // Lazyloading + if (obj.options.lazyLoading == true && number > 200) { + number = 200; + } + + // Reset container + content.innerHTML = ''; + + // First 200 items + for (var i = 0; i < number; i++) { + if (results[i].group) { + if (! results[i].group.parentNode) { + content.appendChild(results[i].group); + } + results[i].group.lastChild.appendChild(results[i].element); + } else { + content.appendChild(results[i].element); + } + } + + // Scroll go to the begin + content.scrollTop = 0; + } + + obj.loadLast = function() { + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + // Show first page + var number = results.length; + + // Max 200 items + if (number > 200) { + number = number - 200; + + // Reset container + content.innerHTML = ''; + + // First 200 items + for (var i = number; i < results.length; i++) { + if (results[i].group) { + if (! results[i].group.parentNode) { + content.appendChild(results[i].group); + } + results[i].group.lastChild.appendChild(results[i].element); + } else { + content.appendChild(results[i].element); + } + } + + // Scroll go to the begin + content.scrollTop = content.scrollHeight; + } + } + + obj.loadUp = function() { + var test = false; + + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + var items = content.querySelectorAll('.jdropdown-item'); + var fistItem = items[0].indexValue; + fistItem = obj.items[fistItem]; + var index = results.indexOf(fistItem) - 1; + + if (index > 0) { + var number = 0; + + while (index > 0 && results[index] && number < 200) { + if (results[index].group) { + if (! results[index].group.parentNode) { + content.insertBefore(results[index].group, content.firstChild); + } + results[index].group.lastChild.insertBefore(results[index].element, results[index].group.lastChild.firstChild); + } else { + content.insertBefore(results[index].element, content.firstChild); + } + + index--; + number++; + } + + // New item added + test = true; + } + + return test; + } + + obj.loadDown = function() { + var test = false; + + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + var items = content.querySelectorAll('.jdropdown-item'); + var lastItem = items[items.length-1].indexValue; + lastItem = obj.items[lastItem]; + var index = results.indexOf(lastItem) + 1; + + if (index < results.length) { + var number = 0; + while (index < results.length && results[index] && number < 200) { + if (results[index].group) { + if (! results[index].group.parentNode) { + content.appendChild(results[index].group); + } + results[index].group.lastChild.appendChild(results[index].element); + } else { + content.appendChild(results[index].element); + } + + index++; + number++; + } + + // New item added + test = true; + } + + return test; + } + + init(); + + return obj; +}); + +jSuites.dropdown.keydown = function(e) { + var dropdown = null; + if (dropdown = jSuites.dropdown.current) { + if (e.which == 13 || e.which == 9) { // enter or tab + if (dropdown.header.value && dropdown.currentIndex == null && dropdown.options.newOptions) { + // if they typed something in, but it matched nothing, and newOptions are allowed, start that flow + dropdown.add(); + } else { + // Quick Select/Filter + if (dropdown.currentIndex == null && dropdown.options.autocomplete == true && dropdown.header.value != "") { + dropdown.find(dropdown.header.value); + } + dropdown.selectIndex(dropdown.currentIndex); + } + } else if (e.which == 38) { // up arrow + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex > 0) { + dropdown.prev(); + } + e.preventDefault(); + } else if (e.which == 40) { // down arrow + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex + 1 < dropdown.items.length) { + dropdown.next(); + } + e.preventDefault(); + } else if (e.which == 36) { + dropdown.first(); + if (! e.target.classList.contains('jdropdown-header')) { + e.preventDefault(); + } + } else if (e.which == 35) { + dropdown.last(); + if (! e.target.classList.contains('jdropdown-header')) { + e.preventDefault(); + } + } else if (e.which == 27) { + dropdown.close(); + } else if (e.which == 33) { // page up + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex > 0) { + for (var i = 0; i < 7; i++) { + dropdown.prev() + } + } + e.preventDefault(); + } else if (e.which == 34) { // page down + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex + 1 < dropdown.items.length) { + for (var i = 0; i < 7; i++) { + dropdown.next() + } + } + e.preventDefault(); + } + } +} + +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(); + } + } +} + +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 }; +} + +jSuites.editor = (function(el, options) { + var obj = {}; + obj.options = {}; + + // 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, + // Placeholder + placeholder: null, + // Parse URL + parseURL: false, + filterPaste: true, + // Accept drop files + dropZone: false, + dropAsSnippet: false, + acceptImages: false, + acceptFiles: false, + maxFileSize: 5000000, + allowImageResize: true, + // Style + border: true, + padding: true, + maxHeight: null, + height: 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; + var files = []; + + // Make sure element is empty + el.innerHTML = ''; + + // Keep the reference for the container + obj.el = el; + + 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'; + + // Placeholder + if (obj.options.placeholder) { + editor.setAttribute('data-placeholder', obj.options.placeholder); + } + + // Max height + if (obj.options.maxHeight || obj.options.height) { + editor.style.overflowY = 'auto'; + + if (obj.options.maxHeight) { + editor.style.maxHeight = obj.options.maxHeight; + } + if (obj.options.height) { + editor.style.height = obj.options.height; + } + } + + // Set editor initial value + if (obj.options.value) { + var value = obj.options.value; + } else { + var value = el.innerHTML ? el.innerHTML : ''; + } + + if (! value) { + var value = ''; + } + + /** + * Onchange event controllers + */ + var change = function(e) { + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, obj, e); + } + + // Update value + obj.options.value = obj.getData(); + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + /** + * 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); + } + } + } + + var updateTotalImages = function() { + var o = null; + if (o = snippet.children[0]) { + // Make sure is a grid + if (! o.classList.contains('jslider-grid')) { + o.classList.add('jslider-grid'); + } + // Quantify of images + var number = o.children.length; + // Set the configuration of the grid + o.setAttribute('data-number', number > 4 ? 4 : number); + // Total of images inside the grid + if (number > 4) { + o.setAttribute('data-total', number - 4); + } else { + o.removeAttribute('data-total'); + } + } + } + + /** + * Append image to the snippet + */ + var appendImage = function(image) { + if (! snippet.innerHTML) { + appendElement({}); + } + snippet.children[0].appendChild(image); + updateTotalImages(); + } + + /** + * Append snippet + * @Param object data + */ + var appendElement = function(data) { + // Reset snippet + snippet.innerHTML = ''; + + // Attributes + var a = [ 'image', 'title', 'description', 'host', 'url' ]; + + for (var i = 0; i < a.length; i++) { + var div = document.createElement('div'); + div.className = 'jsnippet-' + a[i]; + div.setAttribute('data-k', a[i]); + snippet.appendChild(div); + if (data[a[i]]) { + if (a[i] == 'image') { + if (! Array.isArray(data.image)) { + data.image = [ data.image ]; + } + for (var j = 0; j < data.image.length; j++) { + var img = document.createElement('img'); + img.src = data.image[j]; + div.appendChild(img); + } + } else { + div.innerHTML = data[a[i]]; + } + } + } + + editor.appendChild(document.createElement('br')); + editor.appendChild(snippet); + } + + var verifyEditor = function() { + clearTimeout(editorTimer); + editorTimer = setTimeout(function() { + var snippet = editor.querySelector('.jsnippet'); + if (! snippet) { + var html = editor.innerHTML.replace(/\n/g, ' '); + var container = document.createElement('div'); + container.innerHTML = html; + 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') { + obj.addImage(url[0], true); + } 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; + } + // Host + if (result.host) { + p.host = result.host; + } + // Url + if (result.url) { + p.url = result.url; + } + // Append snippet + appendElement(p); + // Add image + if (result.image) { + obj.addImage(result.image, true); + } else if (result['og:image']) { + obj.addImage(result['og:image'], true); + } + } + }); + } + } + + /** + * Set editor value + */ + obj.setData = function(html) { + editor.innerHTML = html; + + if (obj.options.focus) { + jSuites.editor.setCursor(editor, true); + } + + // Reset files container + files = []; + } + + obj.getFiles = function() { + var f = editor.querySelectorAll('.jfile'); + var d = []; + for (var i = 0; i < f.length; i++) { + if (files[f[i].src]) { + d.push(files[f[i].src]); + } + } + return d; + } + + obj.getText = function() { + return editor.innerText; + } + + /** + * Get editor data + */ + obj.getData = function(json) { + if (! json) { + var data = editor.innerHTML; + } else { + var data = { + content : '', + } + + // Get snippet + 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') { + if (! data.snippet.image) { + data.snippet.image = []; + } + // Get all images + for (var j = 0; j < snippet.children[i].children.length; j++) { + data.snippet.image.push(snippet.children[i].children[j].getAttribute('src')) + } + } else { + data.snippet[key] = snippet.children[i].innerHTML; + } + } + } + } + + // Get files + var f = Object.keys(files); + if (f.length) { + data.files = []; + for (var i = 0; i < f.length; i++) { + data.files.push(files[f[i]]); + } + } + + // Get content + var text = editor.innerHTML; + text = text.replace(/
/g, "\n"); + text = text.replace(/<\/div>/g, "<\/div>\n"); + text = text.replace(/<(?:.|\n)*?>/gm, ""); + data.content = text.trim(); + } + + return data; + } + + // Reset + obj.reset = function() { + editor.innerHTML = ''; + snippet.innerHTML = ''; + files = []; + } + + 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.title = data.name; + newImage.className = 'jfile pdf'; + + files[newImage.src] = { + file: newImage.src, + extension: 'pdf', + content: data.result, + } + + insertNodeAtCaret(newImage); + }); + } + } + + obj.addImage = function(src, asSnippet) { + if (! src) { + 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 newImage = document.createElement('img'); + newImage.src = window.URL.createObjectURL(blob); + newImage.classList.add('jfile'); + newImage.setAttribute('tabindex', '900'); + files[newImage.src] = { + file: newImage.src, + extension: extension, + content: canvas.toDataURL(), + } + + if (obj.options.dropAsSnippet || asSnippet) { + appendImage(newImage); + // Just to understand the attachment is part of a snippet + files[newImage.src].snippet = true; + } else { + insertNodeAtCaret(newImage); + } + + 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); + } + }, 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) { + if (editorAction && editorAction.e) { + editorAction.e.classList.remove('resizing'); + } + + 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.width) { + e.target.width = rect.width + 'px'; + } + + if (! e.target.height) { + e.target.height = rect.height + 'px'; + } + + var s = window.getSelection(); + if (s.rangeCount) { + for (var i = 0; i < s.rangeCount; i++) { + s.removeRange(s.getRangeAt(i)); + } + } + + e.target.classList.add('resizing'); + } 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' && ! e.target.parentNode.classList.contains('jsnippet-image') && 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.width = (editorAction.w + (e.clientX - editorAction.x)); + + if (e.shiftKey) { + var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w); + editorAction.e.height = editorAction.h + newHeight; + } else { + var newHeight = null; + } + } + + if (! newHeight) { + if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') { + if (! e.shiftKey) { + editorAction.e.height = editorAction.h + (e.clientY - editorAction.y); + } + } + } + } + } + + var editorKeyUp = function(e) { + if (! editor.innerHTML) { + editor.innerHTML = '

'; + } + + if (typeof(obj.options.onkeyup) == 'function') { + obj.options.onkeyup(el, obj, 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); + } + + if (e.key == 'Delete') { + if (e.target.tagName == 'IMG' && e.target.parentNode.classList.contains('jsnippet-image')) { + e.target.remove(); + updateTotalImages(); + } + } + } + + // Elements to be removed + var remove = [HTMLUnknownElement,HTMLAudioElement,HTMLEmbedElement,HTMLIFrameElement,HTMLTextAreaElement,HTMLInputElement,HTMLScriptElement]; + + // Valid properties + var validProperty = ['width', 'height', 'align', 'border', 'src', 'tabindex']; + + // Valid CSS attributes + var validStyle = ['color', 'font-weight', 'font-size', 'background', 'background-color', 'margin']; + + var parse = function(element) { + // Remove attributes + if (element.attributes && element.attributes.length) { + var image = null; + var style = null; + // Process style attribute + var elementStyle = element.getAttribute('style'); + if (elementStyle) { + style = []; + var t = elementStyle.split(';'); + for (var j = 0; j < t.length; j++) { + var v = t[j].trim().split(':'); + if (validStyle.indexOf(v[0].trim()) >= 0) { + var k = v.shift(); + var v = v.join(':'); + style.push(k + ':' + v); + } + } + } + // Process image + if (element.tagName.toUpperCase() == 'IMG') { + if (! obj.options.acceptImages || ! element.src) { + element.parentNode.removeChild(element); + } else { + // Check if is data + element.setAttribute('tabindex', '900'); + // Check attributes for persistance + obj.addImage(element.src); + } + } + // Remove attributes + var attr = []; + var numAttributes = element.attributes.length - 1; + if (numAttributes > 0) { + for (var i = numAttributes; i >= 0 ; i--) { + attr.push(element.attributes[i].name); + } + attr.forEach(function(v) { + if (validProperty.indexOf(v) == -1) { + element.removeAttribute(v); + } + }); + } + element.style = ''; + // Add valid style + if (style && style.length) { + element.setAttribute('style', style.join(';')); + } + } + // Parse children + if (element.children.length) { + for (var i = 0; i < element.children.length; i++) { + parse(element.children[i]); + } + } + + if (remove.indexOf(element.constructor) >= 0) { + element.remove(); + } + } + + var filter = function(data) { + if (data) { + data = data.replace(new RegExp('', 'gsi'), ''); + } + var parser = new DOMParser(); + var d = parser.parseFromString(data, "text/html"); + parse(d); + var span = document.createElement('span'); + span.innerHTML = d.firstChild.innerHTML; + return span; + } + + var editorPaste = function(e) { + if (obj.options.filterPaste == true) { + 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 { + if (! html) { + html = text.split('\r\n'); + if (! e.target.innerText) { + html.map(function(v) { + var d = document.createElement('div'); + d.innerText = v; + editor.appendChild(d); + }); + } else { + html = html.map(function(v) { + return '
' + v + '
'; + }); + document.execCommand('insertHtml', false, html.join('')); + } + } else { + var d = filter(html); + // Paste to the editor + insertNodeAtCaret(d); + } + } + + 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'); + e.preventDefault(); + } + } + + 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); + e.preventDefault(); + } + } + + 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) { + // Blur + if (typeof(obj.options.onblur) == 'function') { + obj.options.onblur(el, obj, e); + } + + change(e); + } + + var editorFocus = function(e) { + // Focus + if (typeof(obj.options.onfocus) == 'function') { + 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); + editor.addEventListener('focus', editorFocus); + editor.addEventListener('blur', editorBlur); + + // 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) { + // Append to the DOM + el.appendChild(toolbar); + // Create toolbar + jSuites.toolbar(toolbar, { + container: true, + responsive: true, + items: obj.options.toolbar + }); + } + + // Focus to the editor + if (obj.options.focus) { + jSuites.editor.setCursor(editor, obj.options.focus == 'initial' ? true : false); + } + + // Change method + el.change = obj.setData; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + // Data type + var o = el.getAttribute('data-html') === 'true' ? false : true; + return obj.getData(o); + } else { + obj.setData(val); + } + } + + 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.focus = function(el) { + if (el.innerText.length) { + var range = document.createRange(); + var sel = window.getSelection(); + var node = el.childNodes[el.childNodes.length-1]; + range.setStart(node, node.length) + range.collapse(true) + sel.removeAllRanges() + sel.addRange(range) + el.scrollLeft = el.scrollWidth; + } +} + +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.getNode = function() { + var node = document.getSelection().anchorNode; + if (node) { + return (node.nodeType == 3 ? node.parentNode : node); + } else { + return null; + } +} +/** + * Generate hash from a string + */ +jSuites.hash = 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); + if (chr > 32) { + hash = ((hash << 5) - hash) + chr; + hash |= 0; + } + } + } + return hash; +} + +/** + * Generate a random color + */ +jSuites.randomColor = function(h) { + var lum = -0.25; + var hex = String('#' + Math.random().toString(16).slice(2, 8).toUpperCase()).replace(/[^0-9a-f]/gi, ''); + if (hex.length < 6) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + var rgb = [], c, i; + for (i = 0; i < 3; i++) { + c = parseInt(hex.substr(i * 2, 2), 16); + c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); + rgb.push(("00" + c).substr(c.length)); + } + + // Return hex + if (h == true) { + return '#' + jSuites.two(rgb[0].toString(16)) + jSuites.two(rgb[1].toString(16)) + jSuites.two(rgb[2].toString(16)); + } + + return rgb; +} + +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 = jSuites.upload = (function(el, options) { + var obj = {}; + obj.options = {}; + + // Default configuration + var defaults = { + type: 'image', + extension: '*', + input: false, + minWidth: false, + maxWidth: null, + maxHeight: null, + maxJpegSizeBytes: null, // For example, 350Kb would be 350000 + onchange: null, + multiple: false, + remoteParser: null, + text:{ + extensionNotAllowed:'The extension is not allowed', + } + }; + + // 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]; + } + } + + // Multiple + if (obj.options.multiple == true) { + el.setAttribute('data-multiple', true); + } + + // Container + el.content = []; + + // Upload icon + el.classList.add('jupload'); + + if (obj.options.input == true) { + el.classList.add('input'); + } + + obj.add = function(data) { + // Reset container for single files + if (obj.options.multiple == false) { + el.content = []; + el.innerText = ''; + } + + // Append to the element + if (obj.options.type == 'image') { + var img = document.createElement('img'); + img.setAttribute('src', data.file); + img.setAttribute('tabindex', -1); + if (! el.getAttribute('name')) { + img.className = 'jfile'; + img.content = data; + } + el.appendChild(img); + } else { + if (data.name) { + var name = data.name; + } else { + var name = data.file; + } + var div = document.createElement('div'); + div.innerText = name || obj.options.type; + div.classList.add('jupload-item'); + div.setAttribute('tabindex', -1); + el.appendChild(div); + } + + if (data.content) { + data.file = jSuites.guid(); + } + + // Push content + el.content.push(data); + + // Onchange + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, data); + } + } + + obj.addFromFile = function(file) { + var type = file.type.split('/'); + if (type[0] == obj.options.type) { + var readFile = new FileReader(); + readFile.addEventListener("load", function (v) { + var data = { + file: v.srcElement.result, + extension: file.name.substr(file.name.lastIndexOf('.') + 1), + name: file.name, + size: file.size, + lastmodified: file.lastModified, + content: v.srcElement.result, + } + + obj.add(data); + }); + + readFile.readAsDataURL(file); + } else { + alert(obj.options.text.extensionNotAllowed); + } + } + + 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('/'); + var type = extension[0].replace('data:',''); + if (type == obj.options.type) { + var data = { + file: src, + name: '', + extension: extension[1], + content: src, + } + obj.add(data); + } else { + alert(obj.options.text.extensionNotAllowed); + } + } else { + var extension = src.substr(src.lastIndexOf('.') + 1); + // Work for cross browsers + src = obj.options.remoteParser + src; + // Get remove content + jSuites.ajax({ + url: src, + type: 'GET', + dataType: 'blob', + success: function(data) { + //add(extension[0].replace('data:',''), data); + } + }) + } + } + } + + var 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 mime = obj.options.type + '/' + obj.options.extension; + var input = document.createElement('input'); + input.type = 'file'; + input.setAttribute('accept', mime); + input.onchange = function() { + for (var i = 0; i < this.files.length; i++) { + obj.addFromFile(this.files[i]); + } + } + + // Allow multiple files + if (obj.options.multiple == true) { + input.setAttribute('multiple', true); + } + + var current = null; + + el.addEventListener("click", function(e) { + current = null; + if (! el.children.length || e.target === el) { + jSuites.click(input); + } else { + if (e.target.parentNode == el) { + current = e.target; + } + } + }); + + el.addEventListener("dblclick", function(e) { + jSuites.click(input); + }); + + 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('keydown', function(e) { + if (current && e.which == 46) { + var index = Array.prototype.indexOf.call(el.children, current); + if (index >= 0) { + el.content.splice(index, 1); + current.remove(); + current = null; + } + } + }); + + 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.multiple == false) { + el.innerText = ''; + } + + // 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.val = function(val) { + if (val === undefined) { + return el.content && el.content.length ? el.content : null; + } else { + // Reset + el.innerText = ''; + el.content = []; + + if (val) { + if (Array.isArray(val)) { + for (var i = 0; i < val.length; i++) { + if (typeof(val[i]) == 'string') { + obj.add({ file: val[i] }); + } else { + obj.add(val[i]); + } + } + } else if (typeof(val) == 'string') { + obj.add({ file: val }); + } + } + } + } + + el.upload = el.image = obj; + + return obj; +}); + +jSuites.image.create = function(data) { + var img = document.createElement('img'); + img.setAttribute('src', data.file); + img.className = 'jfile'; + img.setAttribute('tabindex', -1); + img.content = data; + + return img; +} + + +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 event = false; + 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); + } + event = true; + } + } else if (el.scrollTop <= el.clientHeight) { + if (options.loadUp()) { + if (scrollTop == el.scrollTop) { + el.scrollTop = el.scrollTop + (el.clientHeight); + } + event = true; + } + } + + timeControlLoading = setTimeout(function() { + timeControlLoading = null; + }, options.timer); + + if (event) { + if (typeof(options.onupdate) == 'function') { + options.onupdate(); + } + } + } + } + + // 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 && loading.parentNode) { + document.body.removeChild(loading); + } + } + + return obj; +})(); + +jSuites.mask = (function() { + // Currency + var tokens = { + // Currency tokens + currency: [ '#(.{1})##0?(.{1}0+)?( ?;(.*)?)?', '#' ], + // Percentage + percentage: [ '0{1}(.{1}0+)?%' ], + // Number + numeric: [ '0{1}(.{1}0+)?' ], + // Data tokens + datetime: [ 'YYYY', 'YYY', 'YY', 'MMMMM', 'MMMM', 'MMM', 'MM', 'DDDDD', 'DDDD', 'DDD', 'DD', 'DY', 'DAY', 'WD', 'D', 'Q', 'HH24', 'HH12', 'HH', '\\[H\\]', 'H', 'AM/PM', 'PM', 'AM', 'MI', 'SS', 'MS', 'MONTH', 'MON', 'Y', 'M' ], + // Other + general: [ 'A', '0', '[0-9a-zA-Z\$]+', '.'] + } + + var getDate = function() { + if (this.mask.toLowerCase().indexOf('[h]') !== -1) { + var m = 0; + if (this.date[4]) { + m = parseFloat(this.date[4] / 60); + } + var v = parseInt(this.date[3]) + m; + v /= 24; + } else if (! (this.date[0] && this.date[1] && this.date[2]) && (this.date[3] || this.date[4])) { + v = jSuites.two(this.date[3]) + ':' + jSuites.two(this.date[4]) + ':' + jSuites.two(this.date[5]) + } else { + if (this.date[0] && this.date[1] && ! this.date[2]) { + this.date[2] = 1; + } + v = jSuites.two(this.date[0]) + '-' + jSuites.two(this.date[1]) + '-' + jSuites.two(this.date[2]); + + if (this.date[3] || this.date[4] || this.date[5]) { + v += ' ' + jSuites.two(this.date[3]) + ':' + jSuites.two(this.date[4]) + ':' + jSuites.two(this.date[5]); + } + } + + return v; + } + + var isBlank = function(v) { + return v === null || v === '' || v === undefined ? true : false; + } + + var isFormula = function(value) { + return (''+value).chartAt(0) == '='; + } + + var isNumeric = function(t) { + return t === 'currency' || t === 'percentage' || t === 'numeric' ? true : false; + } + /** + * Get the decimal defined in the mask configuration + */ + var getDecimal = function(v) { + if (v && Number(v) == v) { + return '.'; + } else { + if (this.options.decimal) { + return this.options.decimal; + } else { + if (this.locale) { + var t = Intl.NumberFormat(this.locale).format(1.1); + return this.options.decimal = t[1]; + } else { + if (! v) { + v = this.mask; + } + var e = new RegExp('0{1}(.{1})0+', 'ig'); + var t = e.exec(v); + if (t && t[1] && t[1].length == 1) { + // Save decimal + this.options.decimal = t[1]; + // Return decimal + return t[1]; + } else { + // Did not find any decimal last resort the default + var e = new RegExp('#,##', 'ig'); + if ((v && v.match(e)) || '1.1'.toLocaleString().substring(1,2) == '.') { + this.options.decimal = '.'; + } else { + this.options.decimal = ','; + } + } + } + } + } + + if (this.options.decimal) { + return this.options.decimal; + } else { + return null; + } + } + + var ParseValue = function(v, decimal) { + if (v == '') { + return ''; + } + + // Get decimal + if (! decimal) { + decimal = getDecimal.call(this); + } + + // New value + v = (''+v).split(decimal); + v[0] = v[0].match(/[\-0-9]+/g, ''); + if (v[0]) { + v[0] = v[0].join(''); + } + if (v[0] || v[1]) { + if (v[1] !== undefined) { + v[1] = v[1].match(/[0-9]+/g, ''); + if (v[1]) { + v[1] = v[1].join(''); + } else { + v[1] = ''; + } + } + } else { + return ''; + } + + return v; + } + + var FormatValue = function(v) { + if (v == '') { + return ''; + } + // Get decimal + var d = getDecimal.call(this); + // Convert value + var o = Object.create(this.options || {}); + if (! o.minimumFractionDigits) { + o.minimumFractionDigits = 1; + } + // Parse value + v = ParseValue.call(this, v); + if (v == '') { + return ''; + } + // Temporary value + if (v[0]) { + var t = parseFloat(v.join('.')); + if (o.style == 'percent') { + t /= 100; + } + } else { + var t = null; + } + var n = new Intl.NumberFormat(this.locale, o).format(t); + n = n.split(d); + var s = n[1].replace(/[0-9]*/g, ''); + if (s) { + n[2] = s; + } + if (v[1] !== undefined) { + n[1] = d + v[1]; + } else { + n[1] = ''; + } + + return n.join(''); + } + + var Format = function(e) { + var v = Value.call(e); + if (! v) { + return; + } + + // Get decimal + var d = getDecimal.call(this); + var n = FormatValue.call(this, v); + var t = (n.length) - v.length; + var index = Caret.call(e) + t; + // Set value and update caret + Value.call(e, n, index, true); + } + + var Extract = function(v) { + // Keep the raw value + var current = ParseValue.call(this, v); + if (current) { + return parseFloat(current.join('.')); + } + return null; + } + + /** + * Caret getter and setter methods + */ + var Caret = function(index, adjustNumeric) { + if (index === undefined) { + if (this.tagName == 'DIV') { + var pos = 0; + var s = window.getSelection(); + if (s) { + if (s.rangeCount !== 0) { + var r = s.getRangeAt(0); + var p = r.cloneRange(); + p.selectNodeContents(this); + p.setEnd(r.endContainer, r.endOffset); + pos = p.toString().length; + } + } + return pos; + } else { + return this.selectionStart; + } + } else { + // Get the current value + var n = Value.call(this); + + // Review the position + if (adjustNumeric) { + var p = null; + for (var i = 0; i < n.length; i++) { + if (n[i].match(/[\-0-9]/g) || n[i] == '.' || n[i] == ',') { + p = i; + } + } + + // If the string has no numbers + if (p === null) { + p = n.indexOf(' '); + } + + if (index >= p) { + index = p + 1; + } + } + + // Do not update caret + if (index > n.length) { + index = n.length; + } + + if (index) { + // Set caret + if (this.tagName == 'DIV') { + var s = window.getSelection(); + var r = document.createRange(); + r.setStart(this.childNodes[0], index); + s.removeAllRanges(); + s.addRange(r); + } else { + this.selectionStart = index; + this.selectionEnd = index; + } + } + } + } + + /** + * Value getter and setter method + */ + var Value = function(v, updateCaret, adjustNumeric) { + if (this.tagName == 'DIV') { + if (v === undefined) { + return this.innerText; + } else { + if (this.innerText !== v) { + this.innerText = v; + + if (updateCaret) { + Caret.call(this, updateCaret, adjustNumeric); + } + } + } + } else { + if (v === undefined) { + return this.value; + } else { + if (this.value !== v) { + this.value = v; + if (updateCaret) { + Caret.call(this, updateCaret, adjustNumeric); + } + } + } + } + } + + // Labels + var weekDaysFull = jSuites.calendar.weekdays; + var weekDays = jSuites.calendar.weekdaysShort; + var monthsFull = jSuites.calendar.months; + var months = jSuites.calendar.monthsShort; + + var parser = { + 'YEAR': function(v, s) { + var y = ''+new Date().getFullYear(); + + if (typeof(this.values[this.index]) === 'undefined') { + this.values[this.index] = ''; + } + if (parseInt(v) >= 0 && parseInt(v) <= 10) { + if (this.values[this.index].length < s) { + this.values[this.index] += v; + } + } + if (this.values[this.index].length == s) { + if (s == 2) { + var y = y.substr(0,2) + this.values[this.index]; + } else if (s == 3) { + var y = y.substr(0,1) + this.values[this.index]; + } else if (s == 4) { + var y = this.values[this.index]; + } + this.date[0] = y; + this.index++; + } + }, + 'YYYY': function(v) { + parser.YEAR.call(this, v, 4); + }, + 'YYY': function(v) { + parser.YEAR.call(this, v, 3); + }, + 'YY': function(v) { + parser.YEAR.call(this, v, 2); + }, + 'FIND': function(v, a) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } + var pos = 0; + var count = 0; + var value = (this.values[this.index] + v).toLowerCase(); + for (var i = 0; i < a.length; i++) { + if (a[i].toLowerCase().indexOf(value) == 0) { + pos = i; + count++; + } + } + if (count > 1) { + this.values[this.index] += v; + } else if (count == 1) { + this.values[this.index] = a[pos]; + this.index++; + + return pos; + } + }, + 'MMM': function(v) { + var ret = parser.FIND.call(this, v, months); + if (ret !== undefined) { + this.date[1] = ret + 1; + } + }, + 'MMMM': function(v) { + var ret = parser.FIND.call(this, v, monthsFull); + if (ret !== undefined) { + this.date[1] = ret + 1; + } + }, + 'MMMMM': function(v) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } + var pos = 0; + var count = 0; + var value = (this.values[this.index] + v).toLowerCase(); + for (var i = 0; i < monthsFull.length; i++) { + if (monthsFull[i][0].toLowerCase().indexOf(value) == 0) { + this.values[this.index] = monthsFull[i][0]; + this.date[1] = i + 1; + this.index++; + break; + } + } + }, + 'MM': function(v) { + if (isBlank(this.values[this.index])) { + if (parseInt(v) > 1 && parseInt(v) < 10) { + this.date[1] = this.values[this.index] = '0' + v; + this.index++; + } else if (parseInt(v) < 2) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 1 && parseInt(v) < 3) { + this.date[1] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0 && parseInt(v) < 10) { + this.date[1] = this.values[this.index] += v; + this.index++; + } + } + }, + 'M': function(v) { + var test = false; + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = v; + if (v > 1) { + this.date[1] = this.values[this.index]; + this.index++; + } + } else { + if (this.values[this.index] == 1 && parseInt(v) < 3) { + this.date[1] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0) { + this.date[1] = this.values[this.index] += v; + this.index++; + } else { + var test = true; + } + } + } else { + var test = true; + } + + // Re-test + if (test == true) { + var t = parseInt(this.values[this.index]); + if (t > 0 && t < 12) { + this.date[2] = this.values[this.index]; + this.index++; + // Repeat the character + this.position--; + } + } + }, + 'D': function(v) { + var test = false; + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = v; + if (parseInt(v) > 3) { + this.date[2] = this.values[this.index]; + this.index++; + } + } else { + if (this.values[this.index] == 3 && parseInt(v) < 2) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 1 || this.values[this.index] == 2) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else { + var test = true; + } + } + } else { + var test = true; + } + + // Re-test + if (test == true) { + var t = parseInt(this.values[this.index]); + if (t > 0 && t < 32) { + this.date[2] = this.values[this.index]; + this.index++; + // Repeat the character + this.position--; + } + } + }, + 'DD': function(v) { + if (isBlank(this.values[this.index])) { + if (parseInt(v) > 3 && parseInt(v) < 10) { + this.date[2] = this.values[this.index] = '0' + v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 3 && parseInt(v) < 2) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if ((this.values[this.index] == 1 || this.values[this.index] == 2) && parseInt(v) < 10) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0 && parseInt(v) < 10) { + this.date[2] = this.values[this.index] += v; + this.index++; + } + } + }, + 'DDD': function(v) { + parser.FIND.call(this, v, weekDays); + }, + 'DDDD': function(v) { + parser.FIND.call(this, v, weekDaysFull); + }, + 'HH12': function(v, two) { + if (isBlank(this.values[this.index])) { + if (parseInt(v) > 1 && parseInt(v) < 10) { + if (two) { + v = 0 + v; + } + this.date[3] = this.values[this.index] = v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 1 && parseInt(v) < 3) { + this.date[3] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] < 1 && parseInt(v) < 10) { + this.date[3] = this.values[this.index] += v; + this.index++; + } + } + }, + 'HH24': function(v, two) { + var test = false; + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (this.values[this.index] == null || this.values[this.index] == '') { + if (parseInt(v) > 2 && parseInt(v) < 10) { + if (two) { + v = 0 + v; + } + this.date[3] = this.values[this.index] = v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 2 && parseInt(v) < 4) { + this.date[3] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] < 2 && parseInt(v) < 10) { + this.date[3] = this.values[this.index] += v; + this.index++; + } + } + } + }, + 'HH': function(v) { + parser['HH24'].call(this, v, 1); + }, + 'H': function(v) { + parser['HH24'].call(this, v, 0); + }, + '\\[H\\]': function(v) { + if (this.values[this.index] == undefined) { + this.values[this.index] = ''; + } + if (v.match(/[0-9]/g)) { + this.date[3] = this.values[this.index] += v; + } else { + if (this.values[this.index].match(/[0-9]/g)) { + this.date[3] = this.values[this.index]; + this.index++; + // Repeat the character + this.position--; + } + } + }, + 'N60': function(v, i) { + if (this.values[this.index] == null || this.values[this.index] == '') { + if (parseInt(v) > 5 && parseInt(v) < 10) { + this.date[i] = this.values[this.index] = '0' + v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (parseInt(v) < 10) { + this.date[i] = this.values[this.index] += v; + this.index++; + } + } + }, + 'MI': function(v) { + parser.N60.call(this, v, 4); + }, + 'SS': function(v) { + parser.N60.call(this, v, 5); + }, + 'AM/PM': function(v) { + this.values[this.index] = ''; + if (v) { + if (this.date[3] > 12) { + this.values[this.index] = 'PM'; + } else { + this.values[this.index] = 'AM'; + } + } + this.index++; + }, + 'WD': function(v) { + if (typeof(this.values[this.index]) === 'undefined') { + this.values[this.index] = ''; + } + if (parseInt(v) >= 0 && parseInt(v) < 7) { + this.values[this.index] = v; + } + if (this.value[this.index].length == 1) { + this.index++; + } + }, + '0{1}(.{1}0+)?': function(v) { + // Get decimal + var decimal = getDecimal.call(this); + // Negative number + var neg = false; + // Create if is blank + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } else { + if (this.values[this.index] == '-') { + neg = true; + } + } + var current = ParseValue.call(this, this.values[this.index], decimal); + if (current) { + this.values[this.index] = current.join(decimal); + } + // New entry + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (this.values[this.index] != '0' || v == decimal) { + this.values[this.index] += v; + } + } else if (decimal && v == decimal) { + if (this.values[this.index].indexOf(decimal) == -1) { + if (! this.values[this.index]) { + this.values[this.index] = '0'; + } + this.values[this.index] += v; + } + } else if (v == '-') { + // Negative signed + neg = true; + } + + if (neg === true && this.values[this.index][0] !== '-') { + this.values[this.index] = '-' + this.values[this.index]; + } + }, + '0{1}(.{1}0+)?%': function(v) { + parser['0{1}(.{1}0+)?'].call(this, v); + + if (this.values[this.index].match(/[\-0-9]/g)) { + if (this.values[this.index] && this.values[this.index].indexOf('%') == -1) { + this.values[this.index] += '%'; + } + } else { + this.values[this.index] = ''; + } + }, + '#(.{1})##0?(.{1}0+)?( ?;(.*)?)?': function(v) { + // Parse number + parser['0{1}(.{1}0+)?'].call(this, v); + // Get decimal + var decimal = getDecimal.call(this); + // Get separator + var separator = this.tokens[this.index].substr(1,1); + // Negative + var negative = this.values[this.index][0] === '-' ? true : false; + // Current value + var current = ParseValue.call(this, this.values[this.index], decimal); + + // Get main and decimal parts + if (current !== '') { + // Format number + var n = current[0].match(/[0-9]/g); + if (n) { + // Format + n = n.join(''); + var t = []; + var s = 0; + for (var j = n.length - 1; j >= 0 ; j--) { + t.push(n[j]); + s++; + if (! (s % 3)) { + t.push(separator); + } + } + t = t.reverse(); + current[0] = t.join(''); + if (current[0].substr(0,1) == separator) { + current[0] = current[0].substr(1); + } + } else { + current[0] = ''; + } + + // Value + this.values[this.index] = current.join(decimal); + + // Negative + if (negative) { + this.values[this.index] = '-' + this.values[this.index]; + } + } + }, + '0': function(v) { + if (v.match(/[0-9]/g)) { + this.values[this.index] = v; + this.index++; + } + }, + '[0-9a-zA-Z$]+': function(v) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } + var t = this.tokens[this.index]; + var s = this.values[this.index]; + var i = s.length; + + if (t[i] == v) { + this.values[this.index] += v; + + if (this.values[this.index] == t) { + this.index++; + } + } else { + this.values[this.index] = t; + this.index++; + + if (v.match(/[\-0-9]/g)) { + // Repeat the character + this.position--; + } + } + }, + 'A': function(v) { + if (v.match(/[a-zA-Z]/gi)) { + this.values[this.index] = v; + this.index++; + } + }, + '.': function(v) { + parser['[0-9a-zA-Z$]+'].call(this, v); + } + } + + /** + * Get the tokens in the mask string + */ + var getTokens = function(str) { + if (this.type == 'general') { + var t = [].concat(tokens.general); + } else { + var t = [].concat(tokens.currency, tokens.datetime, tokens.percentage, tokens.numeric, tokens.general); + } + // Expression to extract all tokens from the string + var e = new RegExp(t.join('|'), 'gi'); + // Extract + return str.match(e); + } + + /** + * Get the method of one given token + */ + var getMethod = function(str) { + if (! this.type) { + var types = Object.keys(tokens); + } else if (this.type == 'general') { + var types = [ 'general' ]; + } else if (this.type == 'datetime') { + var types = [ 'numeric', 'datetime', 'general' ]; + } else { + var types = [ 'currency', 'percentage', 'numeric', 'general' ]; + } + + // Found + for (var i = 0; i < types.length; i++) { + var type = types[i]; + for (var j = 0; j < tokens[type].length; j++) { + var e = new RegExp(tokens[type][j], 'gi'); + var r = str.match(e); + if (r) { + return { type: type, method: tokens[type][j] } + } + } + } + } + + /** + * Identify each method for each token + */ + var getMethods = function(t) { + var result = []; + for (var i = 0; i < t.length; i++) { + var m = getMethod.call(this, t[i]); + if (m) { + result.push(m.method); + } else { + result.push(null); + } + } + + // Compatibility with excel + for (var i = 0; i < result.length; i++) { + if (result[i] == 'MM') { + // Not a month, correct to minutes + if (result[i-1] && result[i-1].indexOf('H') >= 0) { + result[i] = 'MI'; + } else if (result[i-2] && result[i-2].indexOf('H') >= 0) { + result[i] = 'MI'; + } else if (result[i+1] && result[i+1].indexOf('S') >= 0) { + result[i] = 'MI'; + } else if (result[i+2] && result[i+2].indexOf('S') >= 0) { + result[i] = 'MI'; + } + } + } + + return result; + } + + /** + * Get the type for one given token + */ + var getType = function(str) { + var m = getMethod.call(this, str); + if (m) { + var type = m.type; + } + + if (type) { + var numeric = 0; + // Make sure the correct type + var t = getTokens.call(this, str); + for (var i = 0; i < t.length; i++) { + m = getMethod.call(this, t[i]); + if (m && isNumeric(m.type)) { + numeric++; + } + } + if (numeric > 1) { + type = 'general'; + } + } + + return type; + } + + /** + * Parse character per character using the detected tokens in the mask + */ + var parse = function() { + // Parser method for this position + if (typeof(parser[this.methods[this.index]]) == 'function') { + parser[this.methods[this.index]].call(this, this.value[this.position]); + this.position++; + } else { + this.values[this.index] = this.tokens[this.index]; + this.index++; + } + } + + var isFormula = function(value) { + var v = (''+value)[0]; + return v == '=' ? true : false; + } + + var toPlainString = function(num) { + return (''+ +num).replace(/(-?)(\d*)\.?(\d*)e([+-]\d+)/, + function(a,b,c,d,e) { + return e < 0 + ? b + '0.' + Array(1-e-c.length).join(0) + c + d + : b + c + d + Array(e-d.length+1).join(0); + }); + } + + /** + * Mask function + * @param {mixed|string} JS input or a string to be parsed + * @param {object|string} When the first param is a string, the second is the mask or object with the mask options + */ + var obj = function(e, config, returnObject) { + // Options + var r = null; + var t = null; + var o = { + // Element + input: null, + // Current value + value: null, + // Mask options + options: {}, + // New values for each token found + values: [], + // Token position + index: 0, + // Character position + position: 0, + // Date raw values + date: [0,0,0,0,0,0], + // Raw number for the numeric values + number: 0, + } + + // This is a JavaScript Event + if (typeof(e) == 'object') { + // Element + o.input = e.target; + // Current value + o.value = Value.call(e.target); + // Current caret position + o.caret = Caret.call(e.target); + // Mask + if (t = e.target.getAttribute('data-mask')) { + o.mask = t; + } + // Type + if (t = e.target.getAttribute('data-type')) { + o.type = t; + } + // Options + if (e.target.mask) { + if (e.target.mask.options) { + o.options = e.target.mask.options; + } + if (e.target.mask.locale) { + o.locale = e.target.mask.locale; + } + } else { + // Locale + if (t = e.target.getAttribute('data-locale')) { + o.locale = t; + if (o.mask) { + o.options.style = o.mask; + } + } + } + // Extra configuration + if (e.target.attributes && e.target.attributes.length) { + for (var i = 0; i < e.target.attributes.length; i++) { + var k = e.target.attributes[i].name; + var v = e.target.attributes[i].value; + if (k.substr(0,4) == 'data') { + o.options[k.substr(5)] = v; + } + } + } + } else { + // Options + if (typeof(config) == 'string') { + // Mask + o.mask = config; + } else { + // Mask + var k = Object.keys(config); + for (var i = 0; i < k.length; i++) { + o[k[i]] = config[k[i]]; + } + } + + if (typeof(e) === 'number') { + // Get decimal + getDecimal.call(o, o.mask); + // Replace to the correct decimal + e = (''+e).replace('.', o.options.decimal); + } + + // Current + o.value = e; + + if (o.input) { + // Value + Value.call(o.input, e); + // Focus + jSuites.focus(o.input); + // Caret + o.caret = Caret.call(o.input); + } + } + + // Mask detected start the process + if (! isFormula(o.value) && (o.mask || o.locale)) { + // Compatibility ixes + if (o.mask) { + // Legacy + o.mask = o.mask.replace('[-]', ''); + // Excel mask TODO: Improve + if (o.mask.indexOf('##')) { + var d = o.mask.split(';'); + if (d[0]) { + d[0] = d[0].replace('*', ''); + d[0] = d[0].replace(/_/g, ''); + d[0] = d[0].replace(/-/g, ''); + d[0] = d[0].replace('(',''); + d[0] = d[0].replace(')',''); + d[0] = d[0].replace('##0.###','##0.000'); + d[0] = d[0].replace('##0.##','##0.00'); + d[0] = d[0].replace('##0.#','##0.0'); + } + o.mask = d[0]; + } + // Get type + if (! o.type) { + o.type = getType.call(o, o.mask); + } + // Get tokens + o.tokens = getTokens.call(o, o.mask); + } + // On new input + if (typeof(e) !== 'object' || ! e.inputType || e.inputType == 'insertText' || e.inputType == 'insertFromPaste') { + // Start tranformation + if (o.locale) { + if (o.input) { + Format.call(o, o.input); + } else { + var newValue = FormatValue.call(o, o.value); + } + } else { + // Get tokens + o.methods = getMethods.call(o, o.tokens); + // Go through all tokes + while (o.position < o.value.length && typeof(o.tokens[o.index]) !== 'undefined') { + // Get the approate parser + parse.call(o); + } + + if (isNumeric(o.type)) { + // Complement things in the end of the mask + while (typeof(o.tokens[o.index]) !== 'undefined') { + var t = getMethod.call(o, o.tokens[o.index]); + if (t && t.type == 'general') { + o.values[o.index] = o.tokens[o.index]; + } + o.index++; + } + + var adjustNumeric = true; + } else { + var adjustNumeric = false; + } + + // New value + var newValue = o.values.join(''); + + // Reset value + if (o.input) { + t = newValue.length - o.value.length; + if (t > 0) { + var caret = o.caret + t; + } else { + var caret = o.caret; + } + Value.call(o.input, newValue, caret, adjustNumeric); + } + } + } + + // Update raw data + if (o.input) { + var label = null; + if (isNumeric(o.type)) { + // Extract the number + o.number = Extract.call(o, Value.call(o.input)); + // Keep the raw data as a property of the tag + if (o.type == 'percentage') { + label = o.number / 100; + } else { + label = o.number; + } + } else if (o.type == 'datetime') { + label = getDate.call(o); + + if (o.date[0] && o.date[1] && o.date[2]) { + o.input.setAttribute('data-completed', true); + } + } + + if (label) { + o.input.setAttribute('data-value', label); + } + } + + if (newValue !== undefined) { + if (returnObject) { + return o; + } else { + return newValue; + } + } + } + } + + // Extract the tokens from a mask + obj.prepare = function(str, o) { + if (! o) { + o = {}; + } + return getTokens.call(o, str); + } + + /** + * Apply the mask to a element (legacy) + */ + obj.apply = function(e) { + var v = Value.call(e.target); + if (e.key.length == 1) { + v += e.key; + } + Value.call(e.target, obj(v, e.target.getAttribute('data-mask'))); + } + + /** + * Legacy support + */ + obj.run = function(value, mask, decimal) { + return obj(value, { mask, decimal }); + } + + /** + * Extract number from masked string + */ + obj.extract = function(v, options, returnObject) { + if (isBlank(v)) { + return v; + } + if (typeof(options) != 'object') { + return value; + } else { + if (! options.options) { + options.options = {}; + } + } + + // Compatibility + if (! options.mask && options.format) { + options.mask = options.format; + } + + // Get decimal + getDecimal.call(options, options.mask); + + var type = null; + if (options.type == 'percent' || options.options.style == 'percent') { + type = 'percentage'; + } else if (options.mask) { + type = getType.call(options, options.mask); + } + + + if (type === 'datetime') { + if (v instanceof Date) { + var t = jSuites.calendar.getDateString(value, options.mask); + } + + var o = obj(v, options, true); + var value = getDate.call(o); + if ((o.date[0] && o.date[1] && o.date[2]) && ! (o.date[3] || o.date[4] || o.date[5])) { + var t = jSuites.calendar.now(o.date); + value = jSuites.calendar.dateToNum(t); + } + } else { + var value = Extract.call(options, v); + // Percentage + if (type == 'percentage') { + value /= 100; + } + var o = options; + } + + o.value = value; + + if (returnObject) { + return o; + } else { + return value; + } + } + + /** + * Render + */ + obj.render = function(value, options, fullMask) { + if (isBlank(value)) { + return value; + } + + if (typeof(options) != 'object') { + return value; + } else { + if (! options.options) { + options.options = {}; + } + } + + // Compatibility + if (! options.mask && options.format) { + options.mask = options.format; + } + + var type = null; + if (options.type == 'percent' || options.options.style == 'percent') { + type = 'percentage'; + } else if (options.mask) { + type = getType.call(options, options.mask); + } else if (value instanceof Date) { + type = 'datetime'; + } + + // Fill with blanks + var fillWithBlanks = false; + + if (type =='datetime' || options.type == 'calendar') { + var t = jSuites.calendar.getDateString(value, options.mask); + if (t) { + value = t; + } + + if (options.mask && fullMask) { + fillWithBlanks = true; + } + } else { + // Percentage + if (type == 'percentage') { + value *= 100; + } + // Number of decimal places + if (typeof(value) === 'number') { + var t = null; + if (options.mask && fullMask) { + var e = new RegExp('0{1}(.{1})0+', 'ig'); + var d = options.mask.match(e); + if (d && d[0]) { + d = d[0].length - 2; + t = value.toFixed(d); + } else { + t = (''+value); + } + } else if (options.locale && fullMask) { + var d = (''+value).split('.'); + if (! d[1]) { + d[1] = '00'; + } else { + if (d[1].length == 1) { + d[1] += '0'; + } + } + t = d.join('.'); + } else { + t = toPlainString(value); + } + + if (t !== null) { + value = t; + // Get decimal + getDecimal.call(options, options.mask); + // Replace to the correct decimal + if (options.options.decimal) { + value = value.replace('.', options.options.decimal); + } + } + } else { + if (options.mask && fullMask) { + fillWithBlanks = true; + } + } + } + + if (fillWithBlanks) { + var s = options.mask.length - value.length; + if (s > 0) { + for (var i = 0; i < s; i++) { + value += ' '; + } + } + } + + value = obj(value, options); + + return value; + } + + obj.set = function(e, m) { + if (m) { + e.setAttribute('data-mask', m); + // Reset the value + var event = new Event('input', { + bubbles: true, + cancelable: true, + }); + e.dispatchEvent(event); + } + } + + if (typeof document !== 'undefined') { + document.addEventListener('input', function(e) { + if (e.target.getAttribute('data-mask') || e.target.mask) { + obj(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; +} + +// 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"], + ] + + palette.baby = [ + ["eddcd2","fff1e6","fde2e4","fad2e1","c5dedd","dbe7e4","f0efeb","d6e2e9","bcd4e6","99c1de"], + ["e1c4b3","ffd5b5","fab6ba","f5a8c4","aacecd","bfd5cf","dbd9d0","baceda","9dc0db","7eb1d5"], + ["daa990","ffb787","f88e95","f282a9","8fc4c3","a3c8be","cec9b3","9dbcce","82acd2","649dcb"], + ["d69070","ff9c5e","f66770","f05f8f","74bbb9","87bfae","c5b993","83aac3","699bca","4d89c2"], + ["c97d5d","f58443","eb4d57","e54a7b","66a9a7","78ae9c","b5a67e","7599b1","5c88b7","4978aa"], + ] + + if (palette[o]) { + return palette[o]; + } else { + return palette.material; + } +} + +jSuites.picker = (function(el, options) { + // Already created, update options + if (el.picker) { + return el.picker.setOptions(options, true); + } + + // New instance + var obj = { type: 'picker' }; + obj.options = {}; + + var dropdownHeader = null; + var dropdownContent = null; + + /** + * Create the content options + */ + var createContent = function() { + dropdownContent.innerHTML = ''; + + // 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.classList.add('jpicker-item'); + dropdownItem.k = keys[i]; + dropdownItem.v = obj.options.data[keys[i]]; + // Label + dropdownItem.innerHTML = obj.getLabel(keys[i]); + // Append + dropdownContent.appendChild(dropdownItem); + } + } + + /** + * Set or reset the options for the picker + */ + obj.setOptions = function(options, reset) { + // Default configuration + var defaults = { + value: 0, + data: null, + render: null, + onchange: null, + onselect: null, + onopen: null, + onclose: null, + onload: null, + width: null, + header: true, + right: false, + content: false, + columns: null, + height: null, + } + + // Legacy purpose only + if (options && options.options) { + options.data = options.options; + } + + // Loop through the initial configuration + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Start using the options + if (obj.options.header === false) { + dropdownHeader.style.display = 'none'; + } else { + dropdownHeader.style.display = ''; + } + + // Width + if (obj.options.width) { + dropdownHeader.style.width = parseInt(obj.options.width) + 'px'; + } else { + dropdownHeader.style.width = ''; + } + + // Height + if (obj.options.height) { + dropdownContent.style.maxHeight = obj.options.height + 'px'; + dropdownContent.style.overflow = 'scroll'; + } else { + dropdownContent.style.overflow = ''; + } + + if (obj.options.columns > 0) { + dropdownContent.classList.add('jpicker-columns'); + dropdownContent.style.width = obj.options.width ? obj.options.width : 36 * obj.options.columns + 'px'; + } + + if (isNaN(obj.options.value)) { + obj.options.value = '0'; + } + + // Create list from data + createContent(); + + // Set value + obj.setValue(obj.options.value); + + // Set options all returns the own instance + return obj; + } + + obj.getValue = function() { + return obj.options.value; + } + + obj.setValue = function(v) { + // Set label + obj.setLabel(v); + + // Update value + obj.options.value = String(v); + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + + if (dropdownContent.children[v].getAttribute('type') !== 'generic') { + obj.close(); + } + } + + obj.getLabel = function(v) { + var label = obj.options.data[v] || null; + if (typeof(obj.options.render) == 'function') { + label = obj.options.render(label); + } + return label; + } + + obj.setLabel = function(v) { + if (obj.options.content) { + var label = '' + obj.options.content + ''; + } else { + var label = obj.getLabel(v); + } + + dropdownHeader.innerHTML = label; + } + + obj.open = function() { + if (! el.classList.contains('jpicker-focus')) { + // Start tracking the element + jSuites.tracking(obj, true); + + // 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'; + } + + if (typeof obj.options.onopen == 'function') { + obj.options.onopen(el, obj); + } + } + } + + obj.close = function() { + if (el.classList.contains('jpicker-focus')) { + el.classList.remove('jpicker-focus'); + + // Start tracking the element + jSuites.tracking(obj, false); + + if (typeof obj.options.onclose == 'function') { + obj.options.onclose(el, obj); + } + } + } + + /** + * Create floating picker + */ + var init = function() { + // Class + el.classList.add('jpicker'); + el.setAttribute('tabindex', '900'); + el.onmousedown = function(e) { + if (! el.classList.contains('jpicker-focus')) { + obj.open(); + } + } + + // Dropdown Header + dropdownHeader = document.createElement('div'); + dropdownHeader.classList.add('jpicker-header'); + + // Dropdown content + dropdownContent = document.createElement('div'); + dropdownContent.classList.add('jpicker-content'); + dropdownContent.onclick = function(e) { + var item = jSuites.findElement(e.target, 'jpicker-item'); + if (item) { + if (item.parentNode === dropdownContent) { + // Update label + obj.setValue(item.k); + // Call method + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange.call(obj, el, obj, item.v, item.v, item.k); + } + } + } + } + + // Append content and header + el.appendChild(dropdownHeader); + el.appendChild(dropdownContent); + + // Default value + el.value = options.value || 0; + + // Set options + obj.setOptions(options); + + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj); + } + + // Change + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Reference + el.picker = obj; + } + + init(); + + return obj; +}); + +jSuites.rating = (function(el, options) { + // Already created, update options + if (el.rating) { + return el.rating.setOptions(options, true); + } + + // New instance + var obj = {}; + obj.options = {}; + + obj.setOptions = function(options, reset) { + // 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 { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Make sure the container is empty + el.innerHTML = ''; + + // 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); + } + + // Selected option + 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'); + } + } + } + + return obj; + } + + // 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); + } + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + obj.getValue = function() { + return obj.options.value; + } + + var init = function() { + // Start plugin + obj.setOptions(options); + + // Class + el.classList.add('jrating'); + + // 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'); + } + }); + + // Change + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Reference + el.rating = obj; + } + + init(); + + return obj; +}); + + +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'); + } + } + + el.val = function() { + var id = null; + var data = []; + for (var i = 0; i < el.children.length; i++) { + if (id = el.children[i].getAttribute('data-id')) { + data.push(id); + } + } + return data; + } + + 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, + palette: null, + maxWidth: 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) { + if (obj.options.animation) { + var rect = obj.headers.children[index].getBoundingClientRect(); + + if (obj.options.palette == 'modern') { + border.style.width = rect.width - 4 + 'px'; + border.style.left = obj.headers.children[index].offsetLeft + 2 + 'px'; + } else { + border.style.width = rect.width + 'px'; + border.style.left = obj.headers.children[index].offsetLeft + 'px'; + } + + if (obj.options.position == 'bottom') { + border.style.top = '0px'; + } else { + 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 = ''; + } + } + + obj.setBorder = setBorder; + + // 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 { + // Set border + setBorder(index); + + obj.headers.parentNode.style.display = ''; + + 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.remove = 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, cb) { + 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); + + // Callback + if (typeof(cb) == 'function') { + cb(div, h); + } + + // Return element + return div; + } + } + + obj.getActive = function() { + for (var i = 0; i < obj.headers.children.length; i++) { + if (obj.headers.children[i].classList.contains('jtabs-selected')) { + return i + } + } + return 0; + } + + obj.updateContent = function(position, newContent) { + if (typeof newContent !== 'string') { + var contentItem = newContent; + } else { + var contentItem = document.createElement('div'); + contentItem.innerHTML = newContent; + } + + if (obj.content.children[position].classList.contains('jtabs-selected')) { + newContent.classList.add('jtabs-selected'); + } + + obj.content.replaceChild(newContent, obj.content.children[position]); + } + + obj.updatePosition = function(f, t) { + // Ondrop update position of content + if (f > t) { + obj.content.insertBefore(obj.content.children[f], obj.content.children[t]); + } else { + obj.content.insertBefore(obj.content.children[f], obj.content.children[t].nextSibling); + } + + // Open destination tab + obj.open(t); + + // Call event + if (typeof(obj.options.onchangeposition) == 'function') { + obj.options.onchangeposition(obj.headers, f, t); + } + } + + obj.move = function(f, t) { + if (f > t) { + obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t]); + } else { + obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t].nextSibling); + } + + obj.updatePosition(f, t); + } + + obj.setBorder = setBorder; + + 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'); + + if (obj.options.palette) { + el.classList.add('jtabs-modern'); + } else { + el.classList.remove('jtabs-modern'); + } + + // 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); + if (obj.options.maxWidth) { + header.style.maxWidth = parseInt(obj.options.maxWidth) + 'px'; + } + + // Controls + var controls = document.createElement('div'); + controls.className = 'jtabs-controls'; + controls.setAttribute('draggable', 'false'); + header.appendChild(controls); + + // Append DOM elements + if (obj.options.position == 'bottom') { + el.appendChild(obj.content); + el.appendChild(header); + } else { + 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++) { + // Title + if (obj.options.data[i].titleElement) { + var headerItem = obj.options.data[i].titleElement; + } else { + var headerItem = document.createElement('div'); + } + // Icon + if (obj.options.data[i].icon) { + var iconContainer = document.createElement('div'); + var icon = document.createElement('i'); + icon.classList.add('material-icons'); + icon.innerHTML = obj.options.data[i].icon; + iconContainer.appendChild(icon); + headerItem.appendChild(iconContainer); + } + // Title + if (obj.options.data[i].title) { + var title = document.createTextNode(obj.options.data[i].title); + headerItem.appendChild(title); + } + // Width + if (obj.options.data[i].width) { + headerItem.style.width = obj.options.data[i].width; + } + // Content + if (obj.options.data[i].contentElement) { + var contentItem = obj.options.data[i].contentElement; + } else { + var contentItem = document.createElement('div'); + 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) { + if (e.target.parentNode.classList.contains('jtabs-headers')) { + var target = e.target; + } else { + if (e.target.tagName == 'I') { + var target = e.target.parentNode.parentNode; + } else { + var target = e.target.parentNode; + } + } + + var index = obj.selectIndex(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) { + obj.updatePosition(b,c); + }, + }); + } + + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj); + } + } + + // Loading existing nodes as the data + if (el.children[0] && el.children[0].children.length) { + // Create from existing elements + for (var i = 0; i < el.children[0].children.length; i++) { + var item = obj.options.data && obj.options.data[i] ? obj.options.data[i] : {}; + + if (el.children[1] && el.children[1].children[i]) { + item.titleElement = el.children[0].children[i]; + item.contentElement = el.children[1].children[i]; + } else { + item.contentElement = el.children[0].children[i]; + } + + obj.options.data[i] = item; + } + } + + // 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) { + // New instance + var obj = { type:'toolbar' }; + obj.options = {}; + + // Default configuration + var defaults = { + app: null, + container: false, + badge: false, + title: false, + responsive: false, + maxWidth: null, + 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); + } + + // Arrow + var toolbarArrow = document.createElement('div'); + toolbarArrow.classList.add('jtoolbar-item'); + toolbarArrow.classList.add('jtoolbar-arrow'); + + var toolbarFloating = document.createElement('div'); + toolbarFloating.classList.add('jtoolbar-floating'); + toolbarArrow.appendChild(toolbarFloating); + + 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 = ''; + } + + obj.update = function(a, b) { + for (var i = 0; i < toolbarContent.children.length; i++) { + // Toolbar element + var toolbarItem = toolbarContent.children[i]; + // State management + if (typeof(toolbarItem.updateState) == 'function') { + toolbarItem.updateState(el, obj, toolbarItem, a, b); + } + } + } + + 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].updateState) { + toolbarItem.updateState = items[i].updateState; + } + + if (items[i].active) { + toolbarItem.classList.add('jtoolbar-active'); + } + + if (items[i].type == 'select' || items[i].type == 'dropdown') { + 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 = items[i].onclick.bind(items[i], el, obj, toolbarItem); + } + + toolbarContent.appendChild(toolbarItem); + } + + // Fits to the page + obj.refresh(); + } + + obj.open = function() { + toolbarArrow.classList.add('jtoolbar-arrow-selected'); + + var rect = toolbarFloating.getBoundingClientRect(); + if (rect.bottom > window.innerHeight) { + toolbarFloating.style.bottom = '0'; + } else { + toolbarFloating.style.removeProperty('bottom'); + } + + toolbarFloating.style.right = '0'; + + toolbarArrow.children[0].focus(); + // Start tracking + jSuites.tracking(obj, true); + } + + obj.close = function() { + toolbarArrow.classList.remove('jtoolbar-arrow-selected') + // End tracking + jSuites.tracking(obj, false); + } + + obj.refresh = function() { + if (obj.options.responsive == true) { + // Width of the c + var rect = el.parentNode.getBoundingClientRect(); + if (! obj.options.maxWidth) { + obj.options.maxWidth = rect.width; + } + // Max width + var width = parseInt(obj.options.maxWidth); + // Remove arrow + toolbarArrow.remove(); + // Move all items to the toolbar + while (toolbarFloating.firstChild) { + toolbarContent.appendChild(toolbarFloating.firstChild); + } + // Available parent space + var available = obj.options.maxWidth; + // Toolbar is larger than the parent, move elements to the floating element + if (available < toolbarContent.offsetWidth) { + // Give space to the floating element + available -= 50; + // Move to the floating option + while (toolbarContent.lastChild && available < toolbarContent.offsetWidth) { + toolbarFloating.insertBefore(toolbarContent.lastChild, toolbarFloating.firstChild); + } + } + // Show arrow + if (toolbarFloating.children.length > 0) { + toolbarContent.appendChild(toolbarArrow); + } + } + } + + el.onclick = function(e) { + var element = jSuites.findElement(e.target, 'jtoolbar-item'); + if (element) { + obj.selectItem(element); + } + + if (e.target.classList.contains('jtoolbar-arrow')) { + obj.open(); + } + } + + window.addEventListener('resize', function() { + obj.refresh(); + }); + + // Toolbar + el.classList.add('jtoolbar'); + // Reset content + el.innerHTML = ''; + // Container + if (obj.options.container == true) { + el.classList.add('jtoolbar-container'); + } + // Content + var toolbarContent = document.createElement('div'); + el.appendChild(toolbarContent); + // Special toolbar for mobile applications + if (obj.options.app) { + el.classList.add('jtoolbar-mobile'); + } + // Create toolbar + obj.create(obj.options.items); + // Shortcut + el.toolbar = obj; + + return obj; +}); + + + + return jSuites; + +}))); \ No newline at end of file diff --git a/web/_static/jsuites/jsuites.css b/web/_static/jsuites/jsuites.css new file mode 100644 index 0000000..429d9de --- /dev/null +++ b/web/_static/jsuites/jsuites.css @@ -0,0 +1,2724 @@ + +/** + * (c) jSuites Javascript Web Components + * + * Website: https://jsuites.net + * 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 { + position: relative; + box-sizing: border-box; + background-size: initial; + height: 33px; + min-height: initial; + padding: 6px; + padding-right: 30px; +} + +.jupload.input:before { + content: "save"; + font-size: 18px; + font-family: "Material Icons"; + color: #000; + position: absolute; + right: 5px; +} + +.jupload img { + width: 100%; +} + +.jupload.input img { + width: initial; + max-width: 100%; + height: 100%; +} + +.jupload[data-multiple] { + padding: 10px; +} + +.jupload[data-multiple] img { + height: 70px; + width: 100px; + object-fit: cover; + margin-right: 5px; + margin-bottom: 5px; +} + +.jupload { + border: 1px dotted #eee; + cursor: pointer; + box-sizing: border-box; + width: 100%; + height: 100%; + min-height: 180px; +} + +.jupload:not(.input):before { + content: "\e2c3"; + font-family: "Material Icons"; + font-size: 90px; + color: #eee; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.jupload-item { + padding-right: 22px; + border-radius: 1px; + display: inline-block; + position: relative; +} + +.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 { + position: relative; + animation: slide-left-in 0.4s forwards; +} + +.slide-left-out { + position: relative; + animation: slide-left-out 0.4s forwards; +} + +.slide-right-in { + position: relative; + animation: slide-right-in 0.4s forwards; +} + +.slide-right-out { + position: relative; + animation: slide-right-out 0.4s forwards; +} + +.slide-top-in { + position: relative; + animation: slide-top-in 0.4s forwards; +} + +.slide-top-out { + position: relative; + animation: slide-top-out 0.2s forwards; +} + +.slide-bottom-in { + position: relative; + animation: slide-bottom-in 0.4s forwards; +} + +.slide-bottom-out { + position: relative; + animation: slide-bottom-out 0.1s forwards; +} + +.spin { + animation: spin 2s infinite linear; +} + +/** 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% { left: -100%; } + 100% { left: 0%; } +} + +@-webkit-keyframes slide-left-in { + 0% { left: -100%; } + 100% { left: 0%; } +} + +@keyframes slide-left-out { + 0% { left: 0%; } + 100% { left: -100%; } +} + +@-webkit-keyframes slide-left-out { + 0% { left: 0%; } + 100% { left: -100%; } +} + +/** Keyframes Right to Left **/ +@keyframes slide-right-in { + 0% { left: 100%; } + 100% { left: 0%; } +} + +@-webkit-keyframes slide-right-in +{ + 0% { left: 100%; } + 100% { left: 0%; } +} + +@keyframes slide-right-out { + 0% { left: 0%; } + 100% { left: 100%; } +} + +@-webkit-keyframes slide-right-out { + 0% { left: 0%; } + 100% { left: 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(359deg); + } +} + +@keyframes spin { + from { + transform:rotate(0deg); + } + to { + transform:rotate(359deg); + } +} + +.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; + min-width: 260px; +} + +.jcolor-controls { + display: flex; + padding: 10px; + border-bottom: 1px solid #eee; + margin-bottom: 5px; +} + +.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: collapse; + box-sizing: border-box; +} + +.jcolor-focus { + display:block; +} + +.jcolor table { + width:100%; + height:100%; + min-height: 160px; +} + +.jcolor td { + padding: 7px; +} + +.jcolor-selected { + 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: 290px; + 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 */ +} + +.jcolor-content .jtabs-content { + padding: 7px; +} + +.jcolor-grid tr:first-child > td:first-child { + border-top-left-radius: 3px; +} + +.jcolor-grid tr:first-child > td:last-child { + border-top-right-radius: 3px; +} + +.jcolor-grid tr:last-child > td:first-child { + border-bottom-left-radius: 3px; +} + +.jcolor-grid tr:last-child > td:last-child { + border-bottom-right-radius: 3px; +} + +.jcolor-hsl { + box-sizing: border-box; +} + +.jcolor-hsl > div { + height: 100%; + position: relative; +} + +.jcolor-hsl canvas { + display: block; + border-radius: 4px; + -webkit-user-drag: none; +} + +.jcolor-point { + height: 5px; + width: 5px; + background-color: #000; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 50%; +} + +.jcolor-sliders { + padding: 10px 20px 10px 10px; +} + +.jcolor-sliders input { + -webkit-appearance: none; + + height: 12px; + width: 80%; + + background: #d3d3d3; + opacity: 1; + + border-radius: 30px; + outline: none; +} + +.jcolor-sliders-input-subcontainer { + display: flex; + justify-content: space-between; + align-items: center; +} + +.jcolor-sliders-input-container { + margin-top: 4px; + line-height: 0.8em; + text-align: left; +} + +.jcolor-sliders-input-container > label { + font-size: 10px; + text-transform: uppercase; + color: #bbbbbd; +} + +.jcolor-sliders-input-subcontainer > input { + border: 0px; + padding: 1px; +} + +.jcolor-sliders-input-container input::-webkit-slider-thumb { + -webkit-appearance: none; + height: 12px; + width: 12px; + border-radius: 50%; + background: #000; + border: 2px solid #fff; + cursor: pointer; +} + +.jcolor-sliders-input-container input::-moz-range-thumb { + -webkit-appearance: none; + height: 12px; + width: 12px; + border-radius: 50%; + background: #000; + border: 2px solid #fff; + cursor: pointer; +} + +.jcolor-sliders-final-color { + padding: 6px; + user-select: all; + margin-top: 10px; + text-align: center; +} + +.jcolor-sliders-final-color > div:nth-child(2) { + width: 71px; + text-transform: uppercase; +} + +.jcolor .jtabs .jtabs-headers-container .jtabs-controls { + display: none !important; +} + +.jcolor .jtabs .jtabs-headers-container { + display: flex !important; + justify-content: center; + padding: 4px; +} + +.jcolor .jtabs-headers > div:not(.jtabs-border) { + padding: 2px !important; + padding-left: 15px !important; + padding-right: 15px !important; + font-size: 0.8em; +} + +.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' !important; + 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; +} + +@media only screen and (max-width: 420px) { + .jcontextmenu { + top: initial !important; + left: 0px !important; + bottom: 0px !important; + width: 100vw; + height: 260px; + overflow: scroll; + animation: slide-bottom-in 0.4s forwards; + } + .jcontextmenu div { + width: 100%; + text-align: center; + border-bottom: 1px solid #ccc; + padding: 15px; + } + .jcontextmenu > div::before { + display: none; + } + .jcontextmenu a { + font-size: 1.4em; + text-transform: uppercase; + } + .jcontextmenu span { + display: none; + } + .jcontextmenu span { + display: none; + } + .jcontextmenu hr { + display: none; + } +} + +.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[disabled] { + opacity: 0.5; + pointer-events: 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-icon +{ + margin-right:10px; + font-size: 30px; + margin-left: -5px; +} + +.jdropdown-icon-small +{ + font-size: 24px; + margin-left: 0px; +} + +.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; + text-align: left; +} + +.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 !important; + left:0px !important; + width:100% !important; + height:100% !important; + background-color:#fafafa; + padding:0px; + z-index:9001; + overflow-y:scroll; + will-change: scroll-position; + -webkit-overflow-scrolling: touch; +} + +.jdropdown-searchbar.jdropdown-focus .jdropdown-container-header +{ + position: fixed; + top: 0px; + left: 0px; + z-index: 9002; + padding:10px; + background-color:#fff; + box-shadow: 0 1px 2px rgba(0,0,0,.1); + max-height: 24px; + width: 100%; +} + +.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 +{ + margin-top: 40px; + 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-width : 800px) +{ + .jdropdown-list { + width:100% !important; + border:0px; + padding:0px; + } + + .jdropdown-list .jdropdown-container { + min-width:100%; + } + + .jdropdown-searchbar.jdropdown-focus .jdropdown-description { + text-transform: uppercase; + } +} + +.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; +} + +.jdropdown-item[data-disabled] { + opacity: 0.5; + pointer-events: none; +} + +.jeditor-container { + border:1px solid #ccc; + box-sizing: border-box; +} + +.jeditor-dragging { + border:1px dashed #000; +} + +.jeditor-container.jeditor-padding { + padding:10px; +} + +.jeditor { + outline:none; + word-break: break-word; + +} + +.jeditor[data-placeholder]:empty:before { + content: attr(data-placeholder); + color: lightgray; +} + +.jeditor-container.jeditor-padding .jeditor { + min-height:100px; + margin-bottom:10px; + padding:10px; +} + +/** Snippet **/ + +.jsnippet { + margin-top:15px; + cursor:pointer; + border: 1px solid #ccc; + 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: 'close'; + font-family: 'Material icons'; + font-size: 24px; + width: 24px; + height: 24px; + line-height: 24px; + cursor: pointer; + text-shadow: 0px 0px 2px #fff; + position: absolute; + top: 12px; + right: 12px; +} + +.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; +} + +.jeditor img.resizing { + -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; + outline: #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; +} + +.jeditor-toolbar { + width: fit-content; + max-width: 100%; + box-sizing: border-box; +} + +.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 !important; + z-index:9002; + border-radius: 8px; +} + +.jmodal:before { + position:absolute; + top:0; + left:0; + width:100%; + content:attr(title); + padding:15px; + box-sizing: border-box; + font-size:1.2em; + box-shadow: 1px 1px 3px rgba(0,0,0,.2); + background-color: #fff; + border-radius: 8px 8px 0px 0px; +} + +.jmodal_content { + padding:20px; + overflow-y:auto; + max-height:100%; + box-sizing: border-box; + height: -webkit-fill-available; +} +.jmodal.no-title { + padding-top: initial !important; +} + +.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; + bottom: 0px; +} + +.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; + + 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-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-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; + margin: 0px; + width: initial; + } + .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; + position: relative; +} + +.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; + top: 0; + 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; + max-height: 200px; + scrollbar-width: thin; + scrollbar-color: #333 transparent; +} + +.jpicker-content::-webkit-scrollbar { + width: 8px; +} + +.jpicker-content::-webkit-scrollbar-track { + background: #eee; +} + +.jpicker-content::-webkit-scrollbar-thumb { + background: #888; +} + +.jpicker-content > div { + padding: 6px; + padding-left: 15px; + padding-right: 15px; +} + +.jpicker-focus > .jpicker-content { + display: block; +} + +.jpicker-content > div:hover { + background-color:#efefef; +} + +.jpicker-content > div:empty { + opacity: 0; +} + +.jpicker-header > i, .jpicker-header > div { + display: block; +} + +.jpicker-focus > .jpicker-content.jpicker-columns { + display: flex !important ; + justify-content: center; + flex-wrap: wrap; +} + + +.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"); +} + + +.jsearch { + position: relative; + display: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.jsearch_container { + position: absolute; + 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; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.jsearch_container:empty:after { + content: attr(data-placeholder); +} + +.jsearch_container > 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; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.jsearch_container > div:hover { + background-color: #e8eaed; +} + +.jsearch_container > div > img { + width: 32px; + height: 32px; + user-select: none; + border-radius: 16px; + margin-right: 2px; +} + +.jsearch_container > div > div { + overflow: hidden; + text-overflow: ellipsis; + margin-left: 2px; + max-width: 300px; + white-space: nowrap; + user-select: none; +} + +.jsearch_container .selected { + background-color: #e8eaed; +} + +.jslider { + outline: none; +} + +.jslider-focus { + width: 100% !important; + height: 100% !important; +} + +.jslider-focus img { + display: none; +} + +.jslider img { + width: 100px; +} + +.jslider-left::before { + position: fixed; + left: 15px; + top: 50%; + content:'arrow_back_ios'; + color: #fff; + width: 30px; + height: 30px; + font-family: 'Material Icons'; + font-size: 30px; + /* before it was 0px 0px 0px #000 */ + text-shadow: 0px 0px 6px rgb(56 56 56); + text-align: center; + cursor: pointer; +} + +.jslider-right::after { + position: fixed; + right: 15px; + top: 50%; + content: 'arrow_forward_ios'; + color: #fff; + width: 30px; + height: 30px; + font-family: 'Material Icons'; + font-size: 30px; + /* before it was 0px 0px 0px #000 */ + text-shadow: 0px 0px 6px rgb(56 56 56); + text-align: center; + cursor: pointer; +} + +.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; + cursor:pointer; + z-index:3000; + + display: block !important; +} + +.jslider-counter { + height:24px; + background-color: transparent; + position:fixed; + left: 50%; + transform: translateX(-50%); + bottom: 15px; + cursor:pointer; + z-index:3000; + + display: flex; + display: -webkit-flex; + -webkit-justify-content: center; + -webkit-align-items: center; + -webkit-flex-direction: row; + justify-content: center; + align-items: center; + flex-direction: row; +} + +.jslider-caption { + position: fixed; + max-width: 90vw; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + top:15px; + left: 15px; + z-index:3000; + color: #FFF; + font-size: 1rem; + + display: block !important; +} + +.jslider-counter div { + width: 10px; + height: 10px; + background: #fff; + border-radius: 50%; + margin: 0px 5px; + + display: block !important; +} + +.jslider-counter .jslider-counter-focus { + background-color: cornflowerblue; + pointer-events: none; +} + +.jslider-focus { + position:fixed; + left:0; + top:0; + width: 100%; + min-height:100%; + max-height:100%; + z-index:2000; + margin:0px; + box-sizing:border-box; + + background-color:rgba(0,0,0,0.8); + -webkit-transition-duration: .05s; + transition-duration: .05s; + display: flex; + -ms-flex-align: center; + -webkit-align-items: center; + -webkit-box-align: center; + + align-items: center; +} + +.jslider-focus img { + width: 50vw; + height: auto; + box-sizing: border-box; + margin:0 auto; + vertical-align:middle; + display:none; +} + +.jslider-focus img.jslider-vertical { + width: auto; + /* before it was 50vh */ + height: 80vh; +} + +@media only screen and (max-width: 576px) { + .jslider-focus img.jslider-vertical { + width: 99vw !important; + height: auto !important; + } + + .jslider-focus img { + width: 100vw !important; + height: auto !important; + } +} + +.jslider-grid { + display: -ms-grid; + display: grid; + grid-gap: 1px; + position: relative; +} + +.jslider-grid[data-number='2'] { + -ms-grid-columns: 1fr 50%; + grid-template-columns: 1fr 50%; +} + +.jslider-grid[data-number='3'] { + -ms-grid-columns: 1fr 33%; + grid-template-columns: 1fr 33%; +} + +.jslider-grid[data-number='4'] { + -ms-grid-columns: 1fr 25%; + grid-template-columns: 1fr 25%; +} + +.jslider-grid img { + display: none; + width: 100%; + height: 100%; + object-fit: cover; +} + +.jslider-grid[data-total]:after { + content: attr(data-total) "+"; + font-size: 1.5em; + position:absolute; + color: #fff; + right: 15px; + bottom: 6px; +} + +.jslider-grid img:first-child { + -ms-grid-column: 1; + -ms-grid-row: 1; + grid-column: 1; + grid-row: 1; + display: block; +} + +.jslider-grid[data-number='2'] img:nth-child(2) { + -ms-grid-column: 2; + -ms-grid-row: 1; + grid-column: 2; + grid-row: 1; + display: block; +} + +.jslider-grid[data-number='3'] img:first-child { + -ms-grid-column: 1 / 2; + -ms-grid-row: 1 / 4; + grid-column: 1 / 2; + grid-row: 1 / 4; +} + +.jslider-grid[data-number='3'] img:nth-child(2) { + -ms-grid-column: 2; + -ms-grid-row: 1; + grid-column: 2; + grid-row: 1; + display: block; +} + +.jslider-grid[data-number='3'] img:nth-child(3) { + -ms-grid-column: 2; + -ms-grid-row: 2; + grid-column: 2; + grid-row: 2; + display: block; +} + +.jslider-grid[data-number='4'] img:first-child { + -ms-grid-column: 1 / 2; + -ms-grid-row: 1 / 4; + grid-column: 1 / 2; + grid-row: 1 / 4; +} + +.jslider-grid[data-number='4'] img:nth-child(2) { + -ms-grid-column: 2; + -ms-grid-row: 1; + grid-column: 2; + grid-row: 1; + display: block; +} + +.jslider-grid[data-number='4'] img:nth-child(3) { + -ms-grid-column: 2; + -ms-grid-row: 2; + grid-column: 2; + grid-row: 2; + display: block; +} + +.jslider-grid[data-number='4'] img:nth-child(4) { + -ms-grid-column: 2; + -ms-grid-row: 3; + grid-column: 2; + grid-row: 3; + display: block; +} + + +.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 { + 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; + background-color: #f1f1f1; + cursor: pointer; + white-space: nowrap; + text-align: center; +} + +.jtabs .jtabs-headers > div.jtabs-selected { + background-color: #e8e8e8; + color: #000; +} + +.jtabs .jtabs-headers > div > div { + color: #555; + width: 100%; + overflow: hidden; +} + +.jtabs .jtabs-headers i { + display: block; + margin: auto; +} + +.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"); +} + +/** Modern skin **/ + +.jtabs.jtabs-modern .jtabs-headers > div:not(.jtabs-border) { + padding: 4px; + padding-left: 10px; + padding-right: 10px; + background-color: #fff; +} + +.jtabs.jtabs-modern .jtabs-headers > .jtabs-selected { + color: #000; +} + +.jtabs.jtabs-modern .jtabs-headers > .jtabs-selected .material-icons { + color: #000; +} + +.jtabs.jtabs-modern .jtabs-headers { + background: #EEEEEF !important; + padding: 2px; + border-radius: 4px; +} + +.jtabs.jtabs-modern .jtabs-headers .jtabs-border { + border-color: #EEEEEF !important; +} + +.jtabs.jtabs-modern .jtabs-border { + background-color: rgba(194, 197, 188, 0.884); +} + +.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.jtags-empty:not(.jtags-focus)::before { + position: absolute; + margin: 5px; + color: #ccc; + content:attr(data-placeholder); +} + +.jtags > div { + padding: 3px; + padding-left: 10px; + padding-right: 22px; + position: relative; + border-radius: 1px; + margin: 2px; + display: block; + outline: none; +} + +.jtags > div:empty:before { + content: " "; + white-space: pre; +} + +.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; +} + + +.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; + font-size: 13px; +} + +.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: 18px; + padding: 0px; + margin-left: 4px; + margin-right: 4px; + background-color: #ddd; +} + +.jtoolbar .jtoolbar-label { + padding-left: 8px; + padding-right: 8px; +} + + + +.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: 8px; + background-position: top 50% right 0px; + display: flex; + align-items: center; +} + +.jtoolbar .jpicker-content > div { + padding: 6px; +} + +.jtoolbar-active { + background-color:#eee; +} + +.jtoolbar .fa { + width: 18px; + height: 18px; + display: block; + line-height: 18px; + font-size: 14px; +} + +.jtoolbar .material-icons { + font-size: 18px; + width: 24px; + height: 24px; + display: block; + line-height: 24px; + transform: rotate(0.03deg); + text-align: center; +} + +.jtoolbar .jtoolbar-arrow { + background-repeat: no-repeat; + background-position: center; + 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 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z'/%3E%3C/svg%3E"); + width: 24px; + height: 16px; + margin-left: 4px; + border-left: 1px solid #f2f2f2; +} + +.jtoolbar-floating { + 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; +} + +.jtoolbar-floating .jtoolbar-divisor { + display: none; +} + +.jtoolbar-floating > div { + display: block; +} + +.jtoolbar-arrow-selected .jtoolbar-floating { + display: flex; + flex-wrap: wrap; +} + + diff --git a/web/_static/jsuites/jsuites.js b/web/_static/jsuites/jsuites.js new file mode 100644 index 0000000..8145ef4 --- /dev/null +++ b/web/_static/jsuites/jsuites.js @@ -0,0 +1,11452 @@ +/** + * (c) jSuites Javascript Web Components + * + * Website: https://jsuites.net + * 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 = {} + var version = '4.9.11'; + + var find = function(DOMElement, component) { + if (DOMElement[component.type] && DOMElement[component.type] == component) { + return true; + } + if (DOMElement.parentNode) { + return find(DOMElement.parentNode, component); + } + return false; + } + + var isOpened = function(e) { + if (jSuites.current.length > 0) { + for (var i = 0; i < jSuites.current.length; i++) { + if (jSuites.current[i] && ! find(e.target, jSuites.current[i])) { + jSuites.current[i].close(); + } + } + } + } + + obj.init = function() { + document.addEventListener("click", isOpened); + + obj.version = version; + } + + obj.tracking = function(component, state) { + if (state == true) { + jSuites.current = jSuites.current.filter(function(v) { + return v !== null; + }); + + // Start after all events + setTimeout(function() { + jSuites.current.push(component); + }, 0); + + } else { + var index = jSuites.current.indexOf(component); + if (index >= 0) { + jSuites.current[index] = null; + } + } + } + + /** + * Get or set a property from a JSON from a string. + */ + obj.path = function(str, val) { + str = str.split('.'); + if (str.length) { + var o = this; + var p = null; + while (str.length > 1) { + // Get the property + p = str.shift(); + // Check if the property exists + if (o.hasOwnProperty(p)) { + o = o[p]; + } else { + // Property does not exists + if (val === undefined) { + return undefined; + } else { + // Create the property + o[p] = {}; + // Next property + o = o[p]; + } + } + } + // Get the property + p = str.shift(); + // Set or get the value + if (val !== undefined) { + o[p] = val; + // Success + return true; + } else { + // Return the value + return o[p]; + } + } + // Something went wrong + return false; + } + + // Update dictionary + obj.setDictionary = function(d) { + obj.dictionary = d; + + // Translations + var t = null; + for (var i = 0; i < jSuites.calendar.weekdays.length; i++) { + t = jSuites.translate(jSuites.calendar.weekdays[i]); + if (jSuites.calendar.weekdays[i]) { + jSuites.calendar.weekdays[i] = t; + jSuites.calendar.weekdaysShort[i] = t.substr(0,3); + } + } + for (var i = 0; i < jSuites.calendar.months.length; i++) { + t = jSuites.translate(jSuites.calendar.months[i]); + if (t) { + jSuites.calendar.months[i] = t; + jSuites.calendar.monthsShort[i] = t.substr(0,3); + } + } + } + + // Dictionary + obj.dictionary = {}; + + // Translate + obj.translate = function(t) { + return obj.dictionary[t] || t; + } + + // Array of opened components + obj.current = []; + + return obj; +}(); + +/** + * Global jsuites event + */ +if (typeof(document) !== "undefined") { + jSuites.init(); +} + +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'); + } else if (options.dataType == 'blob') { + httpRequest.responseType = "blob"; + } else if (options.dataType == 'html') { + httpRequest.setRequestHeader('Content-Type', 'text/html'); + } + } + + // 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 { + if (options.dataType == 'blob') { + var result = httpRequest.response; + } 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, httpRequest.status); + } + } + + // 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); + // Deprected: Last one? + if (! jSuites.ajax.requests.length) { + // Object event + if (options.complete && typeof(options.complete) == 'function') { + options.complete(result); + } + } + // Group requests + if (options.group) { + if (jSuites.ajax.oncomplete && typeof(jSuites.ajax.oncomplete[options.group]) == 'function') { + if (! jSuites.ajax.pending(options.group)) { + jSuites.ajax.oncomplete[options.group](); + jSuites.ajax.oncomplete[options.group] = null; + } + } + } + // Multiple requests controller + 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); + } + } + } + } + } + + // Keep the options + httpRequest.options = options; + // 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.pending = function(group) { + var n = 0; + var o = jSuites.ajax.requests; + if (o && o.length) { + for (var i = 0; i < o.length; i++) { + if (! group || group == o[i].options.group) { + n++ + } + } + } + return n; +} + +jSuites.ajax.oncomplete = {}; +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.style.display = ''; + 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.style.display = 'none'; + element.classList.remove('fade-out'); + if (typeof(done) == 'function') { + done(); + } + }, 1000); +} + +jSuites.calendar = (function(el, options) { + // Already created, update options + if (el.calendar) { + return el.calendar.setOptions(options, true); + } + + // New instance + var obj = { type:'calendar' }; + obj.options = {}; + + // Date + obj.date = null; + + /** + * Update options + */ + obj.setOptions = function(options, reset) { + // 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: jSuites.calendar.monthsShort, + monthsFull: jSuites.calendar.months, + weekdays: jSuites.calendar.weekdays, + weekdays_short: jSuites.calendar.weekdays, + textDone: jSuites.translate('Done'), + textReset: jSuites.translate('Reset'), + textUpdate: jSuites.translate('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, + // Data type + dataType: null, + } + + for (var i = 0; i < defaults.weekdays_short.length; i++) { + defaults.weekdays_short[i] = defaults.weekdays_short[i].substr(0,1); + } + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Reset button + if (obj.options.resetButton == false) { + calendarReset.style.display = 'none'; + } else { + calendarReset.style.display = ''; + } + + // Readonly + if (obj.options.readonly) { + el.setAttribute('readonly', 'readonly'); + } else { + el.removeAttribute('readonly'); + } + + // Placeholder + if (obj.options.placeholder) { + el.setAttribute('placeholder', obj.options.placeholder); + } else { + el.removeAttribute('placeholder'); + } + + if (jSuites.isNumeric(obj.options.value) && obj.options.value > 0) { + obj.options.value = jSuites.calendar.numToDate(obj.options.value); + // Data type numberic + obj.options.dataType = 'numeric'; + } + + // Texts + calendarReset.innerHTML = obj.options.textReset; + calendarConfirm.innerHTML = obj.options.textDone; + calendarControlsUpdateButton.innerHTML = obj.options.textUpdate; + + // Define mask + el.setAttribute('data-mask', obj.options.format.toLowerCase()); + + // Value + if (! obj.options.value && obj.options.today) { + var value = jSuites.calendar.now(); + } else { + var value = obj.options.value; + } + + // Set internal date + if (value) { + // Force the update + obj.options.value = null; + // New value + obj.setValue(value); + } + + return obj; + } + + /** + * Open the calendar + */ + obj.open = function (value) { + if (! calendar.classList.contains('jcalendar-focus')) { + if (! calendar.classList.contains('jcalendar-inline')) { + // Current + jSuites.calendar.current = obj; + // Start tracking + jSuites.tracking(obj, true); + // Create the days + obj.getDays(); + // Render months + 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]; + } + + // Show calendar + calendar.classList.add('jcalendar-focus'); + + // Get the position of the corner helper + if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen) { + calendar.classList.add('jcalendar-fullsize'); + // Animation + jSuites.animation.slideBottom(calendarContent, 1); + } else { + calendar.classList.remove('jcalendar-fullsize'); + + 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) { + var d = -1 * (rect.height + rectContent.height + 2); + if (d + rect.top < 0) { + d = -1 * (rect.top + rect.height); + } + calendarContainer.style.top = d + 'px'; + } else { + calendarContainer.style.top = 2 + 'px'; + } + + if (window.innerWidth < rect.left + rectContent.width) { + var d = window.innerWidth - (rect.left + rectContent.width + 20); + calendarContainer.style.left = d + 'px'; + } else { + calendarContainer.style.left = '0px'; + } + } + } + + // Events + if (typeof(obj.options.onopen) == 'function') { + obj.options.onopen(el); + } + } + } + } + + obj.close = function (ignoreEvents, update) { + if (calendar.classList.contains('jcalendar-focus')) { + 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'); + // Stop tracking + jSuites.tracking(obj, false); + // Current + jSuites.calendar.current = null; + } + + 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(); + } + } + + /** + * Set today + */ + obj.setToday = function() { + // Today + var value = new Date().toISOString().substr(0, 10); + // Change value + obj.setValue(value); + // Value + return value; + } + + obj.setValue = function(val) { + if (! val) { + val = '' + val; + } + // Values + var newValue = val; + var oldValue = obj.options.value; + + if (oldValue != newValue) { + // Set label + if (! newValue) { + obj.date = null; + var val = ''; + } else { + 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; + + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, newValue, oldValue); + } + + // Lemonade JS + if (el.value != val) { + el.value = val; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + 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, v) { + if (element.classList.contains('jcalendar-disabled')) { + // Do nothing + } else { + var elements = calendar.querySelector('.jcalendar-selected'); + if (elements) { + elements.classList.remove('jcalendar-selected'); + } + element.classList.add('jcalendar-selected'); + + if (element.classList.contains('jcalendar-set-month')) { + obj.date[1] = v; + } else { + obj.date[2] = element.innerText; + } + + if (! obj.options.time) { + obj.close(); + } else { + obj.date[3] = calendarSelectHour.value; + obj.date[4] = calendarSelectMin.value; + } + } + + // Update + updateActions(); + } + + /** + * Set to blank + */ + obj.reset = function() { + // Close calendar + obj.setValue(''); + obj.date = null; + 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; + + // Value + var value = obj.options.value; + + // Current date + var date = new Date(); + var currentYear = parseInt(date.getFullYear()); + var currentMonth = parseInt(date.getMonth()) + 1; + var selectedYear = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : currentYear; + var selectedMonth = obj.date && jSuites.isNumeric(obj.date[1]) ? obj.date[1] : currentMonth; + + // Update title + calendarLabelYear.innerHTML = obj.date[0]; + calendarLabelMonth.innerHTML = months[selectedMonth-1]; + + // Table + var table = document.createElement('table'); + table.setAttribute('width', '100%'); + + // Row + var row = null; + + // Calendar table + for (var i = 0; i < 12; i++) { + if (! (i % 4)) { + // Reset cells container + var row = document.createElement('tr'); + row.setAttribute('align', 'center'); + table.appendChild(row); + } + + // Create cell + var cell = document.createElement('td'); + cell.classList.add('jcalendar-set-month'); + cell.setAttribute('data-value', i+1); + cell.innerText = months[i]; + + if (obj.options.validRange) { + var current = selectedYear + '-' + jSuites.two(i+1); + if (! obj.options.validRange[0] || current >= obj.options.validRange[0].substr(0,7)) { + var test1 = true; + } else { + var test1 = false; + } + + if (! obj.options.validRange[1] || current <= obj.options.validRange[1].substr(0,7)) { + var test2 = true; + } else { + var test2 = false; + } + + if (! (test1 && test2)) { + cell.classList.add('jcalendar-disabled'); + } + } + + if (i+1 == selectedMonth) { + cell.classList.add('jcalendar-selected'); + } + + if (currentYear == selectedYear && i+1 == currentMonth) { + cell.style.fontWeight = 'bold'; + } + + row.appendChild(cell); + } + + calendarBody.innerHTML = ''; + calendarBody.children[0].children[0].appendChild(table); + + // Update + updateActions(); + } + + obj.getYears = function() { + // Mode + obj.options.mode = 'years'; + + // Current date + var date = new Date(); + var currentYear = date.getFullYear(); + var selectedYear = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear()); + + // Array of years + var y = []; + for (var i = 0; i < 25; i++) { + y[i] = parseInt(obj.date[0]) + (i - 12); + } + + // Assembling the year tables + var table = document.createElement('table'); + table.setAttribute('width', '100%'); + + for (var i = 0; i < 25; i++) { + if (! (i % 5)) { + // Reset cells container + var row = document.createElement('tr'); + row.setAttribute('align', 'center'); + table.appendChild(row); + } + + // Create cell + var cell = document.createElement('td'); + cell.classList.add('jcalendar-set-year'); + cell.innerText = y[i]; + + if (selectedYear == y[i]) { + cell.classList.add('jcalendar-selected'); + } + + if (currentYear == y[i]) { + cell.style.fontWeight = 'bold'; + } + + row.appendChild(cell); + } + + calendarBody.innerHTML = ''; + calendarBody.firstChild.firstChild.appendChild(table); + + // Update + updateActions(); + } + + 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 element = jSuites.findElement(e.target, 'jcalendar-container'); + if (element) { + var action = e.target.className; + + // Object id + if (action == 'jcalendar-prev') { + obj.prev(); + } else if (action == 'jcalendar-next') { + obj.next(); + } else if (action == 'jcalendar-month') { + obj.getMonths(); + } else if (action == 'jcalendar-year') { + obj.getYears(); + } else if (action == 'jcalendar-set-year') { + obj.date[0] = e.target.innerText; + if (obj.options.type == 'year-month-picker') { + obj.getMonths(); + } else { + obj.getDays(); + } + } else if (e.target.classList.contains('jcalendar-set-month')) { + var month = parseInt(e.target.getAttribute('data-value')); + if (obj.options.type == 'year-month-picker') { + obj.update(e.target, month); + } else { + obj.date[1] = month; + obj.getDays(); + } + } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update' || action == 'jcalendar-close') { + obj.close(); + } else if (action == 'jcalendar-backdrop') { + obj.close(false, false); + } else if (action == 'jcalendar-reset') { + obj.reset(); + } else if (e.target.classList.contains('jcalendar-set-day') && e.target.innerText) { + obj.update(e.target); + } + } else { + obj.close(); + } + } + + 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) { + obj.setValue(test); + } + } + } + + // 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'); + } + + // Event + if (typeof(obj.options.onupdate) == 'function') { + obj.options.onupdate(el, obj.getValue()); + } + } + + var calendar = null; + var calendarReset = null; + var calendarConfirm = null; + var calendarContainer = null; + var calendarContent = null; + var calendarLabelYear = null; + var calendarLabelMonth = null; + var calendarTable = null; + var calendarBody = null; + + var calendarControls = null; + var calendarControlsTime = null; + var calendarControlsUpdate = null; + var calendarControlsUpdateButton = null; + var calendarSelectHour = null; + var calendarSelectMin = null; + + var init = function() { + // Get value from initial element if that is an input + if (el.tagName == 'INPUT' && el.value) { + options.value = el.value; + } + + // Calendar DOM elements + calendarReset = document.createElement('div'); + calendarReset.className = 'jcalendar-reset'; + + calendarConfirm = document.createElement('div'); + calendarConfirm.className = 'jcalendar-confirm'; + + calendarControls = document.createElement('div'); + calendarControls.className = 'jcalendar-controls' + calendarControls.style.borderBottom = '1px solid #ddd'; + calendarControls.appendChild(calendarReset); + calendarControls.appendChild(calendarConfirm); + + calendarContainer = document.createElement('div'); + calendarContainer.className = 'jcalendar-container'; + + calendarContent = document.createElement('div'); + calendarContent.className = 'jcalendar-content'; + calendarContainer.appendChild(calendarContent); + + // Main element + if (el.tagName == 'DIV') { + calendar = el; + calendar.classList.add('jcalendar-inline'); + } else { + // Add controls to the screen + calendarContent.appendChild(calendarControls); + + calendar = document.createElement('div'); + calendar.className = 'jcalendar'; + } + calendar.classList.add('jcalendar-container'); + 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 + calendarLabelYear = document.createElement('span'); + calendarLabelYear.className = 'jcalendar-year'; + 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 calendarHeader = document.createElement('thead'); + var calendarHeaderRow = document.createElement('tr'); + calendarHeaderRow.appendChild(calendarHeaderPrev); + calendarHeaderRow.appendChild(calendarHeaderTitle); + calendarHeaderRow.appendChild(calendarHeaderNext); + calendarHeader.appendChild(calendarHeaderRow); + + calendarTable = document.createElement('table'); + calendarBody = document.createElement('tbody'); + calendarTable.setAttribute('cellpadding', '0'); + calendarTable.setAttribute('cellspacing', '0'); + calendarTable.appendChild(calendarHeader); + calendarTable.appendChild(calendarBody); + calendarTableContainer.appendChild(calendarTable); + + 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); + } + + 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'; + + calendarControlsTime = document.createElement('div'); + calendarControlsTime.className = 'jcalendar-time'; + calendarControlsTime.style.maxWidth = '140px'; + calendarControlsTime.appendChild(calendarSelectHour); + calendarControlsTime.appendChild(calendarSelectMin); + + calendarControlsUpdateButton = document.createElement('button'); + calendarControlsUpdateButton.setAttribute('type', 'button'); + calendarControlsUpdateButton.className = 'jcalendar-update'; + + 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); + + // 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(); + }); + + el.onmouseup = function() { + obj.open(); + } + + if ('ontouchend' in document.documentElement === true) { + calendar.addEventListener("touchend", mouseUpControls); + } else { + calendar.addEventListener("mouseup", mouseUpControls); + } + + // Global controls + if (! jSuites.calendar.hasEvents) { + // Execute only one time + jSuites.calendar.hasEvents = true; + // Enter and Esc + document.addEventListener("keydown", jSuites.calendar.keydown); + } + + // Set configuration + obj.setOptions(options); + + // Append element to the DOM + if (el.tagName == 'INPUT') { + el.parentNode.insertBefore(calendar, el.nextSibling); + // Add properties + el.setAttribute('autocomplete', 'off'); + // 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]; + } + } + + // Default opened + if (obj.options.opened == true) { + obj.open(); + } + + // Change method + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Keep object available from the node + el.calendar = calendar.calendar = obj; + } + + init(); + + return obj; +}); + +jSuites.calendar.keydown = function(e) { + var calendar = null; + if (calendar = jSuites.calendar.current) { + if (e.which == 13) { + // ENTER + calendar.close(false, true); + } else if (e.which == 27) { + // ESC + calendar.close(false, false); + } + } +} + +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 (Array.isArray(date)) { + var y = date[0]; + var m = date[1]; + var d = date[2]; + var h = date[3]; + var i = date[4]; + var s = date[5]; + } else { + 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"); + if (d >= 0) { + d = v1.substr(d,2); + if (parseInt(d) != d || d > 31) { + test = 0; + } + } else { + d = '01'; + } + + // 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 ''; +} + +/** + * Date to number + */ +jSuites.calendar.dateToNum = function(a, b) { + a = new Date(a); + if (! b) { + b = '1899-12-30 ' + a.getHours() + ':' + a.getMinutes() + ':' + a.getSeconds(); + } + b = new Date(b); + var v = a.getTime() - b.getTime(); + return Math.round(v / 86400000); +} + +/** + * Number to date + */ +jSuites.calendar.numToDate = function(value) { + var d = new Date(Math.round((value - 25569)*86400*1000)); + return d.getFullYear() + "-" + jSuites.two(d.getMonth()+1) + "-" + jSuites.two(d.getDate()) + ' 00:00:00'; +} + +// Helper to convert date into string +jSuites.calendar.getDateString = function(value, options) { + if (! options) { + var options = {}; + } + + // Labels + if (options && typeof(options) == 'object') { + var format = options.format; + } else { + var format = options; + } + + if (! format) { + format = 'YYYY-MM-DD'; + } + + // Convert to number of hours + if (typeof(value) == 'number' && format.indexOf('[h]') >= 0) { + var result = parseFloat(24 * Number(value)); + if (format.indexOf('mm') >= 0) { + var h = (''+result).split('.'); + if (h[1]) { + var d = 60 * parseFloat('0.' + h[1]) + d = parseFloat(d.toFixed(2)); + } else { + var d = 0; + } + result = parseInt(h[0]) + ':' + jSuites.two(d); + } + return result; + } + + // Date instance + if (value instanceof Date) { + value = jSuites.calendar.now(value); + } else if (value && jSuites.isNumeric(value)) { + value = jSuites.calendar.numToDate(value); + } + + // Tokens + var tokens = [ 'DAY', 'WD', 'DDDD', 'DDD', 'DD', 'D', 'Q', 'HH24', 'HH12', 'HH', 'H', 'AM/PM', 'MI', 'SS', 'MS', 'YYYY', 'YYY', 'YY', 'Y', 'MONTH', 'MON', 'MMMMM', 'MMMM', 'MMM', 'MM', 'M', '.' ]; + + // Expression to extract all tokens from the string + var e = new RegExp(tokens.join('|'), 'gi'); + // Extract + var t = format.match(e); + + // Compatibility with excel + for (var i = 0; i < t.length; i++) { + if (t[i].toUpperCase() == 'MM') { + // Not a month, correct to minutes + if (t[i-1] && t[i-1].toUpperCase().indexOf('H') >= 0) { + t[i] = 'mi'; + } else if (t[i-2] && t[i-2].toUpperCase().indexOf('H') >= 0) { + t[i] = 'mi'; + } else if (t[i+1] && t[i+1].toUpperCase().indexOf('S') >= 0) { + t[i] = 'mi'; + } else if (t[i+2] && t[i+2].toUpperCase().indexOf('S') >= 0) { + t[i] = 'mi'; + } + } + } + + // Object + var o = { + tokens: t + } + + // Value + if (value) { + var d = ''+value; + var splitStr = (d.indexOf('T') !== -1) ? 'T' : ' '; + d = d.split(splitStr); + + var h = 0; + var m = 0; + var s = 0; + + if (d[1]) { + h = d[1].split(':'); + m = h[1] ? h[1] : 0; + s = h[2] ? h[2] : 0; + h = h[0] ? h[0] : 0; + } + + 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) { + + // Data + o.data = [ d[0], d[1], d[2], h, m, s ]; + + // Value + o.value = []; + + // Calendar instance + var calendar = new Date(o.data[0], o.data[1]-1, o.data[2], o.data[3], o.data[4], o.data[5]); + + // Get method + var get = function(i) { + // Token + var t = this.tokens[i]; + // Case token + var s = t.toUpperCase(); + var v = null; + + if (s === 'YYYY') { + v = this.data[0]; + } else if (s === 'YYY') { + v = this.data[0].substring(1,4); + } else if (s === 'YY') { + v = this.data[0].substring(2,4); + } else if (s === 'Y') { + v = this.data[0].substring(3,4); + } else if (t === 'MON') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0,3).toUpperCase(); + } else if (t === 'mon') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0,3).toLowerCase(); + } else if (t === 'MONTH') { + v = jSuites.calendar.months[calendar.getMonth()].toUpperCase(); + } else if (t === 'month') { + v = jSuites.calendar.months[calendar.getMonth()].toLowerCase(); + } else if (s === 'MMMMM') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0, 1); + } else if (s === 'MMMM' || t === 'Month') { + v = jSuites.calendar.months[calendar.getMonth()]; + } else if (s === 'MMM' || t == 'Mon') { + v = jSuites.calendar.months[calendar.getMonth()].substr(0,3); + } else if (s === 'MM') { + v = jSuites.two(this.data[1]); + } else if (s === 'M') { + v = calendar.getMonth()+1; + } else if (t === 'DAY') { + v = jSuites.calendar.weekdays[calendar.getDay()].toUpperCase(); + } else if (t === 'day') { + v = jSuites.calendar.weekdays[calendar.getDay()].toLowerCase(); + } else if (s === 'DDDD' || t == 'Day') { + v = jSuites.calendar.weekdays[calendar.getDay()]; + } else if (s === 'DDD') { + v = jSuites.calendar.weekdays[calendar.getDay()].substr(0,3); + } else if (s === 'DD') { + v = jSuites.two(this.data[2]); + } else if (s === 'D') { + v = this.data[2]; + } else if (s === 'Q') { + v = Math.floor((calendar.getMonth() + 3) / 3); + } else if (s === 'HH24' || s === 'HH') { + v = jSuites.two(this.data[3]); + } else if (s === 'HH12') { + if (this.data[3] > 12) { + v = jSuites.two(this.data[3] - 12); + } else { + v = jSuites.two(this.data[3]); + } + } else if (s === 'H') { + v = this.data[3]; + } else if (s === 'MI') { + v = jSuites.two(this.data[4]); + } else if (s === 'SS') { + v = jSuites.two(this.data[5]); + } else if (s === 'MS') { + v = calendar.getMilliseconds(); + } else if (s === 'AM/PM') { + if (this.data[3] >= 12) { + v = 'PM'; + } else { + v = 'AM'; + } + } else if (s === 'WD') { + v = jSuites.calendar.weekdays[calendar.getDay()]; + } + + if (v === null) { + this.value[i] = this.tokens[i]; + } else { + this.value[i] = v; + } + } + + for (var i = 0; i < o.tokens.length; i++) { + get.call(o, i); + } + // Put pieces together + value = o.value.join(''); + } else { + value = ''; + } + } + + return value; +} + +// Jsuites calendar labels +jSuites.calendar.weekdays = [ 'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday' ]; +jSuites.calendar.months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; +jSuites.calendar.weekdaysShort = [ 'Sun','Mon','Tue','Wed','Thu','Fri','Sat' ]; +jSuites.calendar.monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + + +jSuites.color = (function(el, options) { + // Already created, update options + if (el.color) { + return el.color.setOptions(options, true); + } + + // New instance + var obj = { type: 'color' }; + obj.options = {}; + + var container = null; + var backdrop = null; + var content = null; + var resetButton = null; + var closeButton = null; + var tabs = null; + var jsuitesTabs = null; + + /** + * Update options + */ + obj.setOptions = function(options, reset) { + /** + * @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, + opened: false, + } + + if (! options) { + options = {}; + } + + if (options && ! options.palette) { + // Default pallete + options.palette = jSuites.palette(); + } + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Update the text of the controls, if they have already been created + if (resetButton) { + resetButton.innerHTML = obj.options.resetLabel; + } + if (closeButton) { + closeButton.innerHTML = obj.options.doneLabel; + } + + // Update the pallete + if (obj.options.palette && jsuitesTabs) { + jsuitesTabs.updateContent(0, table()); + } + + // Value + if (typeof obj.options.value === 'string') { + el.value = obj.options.value; + } + + // Placeholder + if (obj.options.placeholder) { + el.setAttribute('placeholder', obj.options.placeholder); + } else { + if (el.getAttribute('placeholder')) { + el.removeAttribute('placeholder'); + } + } + + return obj; + } + + /** + * Open color pallete + */ + obj.open = function() { + if (! container.classList.contains('jcolor-focus')) { + // Start tracking + jSuites.tracking(obj, true); + + // 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'; + } + } + } + + if (typeof(obj.options.onopen) == 'function') { + obj.options.onopen(el); + } + + jsuitesTabs.setBorder(jsuitesTabs.getActive()); + + // Update sliders + if (obj.options.value) { + var rgb = HexToRgb(obj.options.value); + + rgbInputs.forEach(function(rgbInput, index) { + rgbInput.value = rgb[index]; + rgbInput.dispatchEvent(new Event('input')); + }); + } + } + } + + /** + * Close color pallete + */ + obj.close = function(ignoreEvents) { + if (container.classList.contains('jcolor-focus')) { + // Remove focus + container.classList.remove('jcolor-focus'); + // Make sure backdrop is hidden + backdrop.style.display = ''; + // Call related events + if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { + obj.options.onclose(el); + } + // Stop the object + jSuites.tracking(obj, false); + } + + return obj.options.value; + } + + /** + * Set value + */ + obj.setValue = function(color) { + if (! color) { + color = ''; + } + + if (color != obj.options.value) { + obj.options.value = color; + slidersResult = 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'); + } + + // Onchange + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, color); + } + + // Changes + if (el.value != obj.options.value) { + // Set input value + el.value = obj.options.value; + // Element onchange native + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + + if (obj.options.closeOnChange == true) { + obj.close(); + } + } + } + + /** + * Get value + */ + obj.getValue = function() { + return obj.options.value; + } + + var backdropClickControl = false; + + // Converts a number in decimal to hexadecimal + var decToHex = function(num) { + var hex = num.toString(16); + return hex.length === 1 ? "0" + hex : hex; + } + + // Converts a color in rgb to hexadecimal + var rgbToHex = function(r, g, b) { + return "#" + decToHex(r) + decToHex(g) + decToHex(b); + } + + // Converts a number in hexadecimal to decimal + var hexToDec = function(hex) { + return parseInt('0x' + hex); + } + + // Converts a color in hexadecimal to rgb + var HexToRgb = function(hex) { + return [hexToDec(hex.substr(1, 2)), hexToDec(hex.substr(3, 2)), hexToDec(hex.substr(5, 2))] + } + + var table = function() { + // Content of the first tab + var tableContainer = document.createElement('div'); + tableContainer.className = 'jcolor-grid'; + + // Cells + obj.values = []; + + // Table pallete + var t = document.createElement('table'); + t.setAttribute('cellpadding', '7'); + t.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.length < 7 && 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; + } + t.appendChild(tr); + } + + // Append to the table + tableContainer.appendChild(t); + + // Select color + tableContainer.addEventListener("mousedown", function(e) { + if (e.target.tagName == 'TD') { + var value = e.target.getAttribute('data-value'); + if (value) { + obj.setValue(value); + } + } + }); + + return tableContainer; + } + + // Canvas where the image will be rendered + var canvas = document.createElement('canvas'); + canvas.width = 200; + canvas.height = 160; + var context = canvas.getContext("2d"); + + var resizeCanvas = function() { + // Specifications necessary to correctly obtain colors later in certain positions + var m = tabs.firstChild.getBoundingClientRect(); + canvas.width = m.width - 14; + gradient() + } + + var gradient = function() { + var g = context.createLinearGradient(0, 0, canvas.width, 0); + // Create color gradient + g.addColorStop(0, "rgb(255,0,0)"); + g.addColorStop(0.15, "rgb(255,0,255)"); + g.addColorStop(0.33, "rgb(0,0,255)"); + g.addColorStop(0.49, "rgb(0,255,255)"); + g.addColorStop(0.67, "rgb(0,255,0)"); + g.addColorStop(0.84, "rgb(255,255,0)"); + g.addColorStop(1, "rgb(255,0,0)"); + context.fillStyle = g; + context.fillRect(0, 0, canvas.width, canvas.height); + g = context.createLinearGradient(0, 0, 0, canvas.height); + g.addColorStop(0, "rgba(255,255,255,1)"); + g.addColorStop(0.5, "rgba(255,255,255,0)"); + g.addColorStop(0.5, "rgba(0,0,0,0)"); + g.addColorStop(1, "rgba(0,0,0,1)"); + context.fillStyle = g; + context.fillRect(0, 0, canvas.width, canvas.height); + } + + var hsl = function() { + var element = document.createElement('div'); + element.className = "jcolor-hsl"; + + var point = document.createElement('div'); + point.className = 'jcolor-point'; + + var div = document.createElement('div'); + div.appendChild(canvas); + div.appendChild(point); + element.appendChild(div); + + // Moves the marquee point to the specified position + var update = function(buttons, x, y) { + if (buttons === 1) { + var rect = element.getBoundingClientRect(); + var left = x - rect.left; + var top = y - rect.top; + if (left < 0) { + left = 0; + } + if (top < 0) { + top = 0; + } + if (left > rect.width) { + left = rect.width; + } + if (top > rect.height) { + top = rect.height; + } + point.style.left = left + 'px'; + point.style.top = top + 'px'; + var pixel = context.getImageData(left, top, 1, 1).data; + slidersResult = rgbToHex(pixel[0], pixel[1], pixel[2]); + } + } + + // Applies the point's motion function to the div that contains it + element.addEventListener('mousedown', function(e) { + update(e.buttons, e.clientX, e.clientY); + }); + + element.addEventListener('mousemove', function(e) { + update(e.buttons, e.clientX, e.clientY); + }); + + element.addEventListener('touchmove', function(e) { + update(1, e.changedTouches[0].clientX, e.changedTouches[0].clientY); + }); + + return element; + } + + var slidersResult = ''; + + var rgbInputs = []; + + var changeInputColors = function() { + if (slidersResult !== '') { + for (var j = 0; j < rgbInputs.length; j++) { + var currentColor = HexToRgb(slidersResult); + + currentColor[j] = 0; + + var newGradient = 'linear-gradient(90deg, rgb('; + newGradient += currentColor.join(', '); + newGradient += '), rgb('; + + currentColor[j] = 255; + + newGradient += currentColor.join(', '); + newGradient += '))'; + + rgbInputs[j].style.backgroundImage = newGradient; + } + } + } + + var sliders = function() { + // Content of the third tab + var slidersElement = document.createElement('div'); + slidersElement.className = 'jcolor-sliders'; + + var slidersBody = document.createElement('div'); + + // Creates a range-type input with the specified name + var createSliderInput = function(name) { + var inputContainer = document.createElement('div'); + inputContainer.className = 'jcolor-sliders-input-container'; + + var label = document.createElement('label'); + label.innerText = name; + + var subContainer = document.createElement('div'); + subContainer.className = 'jcolor-sliders-input-subcontainer'; + + var input = document.createElement('input'); + input.type = 'range'; + input.min = 0; + input.max = 255; + input.value = 0; + + inputContainer.appendChild(label); + subContainer.appendChild(input); + + var value = document.createElement('div'); + value.innerText = input.value; + + input.addEventListener('input', function() { + value.innerText = input.value; + }); + + subContainer.appendChild(value); + inputContainer.appendChild(subContainer); + + slidersBody.appendChild(inputContainer); + + return input; + } + + // Creates red, green and blue inputs + rgbInputs = [ + createSliderInput('Red'), + createSliderInput('Green'), + createSliderInput('Blue'), + ]; + + slidersElement.appendChild(slidersBody); + + // Element that prints the current color + var slidersResultColor = document.createElement('div'); + slidersResultColor.className = 'jcolor-sliders-final-color'; + + var resultElement = document.createElement('div'); + resultElement.style.visibility = 'hidden'; + resultElement.innerText = 'a'; + slidersResultColor.appendChild(resultElement) + + // Update the element that prints the current color + var updateResult = function() { + var resultColor = rgbToHex(parseInt(rgbInputs[0].value), parseInt(rgbInputs[1].value), parseInt(rgbInputs[2].value)); + + resultElement.innerText = resultColor; + resultElement.style.color = resultColor; + resultElement.style.removeProperty('visibility'); + + slidersResult = resultColor; + } + + // Apply the update function to color inputs + rgbInputs.forEach(function(rgbInput) { + rgbInput.addEventListener('input', function() { + updateResult(); + changeInputColors(); + }); + }); + + slidersElement.appendChild(slidersResultColor); + + return slidersElement; + } + + var init = function() { + // Initial options + obj.setOptions(options); + + // Add a proper input tag when the element is an input + if (el.tagName == 'INPUT') { + el.classList.add('jcolor-input'); + el.readOnly = true; + } + + // Table container + container = document.createElement('div'); + container.className = 'jcolor'; + + // Table container + backdrop = document.createElement('div'); + backdrop.className = 'jcolor-backdrop'; + container.appendChild(backdrop); + + // Content + content = document.createElement('div'); + content.className = 'jcolor-content'; + + // Controls + var controls = document.createElement('div'); + controls.className = 'jcolor-controls'; + content.appendChild(controls); + + // Reset button + resetButton = document.createElement('div'); + resetButton.className = 'jcolor-reset'; + resetButton.innerHTML = obj.options.resetLabel; + resetButton.onclick = function(e) { + obj.setValue(''); + obj.close(); + } + controls.appendChild(resetButton); + + // Close button + closeButton = document.createElement('div'); + closeButton.className = 'jcolor-close'; + closeButton.innerHTML = obj.options.doneLabel; + closeButton.onclick = function(e) { + if (jsuitesTabs.getActive() > 0) { + obj.setValue(slidersResult); + } + obj.close(); + } + controls.appendChild(closeButton); + + // Element that will be used to create the tabs + tabs = document.createElement('div'); + content.appendChild(tabs); + + // Starts the jSuites tabs component + jsuitesTabs = jSuites.tabs(tabs, { + animation: true, + data: [ + { + title: 'Grid', + contentElement: table(), + }, + { + title: 'Spectrum', + contentElement: hsl(), + }, + { + title: 'Sliders', + contentElement: sliders(), + } + ], + onchange: function(element, instance, index) { + if (index === 1) { + resizeCanvas(); + } else { + var color = slidersResult !== '' ? slidersResult : obj.getValue(); + + if (index === 2 && color) { + var rgb = HexToRgb(color); + + rgbInputs.forEach(function(rgbInput, index) { + rgbInput.value = rgb[index]; + rgbInput.dispatchEvent(new Event('input')); + }); + } + } + }, + palette: 'modern', + }); + + container.appendChild(content); + + // Insert picker after the element + if (el.tagName == 'INPUT') { + el.parentNode.insertBefore(container, el.nextSibling); + } else { + el.appendChild(container); + } + + /** + * If element is focus open the picker + */ + el.addEventListener("mouseup", function(e) { + obj.open(); + }); + + backdrop.addEventListener("mousedown", function(e) { + backdropClickControl = true; + }); + + backdrop.addEventListener("mouseup", function(e) { + if (backdropClickControl) { + obj.close(); + backdropClickControl = false; + } + }); + + // If the picker is open on the spectrum tab, it changes the canvas size when the window size is changed + window.addEventListener('resize', function() { + if (container.classList.contains('jcolor-focus') && jsuitesTabs.getActive() == 1) { + resizeCanvas(); + } + }); + + // Default opened + if (obj.options.opened == true) { + obj.open(); + } + + // Change + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Keep object available from the node + el.color = obj; + + // Container shortcut + container.color = obj; + } + + init(); + + 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.tooltip) { + itemContainer.setAttribute('title', item.tooltip); + } + + 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("mousedown", function(e) { + e.preventDefault(); + }); + itemContainer.addEventListener("mouseup", function() { + // Execute method + this.method(this); + }); + } + itemContainer.appendChild(itemText); + + if (item.submenu) { + var itemIconSubmenu = document.createElement('span'); + itemIconSubmenu.innerHTML = "►"; + 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) { + obj.close(); + }); + + 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) { + // Already created, update options + if (el.dropdown) { + return el.dropdown.setOptions(options, true); + } + + // New instance + var obj = { type: 'dropdown' }; + obj.options = {}; + + // Success + var success = function(data, val) { + // Set data + if (data && data.length) { + // Sort + if (obj.options.sortResults !== false) { + if(typeof obj.options.sortResults == "function") { + data.sort(obj.options.sortResults); + } else { + data.sort(sortData); + } + } + + obj.setData(data); + + // Onload method + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj, data, val); + } + } + + // Set value + if (val) { + applyValue(val); + } + + // Component value + if (val === undefined || val === null) { + obj.options.value = ''; + } + el.value = obj.options.value; + + // Open dropdown + if (obj.options.opened == true) { + obj.open(); + } + } + + + // Default sort + var sortData = function(itemA, itemB) { + var testA, testB; + if(typeof itemA == "string") { + testA = itemA; + } else { + if(itemA.text) { + testA = itemA.text; + } else if(itemA.name) { + testA = itemA.name; + } + } + + if(typeof itemB == "string") { + testB = itemB; + } else { + if(itemB.text) { + testB = itemB.text; + } else if(itemB.name) { + testB = itemB.name; + } + } + + if(typeof testA == "string" || typeof testB == "string") { + if(typeof testA != "string") { testA = ""+testA; } + if(typeof testB != "string") { testB = ""+testB; } + return testA.localeCompare(testB); + } else { + return testA - testB; + } + } + + /** + * Reset the options for the dropdown + */ + var resetValue = function() { + // Reset value container + obj.value = {}; + // 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 options + obj.options.value = ''; + } + + /** + * Apply values to the dropdown + */ + var applyValue = function(values) { + // Reset the current values + resetValue(); + + // Read values + if (values !== null) { + if (! values) { + if (typeof(obj.value['']) !== 'undefined') { + obj.value[''] = ''; + } + } else { + if (! Array.isArray(values)) { + values = ('' + values).split(';'); + } + for (var i = 0; i < values.length; i++) { + obj.value[values[i]] = ''; + } + } + } + + // Update the DOM + for (var i = 0; i < obj.items.length; i++) { + if (typeof(obj.value[Value(i)]) !== 'undefined') { + if (obj.items[i].element) { + obj.items[i].element.classList.add('jdropdown-selected') + } + obj.items[i].selected = true; + + // Keep label + obj.value[Value(i)] = Text(i); + } + } + + // Global value + obj.options.value = Object.keys(obj.value).join(';'); + + // Update labels + obj.header.value = obj.getText(); + } + + // Get the value of one item + var Value = function(k, v) { + // Legacy purposes + if (! obj.options.format) { + var property = 'value'; + } else { + var property = 'id'; + } + + if (obj.items[k]) { + if (v !== undefined) { + return obj.items[k].data[property] = v; + } else { + return obj.items[k].data[property]; + } + } + + return ''; + } + + // Get the label of one item + var Text = function(k, v) { + // Legacy purposes + if (! obj.options.format) { + var property = 'text'; + } else { + var property = 'name'; + } + + if (obj.items[k]) { + if (v !== undefined) { + return obj.items[k].data[property] = v; + } else { + return obj.items[k].data[property]; + } + } + + return ''; + } + + var getValue = function() { + return Object.keys(obj.value); + } + + var getText = function() { + var data = []; + var k = Object.keys(obj.value); + for (var i = 0; i < k.length; i++) { + data.push(obj.value[k[i]]); + } + return data; + } + + obj.setOptions = function(options, reset) { + if (! options) { + options = {}; + } + + // Default configuration + var defaults = { + url: null, + data: [], + format: 0, + 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, + onbeforeinsert: null, + sortResults: false, + autofocus: false, + } + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Force autocomplete search + if (obj.options.remoteSearch == true || obj.options.type === 'searchbar') { + obj.options.autocomplete = true; + } + + // New options + if (obj.options.newOptions == true) { + obj.header.classList.add('jdropdown-add'); + } else { + obj.header.classList.remove('jdropdown-add'); + } + + // Autocomplete + if (obj.options.autocomplete == true) { + obj.header.removeAttribute('readonly'); + } else { + obj.header.setAttribute('readonly', 'readonly'); + } + + // Place holder + if (obj.options.placeholder) { + obj.header.setAttribute('placeholder', obj.options.placeholder); + } else { + obj.header.removeAttribute('placeholder'); + } + + // Remove specific dropdown typing to add again + el.classList.remove('jdropdown-searchbar'); + el.classList.remove('jdropdown-picker'); + el.classList.remove('jdropdown-list'); + + 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) { + if (obj.options.autocomplete) { + el.classList.add('jdropdown-searchbar'); + obj.options.type = 'searchbar'; + } else { + 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; + } else { + el.style.removeProperty('width'); + el.style.removeProperty('min-width'); + } + + el.classList.add('jdropdown-default'); + obj.options.type = 'default'; + } + } + + // Close button + if (obj.options.type == 'searchbar') { + containerHeader.appendChild(closeButton); + } else { + container.insertBefore(closeButton, container.firstChild); + } + + // Load the content + if (obj.options.url && ! options.data) { + jSuites.ajax({ + url: obj.options.url, + method: 'GET', + dataType: 'json', + success: function(data) { + if (data) { + success(data, obj.options.value); + } + } + }); + } else { + success(obj.options.data, obj.options.value); + } + + // Return the instance + return obj; + } + + // Helpers + var containerHeader = null; + var container = null; + var content = null; + var closeButton = null; + var resetButton = null; + var backdrop = null; + + var keyTimer = null; + + /** + * Init dropdown + */ + var init = function() { + // Do not accept null + if (! options) { + 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; + } + + // Place holder + if (! options.placeholder && el.getAttribute('placeholder')) { + options.placeholder = el.getAttribute('placeholder'); + } + + // Value container + obj.value = {}; + // Containers + obj.items = []; + obj.groups = []; + // Search options + obj.search = ''; + obj.results = null; + + // Create dropdown + el.classList.add('jdropdown'); + + // Header container + containerHeader = document.createElement('div'); + containerHeader.className = 'jdropdown-container-header'; + + // Header + obj.header = document.createElement('input'); + obj.header.className = 'jdropdown-header'; + obj.header.type = 'text'; + obj.header.setAttribute('autocomplete', 'off'); + obj.header.onfocus = function() { + if (typeof(obj.options.onfocus) == 'function') { + obj.options.onfocus(el); + } + } + + obj.header.onblur = function() { + if (typeof(obj.options.onblur) == 'function') { + obj.options.onblur(el); + } + } + + obj.header.onkeyup = function(e) { + if (obj.options.autocomplete == true && ! 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 { + if (! obj.options.autocomplete) { + obj.next(e.key); + } + } + } + + // Global controls + if (! jSuites.dropdown.hasEvents) { + // Execute only one time + jSuites.dropdown.hasEvents = true; + // Enter and Esc + document.addEventListener("keydown", jSuites.dropdown.keydown); + } + + // Container + container = document.createElement('div'); + container.className = 'jdropdown-container'; + + // Dropdown content + content = document.createElement('div'); + content.className = 'jdropdown-content'; + + // Close button + closeButton = document.createElement('div'); + closeButton.className = 'jdropdown-close'; + closeButton.innerHTML = 'Done'; + + // Reset button + resetButton = document.createElement('div'); + resetButton.className = 'jdropdown-reset'; + resetButton.innerHTML = 'x'; + resetButton.onclick = function() { + obj.reset(); + obj.close(); + } + + // Create backdrop + backdrop = document.createElement('div'); + backdrop.className = 'jdropdown-backdrop'; + + // Append elements + containerHeader.appendChild(obj.header); + + container.appendChild(content); + el.appendChild(containerHeader); + el.appendChild(container); + el.appendChild(backdrop); + + // Set the otiptions + obj.setOptions(options); + + if ('ontouchsend' in document.documentElement === true) { + el.addEventListener('touchsend', jSuites.dropdown.mouseup); + } else { + el.addEventListener('mouseup', jSuites.dropdown.mouseup); + } + + // Lazyloading + if (obj.options.lazyLoading == true) { + jSuites.lazyLoading(content, { + loadUp: obj.loadUp, + loadDown: obj.loadDown, + }); + } + + content.onwheel = function(e) { + e.stopPropagation(); + } + + // Change method + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(obj.options.multiple ? true : false); + } else { + obj.setValue(val); + } + } + + // Keep object available from the node + el.dropdown = obj; + } + + /** + * Get the current remote source of data URL + */ + obj.getUrl = function() { + return obj.options.url; + } + + /** + * Set the new data from a remote source + * @param {string} url - url from the remote source + * @param {function} callback - callback when the data is loaded + */ + obj.setUrl = function(url, callback) { + obj.options.url = url; + + jSuites.ajax({ + url: obj.options.url, + method: 'GET', + dataType: 'json', + success: function(data) { + obj.setData(data); + // Callback + if (typeof(callback) == 'function') { + callback(obj); + } + } + }); + } + + /** + * Set ID for one item + */ + obj.setId = function(item, v) { + // Legacy purposes + if (! obj.options.format) { + var property = 'value'; + } else { + var property = 'id'; + } + + if (typeof(item) == 'object') { + item[property] = v; + } else { + obj.items[item].data[property] = v; + } + } + + /** + * Add a new item + * @param {string} title - title of the new item + * @param {string} id - value/id of the new item + */ + obj.add = function(title, id) { + if (! title) { + var current = obj.options.autocomplete == true ? obj.header.value : ''; + var title = prompt(jSuites.translate('Add A New Option'), current); + if (! title) { + return false; + } + } + + // Id + if (! id) { + id = jSuites.guid(); + } + + // Create new item + if (! obj.options.format) { + var item = { + value: id, + text: title, + } + } else { + var item = { + id: id, + name: title, + } + } + + // Callback + if (typeof(obj.options.onbeforeinsert) == 'function') { + var ret = obj.options.onbeforeinsert(obj, item); + if (ret === false) { + return false; + } else if (ret) { + item = ret; + } + } + + // Add item to the main list + obj.options.data.push(item); + + // Create DOM + 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, item, newItem); + } + + // Show content + if (content.style.display == 'none') { + content.style.display = ''; + } + + // Search? + if (obj.results) { + obj.results.push(newItem); + } + + return item; + } + + /** + * Create a new item + */ + obj.createItem = function(data, group, groupName) { + // Keep the correct source of data + if (! obj.options.format) { + if (! data.value && data.id !== undefined) { + data.value = data.id; + //delete data.id; + } + if (! data.text && data.name !== undefined) { + data.text = data.name; + //delete data.name; + } + } else { + if (! data.id && data.value !== undefined) { + data.id = data.value; + //delete data.value; + } + if (! data.name && data.text !== undefined) { + data.name = data.text + //delete data.text; + } + } + + // Create item + var item = {}; + item.element = document.createElement('div'); + item.element.className = 'jdropdown-item'; + item.element.indexValue = obj.items.length; + item.data = data; + + // Groupd DOM + if (group) { + item.group = group; + } + + // Id + if (data.id) { + item.element.setAttribute('id', data.id); + } + + // Disabled + if (data.disabled == true) { + item.element.setAttribute('data-disabled', true); + } + + // Tooltip + if (data.tooltip) { + item.element.setAttribute('title', data.tooltip); + } + + // 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.icon) { + var icon = document.createElement('span'); + icon.className = "jdropdown-icon material-icons"; + icon.innerText = data.icon; + if (! data.title) { + icon.classList.add('jdropdown-icon-small'); + } + if (data.color) { + icon.style.color = data.color; + } + item.element.appendChild(icon); + } else if (data.color) { + var color = document.createElement('div'); + color.className = 'jdropdown-color'; + color.style.backgroundColor = data.color; + item.element.appendChild(color); + } + + // Set content + if (! obj.options.format) { + var text = data.text; + } else { + var text = data.name; + } + + var node = document.createElement('div'); + node.className = 'jdropdown-description'; + node.innerHTML = text || ' '; + + // Title + if (data.title) { + var title = document.createElement('div'); + title.className = 'jdropdown-title'; + title.innerText = data.title; + node.appendChild(title); + } + + // Set content + if (! obj.options.format) { + var val = data.value; + } else { + var val = data.id; + } + + // Value + if (obj.value[val]) { + 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) { + // 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); + } + } + + // Number of items counter + var counter = 0; + + // 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 || counter < 200) { + groupContent.appendChild(item.element); + counter++; + } + } + // 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 || counter < 200) { + content.appendChild(item.element); + counter++; + } + } + } + } + } + + 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 + if (! obj.options.format) { + data[i] = { + value: data[i], + text: data[i] + } + } else { + data[i] = { + id: data[i], + name: data[i] + } + } + } + } + + // Reset current value + resetValue(); + + // Make sure the content container is blank + content.innerHTML = ''; + + // Reset + obj.header.value = ''; + + // Reset items and values + obj.items = []; + + // Append data + obj.appendData(data); + + // Update data + obj.options.data = data; + } + } + + obj.getData = function() { + return obj.options.data; + } + + /** + * Get position of the item + */ + obj.getPosition = function(val) { + for (var i = 0; i < obj.items.length; i++) { + if (Value(i) == val) { + return i; + } + } + return false; + } + + /** + * Get dropdown current text + */ + obj.getText = function(asArray) { + // Get value + var v = getText(); + // Return value + if (asArray) { + return v; + } else { + return v.join('; '); + } + } + + /** + * Get dropdown current value + */ + obj.getValue = function(asArray) { + // Get value + var v = getValue(); + // Return value + if (asArray) { + return v; + } else { + return v.join(';'); + } + } + + /** + * Change event + */ + var change = function(oldValue) { + // Events + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, obj, oldValue, obj.options.value); + } + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + /** + * Set value + */ + obj.setValue = function(newValue) { + // Current value + var oldValue = obj.getValue(); + // New value + if (Array.isArray(newValue)) { + newValue = newValue.join(';') + } + + if (oldValue !== newValue) { + // Set value + applyValue(newValue); + + // Change + change(oldValue); + } + } + + obj.resetSelected = function() { + obj.setValue(null); + } + + obj.selectIndex = function(index, force) { + // Make sure is a number + var index = parseInt(index); + + // Only select those existing elements + if (obj.items && obj.items[index] && (force === true || obj.items[index].data.disabled !== true)) { + // Reset cursor to a new position + obj.setCursor(index, false); + + // Behaviour + if (! obj.options.multiple) { + // Update value + if (obj.items[index].selected) { + obj.setValue(null); + } else { + obj.setValue(Value(index)); + } + + // Close component + obj.close(); + } else { + // Old value + var oldValue = obj.options.value; + + // Toggle option + if (obj.items[index].selected) { + obj.items[index].element.classList.remove('jdropdown-selected'); + obj.items[index].selected = false; + + delete obj.value[Value(index)]; + } else { + // Select element + obj.items[index].element.classList.add('jdropdown-selected'); + obj.items[index].selected = true; + + // Set value + obj.value[Value(index)] = Text(index); + } + + // Global value + obj.options.value = Object.keys(obj.value).join(';'); + + // Update labels for multiple dropdown + if (obj.options.autocomplete == false) { + obj.header.value = getText().join('; '); + } + + // Events + change(oldValue); + } + } + } + + obj.selectItem = function(item) { + obj.selectIndex(item.indexValue); + } + + var exists = function(k, result) { + for (var j = 0; j < result.length; j++) { + if (! obj.options.format) { + if (result[j].value == k) { + return true; + } + } else { + if (result[j].id == k) { + return true; + } + } + } + return false; + } + + obj.find = function(str) { + if (obj.search == str.trim()) { + return false; + } + + // Search term + obj.search = str; + + // Reset index + obj.setCursor(); + + // Remove nodes from all groups + if (obj.groups.length) { + for (var i = 0; i < obj.groups.length; i++) { + obj.groups[i].lastChild.innerHTML = ''; + } + } + + // Remove all nodes + content.innerHTML = ''; + + // Remove current items in the remote search + if (obj.options.remoteSearch == true) { + // Reset results + obj.results = null; + // URL + var url = obj.options.url + (obj.options.url.indexOf('?') > 0 ? '&' : '?') + 'q=' + str; + // Remote search + jSuites.ajax({ + url: url, + method: 'GET', + dataType: 'json', + success: function(result) { + // Reset items + obj.items = []; + + // Add the current selected items to the results in case they are not there + var current = Object.keys(obj.value); + if (current.length) { + for (var i = 0; i < current.length; i++) { + if (! exists(current[i], result)) { + if (! obj.options.format) { + result.unshift({ value: current[i], text: obj.value[current[i]] }); + } else { + result.unshift({ id: current[i], name: obj.value[current[i]] }); + } + } + } + } + // Append data + obj.appendData(result); + // Show or hide results + if (! result.length) { + content.style.display = 'none'; + } else { + content.style.display = ''; + } + } + }); + } else { + // Search terms + str = new RegExp(str, 'gi'); + + // Reset search + var results = []; + + // Append options + for (var i = 0; i < obj.items.length; i++) { + // Item label + var label = Text(i); + // Item title + var title = obj.items[i].data.title || ''; + // Group name + var groupName = obj.items[i].data.group || ''; + // Synonym + var synonym = obj.items[i].data.synonym || ''; + if (synonym) { + synonym = synonym.join(' '); + } + + if (str == null || obj.items[i].selected == true || label.match(str) || title.match(str) || groupName.match(str) || synonym.match(str)) { + results.push(obj.items[i]); + } + } + + if (! results.length) { + content.style.display = 'none'; + + // Results + obj.results = null; + } else { + content.style.display = ''; + + // Results + obj.results = results; + + // Show 200 items at once + var number = 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.lastChild.appendChild(obj.results[i].element); + } else { + content.appendChild(obj.results[i].element); + } + } + } + } + + // Auto focus + if (obj.options.autofocus == true) { + obj.first(); + } + } + + obj.open = function() { + // Focus + if (! el.classList.contains('jdropdown-focus')) { + // Current dropdown + jSuites.dropdown.current = obj; + + // Start tracking + jSuites.tracking(obj, true); + + // 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 = getValue(); + if (k[0]) { + var cursor = obj.getPosition(k[0]); + if (cursor !== false) { + 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 (el.classList.contains('jdropdown-focus')) { + // Update labels + obj.header.value = obj.getText(); + // Remove cursor + obj.setCursor(); + // 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'); + // Start tracking + jSuites.tracking(obj, false); + // Current dropdown + jSuites.dropdown.current = null; + } + + 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 { + index = parseInt(index); + + // Cursor only for visible items + if (obj.items[index].element.parentNode) { + 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 available item + */ + obj.first = function() { + if (obj.options.lazyLoading === true) { + obj.loadFirst(); + } + + var items = content.querySelectorAll('.jdropdown-item'); + if (items.length) { + var newIndex = items[0].indexValue; + obj.setCursor(newIndex); + } + } + + /** + * Last available item + */ + obj.last = function() { + if (obj.options.lazyLoading === true) { + obj.loadLast(); + } + + var items = content.querySelectorAll('.jdropdown-item'); + if (items.length) { + var newIndex = items[items.length-1].indexValue; + obj.setCursor(newIndex); + } + } + + obj.next = function(letter) { + var newIndex = null; + + if (letter) { + if (letter.length == 1) { + // Current index + var current = obj.currentIndex || -1; + // Letter + letter = letter.toLowerCase(); + + var e = null; + var l = null; + var items = content.querySelectorAll('.jdropdown-item'); + if (items.length) { + for (var i = 0; i < items.length; i++) { + if (items[i].indexValue > current) { + if (e = obj.items[items[i].indexValue]) { + if (l = e.element.innerText[0]) { + l = l.toLowerCase(); + if (letter == l) { + newIndex = items[i].indexValue; + break; + } + } + } + } + } + obj.setCursor(newIndex); + } + } + } else { + if (obj.currentIndex == undefined || obj.currentIndex == null) { + obj.first(); + } else { + var element = obj.items[obj.currentIndex].element; + + var next = element.nextElementSibling; + if (next) { + if (next.classList.contains('jdropdown-group')) { + next = next.lastChild.firstChild; + } + newIndex = next.indexValue; + } else { + if (element.parentNode.classList.contains('jdropdown-group-items')) { + if (next = element.parentNode.parentNode.nextElementSibling) { + if (next.classList.contains('jdropdown-group')) { + next = next.lastChild.firstChild; + } else if (next.classList.contains('jdropdown-item')) { + newIndex = next.indexValue; + } else { + next = null; + } + } + + if (next) { + newIndex = next.indexValue; + } + } + } + + if (newIndex !== null) { + obj.setCursor(newIndex); + } + } + } + } + + obj.prev = function() { + var newIndex = null; + + if (obj.currentIndex === null) { + obj.first(); + } else { + var element = obj.items[obj.currentIndex].element; + + var prev = element.previousElementSibling; + if (prev) { + if (prev.classList.contains('jdropdown-group')) { + prev = prev.lastChild.lastChild; + } + newIndex = prev.indexValue; + } else { + if (element.parentNode.classList.contains('jdropdown-group-items')) { + if (prev = element.parentNode.parentNode.previousElementSibling) { + if (prev.classList.contains('jdropdown-group')) { + prev = prev.lastChild.lastChild; + } else if (prev.classList.contains('jdropdown-item')) { + newIndex = prev.indexValue; + } else { + prev = null + } + } + + if (prev) { + newIndex = prev.indexValue; + } + } + } + } + + if (newIndex !== null) { + obj.setCursor(newIndex); + } + } + + obj.loadFirst = function() { + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + // Show 200 items at once + var number = results.length || 0; + + // Lazyloading + if (obj.options.lazyLoading == true && number > 200) { + number = 200; + } + + // Reset container + content.innerHTML = ''; + + // First 200 items + for (var i = 0; i < number; i++) { + if (results[i].group) { + if (! results[i].group.parentNode) { + content.appendChild(results[i].group); + } + results[i].group.lastChild.appendChild(results[i].element); + } else { + content.appendChild(results[i].element); + } + } + + // Scroll go to the begin + content.scrollTop = 0; + } + + obj.loadLast = function() { + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + // Show first page + var number = results.length; + + // Max 200 items + if (number > 200) { + number = number - 200; + + // Reset container + content.innerHTML = ''; + + // First 200 items + for (var i = number; i < results.length; i++) { + if (results[i].group) { + if (! results[i].group.parentNode) { + content.appendChild(results[i].group); + } + results[i].group.lastChild.appendChild(results[i].element); + } else { + content.appendChild(results[i].element); + } + } + + // Scroll go to the begin + content.scrollTop = content.scrollHeight; + } + } + + obj.loadUp = function() { + var test = false; + + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + var items = content.querySelectorAll('.jdropdown-item'); + var fistItem = items[0].indexValue; + fistItem = obj.items[fistItem]; + var index = results.indexOf(fistItem) - 1; + + if (index > 0) { + var number = 0; + + while (index > 0 && results[index] && number < 200) { + if (results[index].group) { + if (! results[index].group.parentNode) { + content.insertBefore(results[index].group, content.firstChild); + } + results[index].group.lastChild.insertBefore(results[index].element, results[index].group.lastChild.firstChild); + } else { + content.insertBefore(results[index].element, content.firstChild); + } + + index--; + number++; + } + + // New item added + test = true; + } + + return test; + } + + obj.loadDown = function() { + var test = false; + + // Search + if (obj.results) { + var results = obj.results; + } else { + var results = obj.items; + } + + var items = content.querySelectorAll('.jdropdown-item'); + var lastItem = items[items.length-1].indexValue; + lastItem = obj.items[lastItem]; + var index = results.indexOf(lastItem) + 1; + + if (index < results.length) { + var number = 0; + while (index < results.length && results[index] && number < 200) { + if (results[index].group) { + if (! results[index].group.parentNode) { + content.appendChild(results[index].group); + } + results[index].group.lastChild.appendChild(results[index].element); + } else { + content.appendChild(results[index].element); + } + + index++; + number++; + } + + // New item added + test = true; + } + + return test; + } + + init(); + + return obj; +}); + +jSuites.dropdown.keydown = function(e) { + var dropdown = null; + if (dropdown = jSuites.dropdown.current) { + if (e.which == 13 || e.which == 9) { // enter or tab + if (dropdown.header.value && dropdown.currentIndex == null && dropdown.options.newOptions) { + // if they typed something in, but it matched nothing, and newOptions are allowed, start that flow + dropdown.add(); + } else { + // Quick Select/Filter + if (dropdown.currentIndex == null && dropdown.options.autocomplete == true && dropdown.header.value != "") { + dropdown.find(dropdown.header.value); + } + dropdown.selectIndex(dropdown.currentIndex); + } + } else if (e.which == 38) { // up arrow + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex > 0) { + dropdown.prev(); + } + e.preventDefault(); + } else if (e.which == 40) { // down arrow + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex + 1 < dropdown.items.length) { + dropdown.next(); + } + e.preventDefault(); + } else if (e.which == 36) { + dropdown.first(); + if (! e.target.classList.contains('jdropdown-header')) { + e.preventDefault(); + } + } else if (e.which == 35) { + dropdown.last(); + if (! e.target.classList.contains('jdropdown-header')) { + e.preventDefault(); + } + } else if (e.which == 27) { + dropdown.close(); + } else if (e.which == 33) { // page up + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex > 0) { + for (var i = 0; i < 7; i++) { + dropdown.prev() + } + } + e.preventDefault(); + } else if (e.which == 34) { // page down + if (dropdown.currentIndex == null) { + dropdown.first(); + } else if (dropdown.currentIndex + 1 < dropdown.items.length) { + for (var i = 0; i < 7; i++) { + dropdown.next() + } + } + e.preventDefault(); + } + } +} + +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(); + } + } +} + +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 }; +} + +jSuites.editor = (function(el, options) { + var obj = {}; + obj.options = {}; + + // 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, + // Placeholder + placeholder: null, + // Parse URL + parseURL: false, + filterPaste: true, + // Accept drop files + dropZone: false, + dropAsSnippet: false, + acceptImages: false, + acceptFiles: false, + maxFileSize: 5000000, + allowImageResize: true, + // Style + border: true, + padding: true, + maxHeight: null, + height: 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; + var files = []; + + // Make sure element is empty + el.innerHTML = ''; + + // Keep the reference for the container + obj.el = el; + + 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'; + + // Placeholder + if (obj.options.placeholder) { + editor.setAttribute('data-placeholder', obj.options.placeholder); + } + + // Max height + if (obj.options.maxHeight || obj.options.height) { + editor.style.overflowY = 'auto'; + + if (obj.options.maxHeight) { + editor.style.maxHeight = obj.options.maxHeight; + } + if (obj.options.height) { + editor.style.height = obj.options.height; + } + } + + // Set editor initial value + if (obj.options.value) { + var value = obj.options.value; + } else { + var value = el.innerHTML ? el.innerHTML : ''; + } + + if (! value) { + var value = ''; + } + + /** + * Onchange event controllers + */ + var change = function(e) { + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, obj, e); + } + + // Update value + obj.options.value = obj.getData(); + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + /** + * 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); + } + } + } + + var updateTotalImages = function() { + var o = null; + if (o = snippet.children[0]) { + // Make sure is a grid + if (! o.classList.contains('jslider-grid')) { + o.classList.add('jslider-grid'); + } + // Quantify of images + var number = o.children.length; + // Set the configuration of the grid + o.setAttribute('data-number', number > 4 ? 4 : number); + // Total of images inside the grid + if (number > 4) { + o.setAttribute('data-total', number - 4); + } else { + o.removeAttribute('data-total'); + } + } + } + + /** + * Append image to the snippet + */ + var appendImage = function(image) { + if (! snippet.innerHTML) { + appendElement({}); + } + snippet.children[0].appendChild(image); + updateTotalImages(); + } + + /** + * Append snippet + * @Param object data + */ + var appendElement = function(data) { + // Reset snippet + snippet.innerHTML = ''; + + // Attributes + var a = [ 'image', 'title', 'description', 'host', 'url' ]; + + for (var i = 0; i < a.length; i++) { + var div = document.createElement('div'); + div.className = 'jsnippet-' + a[i]; + div.setAttribute('data-k', a[i]); + snippet.appendChild(div); + if (data[a[i]]) { + if (a[i] == 'image') { + if (! Array.isArray(data.image)) { + data.image = [ data.image ]; + } + for (var j = 0; j < data.image.length; j++) { + var img = document.createElement('img'); + img.src = data.image[j]; + div.appendChild(img); + } + } else { + div.innerHTML = data[a[i]]; + } + } + } + + editor.appendChild(document.createElement('br')); + editor.appendChild(snippet); + } + + var verifyEditor = function() { + clearTimeout(editorTimer); + editorTimer = setTimeout(function() { + var snippet = editor.querySelector('.jsnippet'); + if (! snippet) { + var html = editor.innerHTML.replace(/\n/g, ' '); + var container = document.createElement('div'); + container.innerHTML = html; + 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') { + obj.addImage(url[0], true); + } 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; + } + // Host + if (result.host) { + p.host = result.host; + } + // Url + if (result.url) { + p.url = result.url; + } + // Append snippet + appendElement(p); + // Add image + if (result.image) { + obj.addImage(result.image, true); + } else if (result['og:image']) { + obj.addImage(result['og:image'], true); + } + } + }); + } + } + + /** + * Set editor value + */ + obj.setData = function(html) { + editor.innerHTML = html; + + if (obj.options.focus) { + jSuites.editor.setCursor(editor, true); + } + + // Reset files container + files = []; + } + + obj.getFiles = function() { + var f = editor.querySelectorAll('.jfile'); + var d = []; + for (var i = 0; i < f.length; i++) { + if (files[f[i].src]) { + d.push(files[f[i].src]); + } + } + return d; + } + + obj.getText = function() { + return editor.innerText; + } + + /** + * Get editor data + */ + obj.getData = function(json) { + if (! json) { + var data = editor.innerHTML; + } else { + var data = { + content : '', + } + + // Get snippet + 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') { + if (! data.snippet.image) { + data.snippet.image = []; + } + // Get all images + for (var j = 0; j < snippet.children[i].children.length; j++) { + data.snippet.image.push(snippet.children[i].children[j].getAttribute('src')) + } + } else { + data.snippet[key] = snippet.children[i].innerHTML; + } + } + } + } + + // Get files + var f = Object.keys(files); + if (f.length) { + data.files = []; + for (var i = 0; i < f.length; i++) { + data.files.push(files[f[i]]); + } + } + + // Get content + var text = editor.innerHTML; + text = text.replace(/
/g, "\n"); + text = text.replace(/<\/div>/g, "<\/div>\n"); + text = text.replace(/<(?:.|\n)*?>/gm, ""); + data.content = text.trim(); + } + + return data; + } + + // Reset + obj.reset = function() { + editor.innerHTML = ''; + snippet.innerHTML = ''; + files = []; + } + + 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.title = data.name; + newImage.className = 'jfile pdf'; + + files[newImage.src] = { + file: newImage.src, + extension: 'pdf', + content: data.result, + } + + insertNodeAtCaret(newImage); + }); + } + } + + obj.addImage = function(src, asSnippet) { + if (! src) { + 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 newImage = document.createElement('img'); + newImage.src = window.URL.createObjectURL(blob); + newImage.classList.add('jfile'); + newImage.setAttribute('tabindex', '900'); + files[newImage.src] = { + file: newImage.src, + extension: extension, + content: canvas.toDataURL(), + } + + if (obj.options.dropAsSnippet || asSnippet) { + appendImage(newImage); + // Just to understand the attachment is part of a snippet + files[newImage.src].snippet = true; + } else { + insertNodeAtCaret(newImage); + } + + 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); + } + }, 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) { + if (editorAction && editorAction.e) { + editorAction.e.classList.remove('resizing'); + } + + 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.width) { + e.target.width = rect.width + 'px'; + } + + if (! e.target.height) { + e.target.height = rect.height + 'px'; + } + + var s = window.getSelection(); + if (s.rangeCount) { + for (var i = 0; i < s.rangeCount; i++) { + s.removeRange(s.getRangeAt(i)); + } + } + + e.target.classList.add('resizing'); + } 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' && ! e.target.parentNode.classList.contains('jsnippet-image') && 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.width = (editorAction.w + (e.clientX - editorAction.x)); + + if (e.shiftKey) { + var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w); + editorAction.e.height = editorAction.h + newHeight; + } else { + var newHeight = null; + } + } + + if (! newHeight) { + if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') { + if (! e.shiftKey) { + editorAction.e.height = editorAction.h + (e.clientY - editorAction.y); + } + } + } + } + } + + var editorKeyUp = function(e) { + if (! editor.innerHTML) { + editor.innerHTML = '

'; + } + + if (typeof(obj.options.onkeyup) == 'function') { + obj.options.onkeyup(el, obj, 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); + } + + if (e.key == 'Delete') { + if (e.target.tagName == 'IMG' && e.target.parentNode.classList.contains('jsnippet-image')) { + e.target.remove(); + updateTotalImages(); + } + } + } + + // Elements to be removed + var remove = [HTMLUnknownElement,HTMLAudioElement,HTMLEmbedElement,HTMLIFrameElement,HTMLTextAreaElement,HTMLInputElement,HTMLScriptElement]; + + // Valid properties + var validProperty = ['width', 'height', 'align', 'border', 'src', 'tabindex']; + + // Valid CSS attributes + var validStyle = ['color', 'font-weight', 'font-size', 'background', 'background-color', 'margin']; + + var parse = function(element) { + // Remove attributes + if (element.attributes && element.attributes.length) { + var image = null; + var style = null; + // Process style attribute + var elementStyle = element.getAttribute('style'); + if (elementStyle) { + style = []; + var t = elementStyle.split(';'); + for (var j = 0; j < t.length; j++) { + var v = t[j].trim().split(':'); + if (validStyle.indexOf(v[0].trim()) >= 0) { + var k = v.shift(); + var v = v.join(':'); + style.push(k + ':' + v); + } + } + } + // Process image + if (element.tagName.toUpperCase() == 'IMG') { + if (! obj.options.acceptImages || ! element.src) { + element.parentNode.removeChild(element); + } else { + // Check if is data + element.setAttribute('tabindex', '900'); + // Check attributes for persistance + obj.addImage(element.src); + } + } + // Remove attributes + var attr = []; + var numAttributes = element.attributes.length - 1; + if (numAttributes > 0) { + for (var i = numAttributes; i >= 0 ; i--) { + attr.push(element.attributes[i].name); + } + attr.forEach(function(v) { + if (validProperty.indexOf(v) == -1) { + element.removeAttribute(v); + } + }); + } + element.style = ''; + // Add valid style + if (style && style.length) { + element.setAttribute('style', style.join(';')); + } + } + // Parse children + if (element.children.length) { + for (var i = 0; i < element.children.length; i++) { + parse(element.children[i]); + } + } + + if (remove.indexOf(element.constructor) >= 0) { + element.remove(); + } + } + + var filter = function(data) { + if (data) { + data = data.replace(new RegExp('', 'gsi'), ''); + } + var parser = new DOMParser(); + var d = parser.parseFromString(data, "text/html"); + parse(d); + var span = document.createElement('span'); + span.innerHTML = d.firstChild.innerHTML; + return span; + } + + var editorPaste = function(e) { + if (obj.options.filterPaste == true) { + 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 { + if (! html) { + html = text.split('\r\n'); + if (! e.target.innerText) { + html.map(function(v) { + var d = document.createElement('div'); + d.innerText = v; + editor.appendChild(d); + }); + } else { + html = html.map(function(v) { + return '
' + v + '
'; + }); + document.execCommand('insertHtml', false, html.join('')); + } + } else { + var d = filter(html); + // Paste to the editor + insertNodeAtCaret(d); + } + } + + 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'); + e.preventDefault(); + } + } + + 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); + e.preventDefault(); + } + } + + 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) { + // Blur + if (typeof(obj.options.onblur) == 'function') { + obj.options.onblur(el, obj, e); + } + + change(e); + } + + var editorFocus = function(e) { + // Focus + if (typeof(obj.options.onfocus) == 'function') { + 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); + editor.addEventListener('focus', editorFocus); + editor.addEventListener('blur', editorBlur); + + // 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) { + // Append to the DOM + el.appendChild(toolbar); + // Create toolbar + jSuites.toolbar(toolbar, { + container: true, + responsive: true, + items: obj.options.toolbar + }); + } + + // Focus to the editor + if (obj.options.focus) { + jSuites.editor.setCursor(editor, obj.options.focus == 'initial' ? true : false); + } + + // Change method + el.change = obj.setData; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + // Data type + var o = el.getAttribute('data-html') === 'true' ? false : true; + return obj.getData(o); + } else { + obj.setData(val); + } + } + + 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.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, + onbeforeload: null, + onload: null, + onbeforesave: null, + onsave: null, + onbeforeremove: null, + onremove: 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 = {}; + } + + // Submit Button + if (! obj.options.submitButton) { + obj.options.submitButton = el.querySelector('input[type=submit]'); + } + + if (obj.options.submitButton && obj.options.url) { + obj.options.submitButton.onclick = function() { + obj.save(); + } + } + + if (! obj.options.validations.email) { + obj.options.validations.email = jSuites.validations.email; + } + + if (! obj.options.validations.length) { + obj.options.validations.length = jSuites.validations.length; + } + + if (! obj.options.validations.required) { + obj.options.validations.required = jSuites.validations.required; + } + + obj.setUrl = function(url) { + obj.options.url = url; + } + + obj.load = function() { + jSuites.ajax({ + url: obj.options.url, + method: 'GET', + dataType: 'json', + queue: true, + success: function(data) { + // Overwrite values from the backend + if (typeof(obj.options.onbeforeload) == 'function') { + var ret = obj.options.onbeforeload(el, data); + if (ret) { + data = ret; + } + } + // Apply values to the form + jSuites.form.setElements(el, data); + // Onload methods + 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) { + 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.remove = function() { + if (typeof(obj.options.onbeforeremove) == 'function') { + var ret = obj.options.onbeforeremove(el, obj); + if (ret === false) { + return false; + } + } + + jSuites.ajax({ + url: obj.options.url, + method: 'DELETE', + dataType: 'json', + success: function(result) { + if (typeof(obj.options.onremove) == 'function') { + obj.options.onremove(el, obj, 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, div[name]"); + // 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; + // Value + var value = jSuites.form.getValue(element); + // Validation + var validation = element.getAttribute('data-validation'); + // Parse + if (typeof(obj.options.validations[validation]) == 'function' && ! obj.options.validations[validation](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 name = null; + var elements = el.querySelectorAll("input, select, textarea, div[name]"); + // Run all elements + for (var i = 0; i < elements.length; i++) { + if (name = elements[i].getAttribute('name')) { + if (elements[i].type == 'checkbox' || elements[i].type == 'radio') { + elements[i].checked = false; + } else { + if (typeof(elements[i].val) == 'function') { + elements[i].val(''); + } else { + elements[i].value = ''; + } + } + } + } + } + + // Run form validation + obj.validate = function() { + var test = []; + // Get elements in the form + var elements = el.querySelectorAll("input, select, textarea, div[name]"); + // 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('
'); + } 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; + } + + // 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 value from one element +jSuites.form.getValue = function(element) { + var value = null; + if (element.type == 'checkbox') { + if (element.checked == true) { + value = element.value || true; + } + } else if (element.type == 'radio') { + if (element.checked == true) { + value = element.value; + } + } else if (element.tagName == 'select' && element.multiple == true) { + value = []; + var options = element.querySelectorAll("options[selected]"); + for (var j = 0; j < options.length; j++) { + value.push(options[j].value); + } + } else if (typeof(element.val) == 'function') { + value = element.val(); + } else { + value = element.value || ''; + } + + return value; +} + +// Get form elements +jSuites.form.getElements = function(el, asArray) { + var data = {}; + var name = null; + var elements = el.querySelectorAll("input, select, textarea, div[name]"); + + for (var i = 0; i < elements.length; i++) { + if (name = elements[i].getAttribute('name')) { + data[name] = jSuites.form.getValue(elements[i]) || ''; + } + } + + return asArray == true ? data : JSON.stringify(data); +} + +//Get form elements +jSuites.form.setElements = function(el, data) { + var name = null; + var value = null; + var elements = el.querySelectorAll("input, select, textarea, div[name]"); + for (var i = 0; i < elements.length; i++) { + // Attributes + var type = elements[i].getAttribute('type'); + if (name = elements[i].getAttribute('name')) { + // Transform variable names in pathname + name = name.replace(new RegExp(/\[(.*?)\]/ig), '.$1'); + value = null; + // Seach for the data in the path + if (name.match(/\./)) { + var tmp = jSuites.path.call(data, name) || ''; + if (typeof(tmp) !== 'undefined') { + value = tmp; + } + } else { + if (typeof(data[name]) !== 'undefined') { + value = data[name]; + } + } + // Set the values + if (value !== null) { + if (type == 'checkbox' || type == 'radio') { + elements[i].checked = value ? true : false; + } else { + if (typeof (elements[i].val) == 'function') { + elements[i].val(value); + } else { + elements[i].value = value; + } + } + } + } + } +} + +// Legacy +jSuites.tracker = jSuites.form; + +jSuites.focus = function(el) { + if (el.innerText.length) { + var range = document.createRange(); + var sel = window.getSelection(); + var node = el.childNodes[el.childNodes.length-1]; + range.setStart(node, node.length) + range.collapse(true) + sel.removeAllRanges() + sel.addRange(range) + el.scrollLeft = el.scrollWidth; + } +} + +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.getNode = function() { + var node = document.getSelection().anchorNode; + if (node) { + return (node.nodeType == 3 ? node.parentNode : node); + } else { + return null; + } +} +/** + * Generate hash from a string + */ +jSuites.hash = 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); + if (chr > 32) { + hash = ((hash << 5) - hash) + chr; + hash |= 0; + } + } + } + return hash; +} + +/** + * Generate a random color + */ +jSuites.randomColor = function(h) { + var lum = -0.25; + var hex = String('#' + Math.random().toString(16).slice(2, 8).toUpperCase()).replace(/[^0-9a-f]/gi, ''); + if (hex.length < 6) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + var rgb = [], c, i; + for (i = 0; i < 3; i++) { + c = parseInt(hex.substr(i * 2, 2), 16); + c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); + rgb.push(("00" + c).substr(c.length)); + } + + // Return hex + if (h == true) { + return '#' + jSuites.two(rgb[0].toString(16)) + jSuites.two(rgb[1].toString(16)) + jSuites.two(rgb[2].toString(16)); + } + + return rgb; +} + +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 = jSuites.upload = (function(el, options) { + var obj = {}; + obj.options = {}; + + // Default configuration + var defaults = { + type: 'image', + extension: '*', + input: false, + minWidth: false, + maxWidth: null, + maxHeight: null, + maxJpegSizeBytes: null, // For example, 350Kb would be 350000 + onchange: null, + multiple: false, + remoteParser: null, + text:{ + extensionNotAllowed:'The extension is not allowed', + } + }; + + // 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]; + } + } + + // Multiple + if (obj.options.multiple == true) { + el.setAttribute('data-multiple', true); + } + + // Container + el.content = []; + + // Upload icon + el.classList.add('jupload'); + + if (obj.options.input == true) { + el.classList.add('input'); + } + + obj.add = function(data) { + // Reset container for single files + if (obj.options.multiple == false) { + el.content = []; + el.innerText = ''; + } + + // Append to the element + if (obj.options.type == 'image') { + var img = document.createElement('img'); + img.setAttribute('src', data.file); + img.setAttribute('tabindex', -1); + if (! el.getAttribute('name')) { + img.className = 'jfile'; + img.content = data; + } + el.appendChild(img); + } else { + if (data.name) { + var name = data.name; + } else { + var name = data.file; + } + var div = document.createElement('div'); + div.innerText = name || obj.options.type; + div.classList.add('jupload-item'); + div.setAttribute('tabindex', -1); + el.appendChild(div); + } + + if (data.content) { + data.file = jSuites.guid(); + } + + // Push content + el.content.push(data); + + // Onchange + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, data); + } + } + + obj.addFromFile = function(file) { + var type = file.type.split('/'); + if (type[0] == obj.options.type) { + var readFile = new FileReader(); + readFile.addEventListener("load", function (v) { + var data = { + file: v.srcElement.result, + extension: file.name.substr(file.name.lastIndexOf('.') + 1), + name: file.name, + size: file.size, + lastmodified: file.lastModified, + content: v.srcElement.result, + } + + obj.add(data); + }); + + readFile.readAsDataURL(file); + } else { + alert(obj.options.text.extensionNotAllowed); + } + } + + 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('/'); + var type = extension[0].replace('data:',''); + if (type == obj.options.type) { + var data = { + file: src, + name: '', + extension: extension[1], + content: src, + } + obj.add(data); + } else { + alert(obj.options.text.extensionNotAllowed); + } + } else { + var extension = src.substr(src.lastIndexOf('.') + 1); + // Work for cross browsers + src = obj.options.remoteParser + src; + // Get remove content + jSuites.ajax({ + url: src, + type: 'GET', + dataType: 'blob', + success: function(data) { + //add(extension[0].replace('data:',''), data); + } + }) + } + } + } + + var 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 mime = obj.options.type + '/' + obj.options.extension; + var input = document.createElement('input'); + input.type = 'file'; + input.setAttribute('accept', mime); + input.onchange = function() { + for (var i = 0; i < this.files.length; i++) { + obj.addFromFile(this.files[i]); + } + } + + // Allow multiple files + if (obj.options.multiple == true) { + input.setAttribute('multiple', true); + } + + var current = null; + + el.addEventListener("click", function(e) { + current = null; + if (! el.children.length || e.target === el) { + jSuites.click(input); + } else { + if (e.target.parentNode == el) { + current = e.target; + } + } + }); + + el.addEventListener("dblclick", function(e) { + jSuites.click(input); + }); + + 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('keydown', function(e) { + if (current && e.which == 46) { + var index = Array.prototype.indexOf.call(el.children, current); + if (index >= 0) { + el.content.splice(index, 1); + current.remove(); + current = null; + } + } + }); + + 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.multiple == false) { + el.innerText = ''; + } + + // 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.val = function(val) { + if (val === undefined) { + return el.content && el.content.length ? el.content : null; + } else { + // Reset + el.innerText = ''; + el.content = []; + + if (val) { + if (Array.isArray(val)) { + for (var i = 0; i < val.length; i++) { + if (typeof(val[i]) == 'string') { + obj.add({ file: val[i] }); + } else { + obj.add(val[i]); + } + } + } else if (typeof(val) == 'string') { + obj.add({ file: val }); + } + } + } + } + + el.upload = el.image = obj; + + return obj; +}); + +jSuites.image.create = function(data) { + var img = document.createElement('img'); + img.setAttribute('src', data.file); + img.className = 'jfile'; + img.setAttribute('tabindex', -1); + img.content = data; + + return img; +} + + +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 event = false; + 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); + } + event = true; + } + } else if (el.scrollTop <= el.clientHeight) { + if (options.loadUp()) { + if (scrollTop == el.scrollTop) { + el.scrollTop = el.scrollTop + (el.clientHeight); + } + event = true; + } + } + + timeControlLoading = setTimeout(function() { + timeControlLoading = null; + }, options.timer); + + if (event) { + if (typeof(options.onupdate) == 'function') { + options.onupdate(); + } + } + } + } + + // 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 && loading.parentNode) { + document.body.removeChild(loading); + } + } + + return obj; +})(); + +jSuites.mask = (function() { + // Currency + var tokens = { + // Currency tokens + currency: [ '#(.{1})##0?(.{1}0+)?( ?;(.*)?)?', '#' ], + // Percentage + percentage: [ '0{1}(.{1}0+)?%' ], + // Number + numeric: [ '0{1}(.{1}0+)?' ], + // Data tokens + datetime: [ 'YYYY', 'YYY', 'YY', 'MMMMM', 'MMMM', 'MMM', 'MM', 'DDDDD', 'DDDD', 'DDD', 'DD', 'DY', 'DAY', 'WD', 'D', 'Q', 'HH24', 'HH12', 'HH', '\\[H\\]', 'H', 'AM/PM', 'PM', 'AM', 'MI', 'SS', 'MS', 'MONTH', 'MON', 'Y', 'M' ], + // Other + general: [ 'A', '0', '[0-9a-zA-Z\$]+', '.'] + } + + var getDate = function() { + if (this.mask.toLowerCase().indexOf('[h]') !== -1) { + var m = 0; + if (this.date[4]) { + m = parseFloat(this.date[4] / 60); + } + var v = parseInt(this.date[3]) + m; + v /= 24; + } else if (! (this.date[0] && this.date[1] && this.date[2]) && (this.date[3] || this.date[4])) { + v = jSuites.two(this.date[3]) + ':' + jSuites.two(this.date[4]) + ':' + jSuites.two(this.date[5]) + } else { + if (this.date[0] && this.date[1] && ! this.date[2]) { + this.date[2] = 1; + } + v = jSuites.two(this.date[0]) + '-' + jSuites.two(this.date[1]) + '-' + jSuites.two(this.date[2]); + + if (this.date[3] || this.date[4] || this.date[5]) { + v += ' ' + jSuites.two(this.date[3]) + ':' + jSuites.two(this.date[4]) + ':' + jSuites.two(this.date[5]); + } + } + + return v; + } + + var isBlank = function(v) { + return v === null || v === '' || v === undefined ? true : false; + } + + var isFormula = function(value) { + return (''+value).chartAt(0) == '='; + } + + var isNumeric = function(t) { + return t === 'currency' || t === 'percentage' || t === 'numeric' ? true : false; + } + /** + * Get the decimal defined in the mask configuration + */ + var getDecimal = function(v) { + if (v && Number(v) == v) { + return '.'; + } else { + if (this.options.decimal) { + return this.options.decimal; + } else { + if (this.locale) { + var t = Intl.NumberFormat(this.locale).format(1.1); + return this.options.decimal = t[1]; + } else { + if (! v) { + v = this.mask; + } + var e = new RegExp('0{1}(.{1})0+', 'ig'); + var t = e.exec(v); + if (t && t[1] && t[1].length == 1) { + // Save decimal + this.options.decimal = t[1]; + // Return decimal + return t[1]; + } else { + // Did not find any decimal last resort the default + var e = new RegExp('#,##', 'ig'); + if ((v && v.match(e)) || '1.1'.toLocaleString().substring(1,2) == '.') { + this.options.decimal = '.'; + } else { + this.options.decimal = ','; + } + } + } + } + } + + if (this.options.decimal) { + return this.options.decimal; + } else { + return null; + } + } + + var ParseValue = function(v, decimal) { + if (v == '') { + return ''; + } + + // Get decimal + if (! decimal) { + decimal = getDecimal.call(this); + } + + // New value + v = (''+v).split(decimal); + v[0] = v[0].match(/[\-0-9]+/g, ''); + if (v[0]) { + v[0] = v[0].join(''); + } + if (v[0] || v[1]) { + if (v[1] !== undefined) { + v[1] = v[1].match(/[0-9]+/g, ''); + if (v[1]) { + v[1] = v[1].join(''); + } else { + v[1] = ''; + } + } + } else { + return ''; + } + + return v; + } + + var FormatValue = function(v) { + if (v == '') { + return ''; + } + // Get decimal + var d = getDecimal.call(this); + // Convert value + var o = Object.create(this.options || {}); + if (! o.minimumFractionDigits) { + o.minimumFractionDigits = 1; + } + // Parse value + v = ParseValue.call(this, v); + if (v == '') { + return ''; + } + // Temporary value + if (v[0]) { + var t = parseFloat(v.join('.')); + if (o.style == 'percent') { + t /= 100; + } + } else { + var t = null; + } + var n = new Intl.NumberFormat(this.locale, o).format(t); + n = n.split(d); + var s = n[1].replace(/[0-9]*/g, ''); + if (s) { + n[2] = s; + } + if (v[1] !== undefined) { + n[1] = d + v[1]; + } else { + n[1] = ''; + } + + return n.join(''); + } + + var Format = function(e) { + var v = Value.call(e); + if (! v) { + return; + } + + // Get decimal + var d = getDecimal.call(this); + var n = FormatValue.call(this, v); + var t = (n.length) - v.length; + var index = Caret.call(e) + t; + // Set value and update caret + Value.call(e, n, index, true); + } + + var Extract = function(v) { + // Keep the raw value + var current = ParseValue.call(this, v); + if (current) { + return parseFloat(current.join('.')); + } + return null; + } + + /** + * Caret getter and setter methods + */ + var Caret = function(index, adjustNumeric) { + if (index === undefined) { + if (this.tagName == 'DIV') { + var pos = 0; + var s = window.getSelection(); + if (s) { + if (s.rangeCount !== 0) { + var r = s.getRangeAt(0); + var p = r.cloneRange(); + p.selectNodeContents(this); + p.setEnd(r.endContainer, r.endOffset); + pos = p.toString().length; + } + } + return pos; + } else { + return this.selectionStart; + } + } else { + // Get the current value + var n = Value.call(this); + + // Review the position + if (adjustNumeric) { + var p = null; + for (var i = 0; i < n.length; i++) { + if (n[i].match(/[\-0-9]/g) || n[i] == '.' || n[i] == ',') { + p = i; + } + } + + // If the string has no numbers + if (p === null) { + p = n.indexOf(' '); + } + + if (index >= p) { + index = p + 1; + } + } + + // Do not update caret + if (index > n.length) { + index = n.length; + } + + if (index) { + // Set caret + if (this.tagName == 'DIV') { + var s = window.getSelection(); + var r = document.createRange(); + r.setStart(this.childNodes[0], index); + s.removeAllRanges(); + s.addRange(r); + } else { + this.selectionStart = index; + this.selectionEnd = index; + } + } + } + } + + /** + * Value getter and setter method + */ + var Value = function(v, updateCaret, adjustNumeric) { + if (this.tagName == 'DIV') { + if (v === undefined) { + return this.innerText; + } else { + if (this.innerText !== v) { + this.innerText = v; + + if (updateCaret) { + Caret.call(this, updateCaret, adjustNumeric); + } + } + } + } else { + if (v === undefined) { + return this.value; + } else { + if (this.value !== v) { + this.value = v; + if (updateCaret) { + Caret.call(this, updateCaret, adjustNumeric); + } + } + } + } + } + + // Labels + var weekDaysFull = jSuites.calendar.weekdays; + var weekDays = jSuites.calendar.weekdaysShort; + var monthsFull = jSuites.calendar.months; + var months = jSuites.calendar.monthsShort; + + var parser = { + 'YEAR': function(v, s) { + var y = ''+new Date().getFullYear(); + + if (typeof(this.values[this.index]) === 'undefined') { + this.values[this.index] = ''; + } + if (parseInt(v) >= 0 && parseInt(v) <= 10) { + if (this.values[this.index].length < s) { + this.values[this.index] += v; + } + } + if (this.values[this.index].length == s) { + if (s == 2) { + var y = y.substr(0,2) + this.values[this.index]; + } else if (s == 3) { + var y = y.substr(0,1) + this.values[this.index]; + } else if (s == 4) { + var y = this.values[this.index]; + } + this.date[0] = y; + this.index++; + } + }, + 'YYYY': function(v) { + parser.YEAR.call(this, v, 4); + }, + 'YYY': function(v) { + parser.YEAR.call(this, v, 3); + }, + 'YY': function(v) { + parser.YEAR.call(this, v, 2); + }, + 'FIND': function(v, a) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } + var pos = 0; + var count = 0; + var value = (this.values[this.index] + v).toLowerCase(); + for (var i = 0; i < a.length; i++) { + if (a[i].toLowerCase().indexOf(value) == 0) { + pos = i; + count++; + } + } + if (count > 1) { + this.values[this.index] += v; + } else if (count == 1) { + this.values[this.index] = a[pos]; + this.index++; + + return pos; + } + }, + 'MMM': function(v) { + var ret = parser.FIND.call(this, v, months); + if (ret !== undefined) { + this.date[1] = ret + 1; + } + }, + 'MMMM': function(v) { + var ret = parser.FIND.call(this, v, monthsFull); + if (ret !== undefined) { + this.date[1] = ret + 1; + } + }, + 'MMMMM': function(v) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } + var pos = 0; + var count = 0; + var value = (this.values[this.index] + v).toLowerCase(); + for (var i = 0; i < monthsFull.length; i++) { + if (monthsFull[i][0].toLowerCase().indexOf(value) == 0) { + this.values[this.index] = monthsFull[i][0]; + this.date[1] = i + 1; + this.index++; + break; + } + } + }, + 'MM': function(v) { + if (isBlank(this.values[this.index])) { + if (parseInt(v) > 1 && parseInt(v) < 10) { + this.date[1] = this.values[this.index] = '0' + v; + this.index++; + } else if (parseInt(v) < 2) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 1 && parseInt(v) < 3) { + this.date[1] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0 && parseInt(v) < 10) { + this.date[1] = this.values[this.index] += v; + this.index++; + } + } + }, + 'M': function(v) { + var test = false; + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = v; + if (v > 1) { + this.date[1] = this.values[this.index]; + this.index++; + } + } else { + if (this.values[this.index] == 1 && parseInt(v) < 3) { + this.date[1] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0) { + this.date[1] = this.values[this.index] += v; + this.index++; + } else { + var test = true; + } + } + } else { + var test = true; + } + + // Re-test + if (test == true) { + var t = parseInt(this.values[this.index]); + if (t > 0 && t < 12) { + this.date[2] = this.values[this.index]; + this.index++; + // Repeat the character + this.position--; + } + } + }, + 'D': function(v) { + var test = false; + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = v; + if (parseInt(v) > 3) { + this.date[2] = this.values[this.index]; + this.index++; + } + } else { + if (this.values[this.index] == 3 && parseInt(v) < 2) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 1 || this.values[this.index] == 2) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else { + var test = true; + } + } + } else { + var test = true; + } + + // Re-test + if (test == true) { + var t = parseInt(this.values[this.index]); + if (t > 0 && t < 32) { + this.date[2] = this.values[this.index]; + this.index++; + // Repeat the character + this.position--; + } + } + }, + 'DD': function(v) { + if (isBlank(this.values[this.index])) { + if (parseInt(v) > 3 && parseInt(v) < 10) { + this.date[2] = this.values[this.index] = '0' + v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 3 && parseInt(v) < 2) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if ((this.values[this.index] == 1 || this.values[this.index] == 2) && parseInt(v) < 10) { + this.date[2] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] == 0 && parseInt(v) > 0 && parseInt(v) < 10) { + this.date[2] = this.values[this.index] += v; + this.index++; + } + } + }, + 'DDD': function(v) { + parser.FIND.call(this, v, weekDays); + }, + 'DDDD': function(v) { + parser.FIND.call(this, v, weekDaysFull); + }, + 'HH12': function(v, two) { + if (isBlank(this.values[this.index])) { + if (parseInt(v) > 1 && parseInt(v) < 10) { + if (two) { + v = 0 + v; + } + this.date[3] = this.values[this.index] = v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 1 && parseInt(v) < 3) { + this.date[3] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] < 1 && parseInt(v) < 10) { + this.date[3] = this.values[this.index] += v; + this.index++; + } + } + }, + 'HH24': function(v, two) { + var test = false; + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (this.values[this.index] == null || this.values[this.index] == '') { + if (parseInt(v) > 2 && parseInt(v) < 10) { + if (two) { + v = 0 + v; + } + this.date[3] = this.values[this.index] = v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (this.values[this.index] == 2 && parseInt(v) < 4) { + this.date[3] = this.values[this.index] += v; + this.index++; + } else if (this.values[this.index] < 2 && parseInt(v) < 10) { + this.date[3] = this.values[this.index] += v; + this.index++; + } + } + } + }, + 'HH': function(v) { + parser['HH24'].call(this, v, 1); + }, + 'H': function(v) { + parser['HH24'].call(this, v, 0); + }, + '\\[H\\]': function(v) { + if (this.values[this.index] == undefined) { + this.values[this.index] = ''; + } + if (v.match(/[0-9]/g)) { + this.date[3] = this.values[this.index] += v; + } else { + if (this.values[this.index].match(/[0-9]/g)) { + this.date[3] = this.values[this.index]; + this.index++; + // Repeat the character + this.position--; + } + } + }, + 'N60': function(v, i) { + if (this.values[this.index] == null || this.values[this.index] == '') { + if (parseInt(v) > 5 && parseInt(v) < 10) { + this.date[i] = this.values[this.index] = '0' + v; + this.index++; + } else if (parseInt(v) < 10) { + this.values[this.index] = v; + } + } else { + if (parseInt(v) < 10) { + this.date[i] = this.values[this.index] += v; + this.index++; + } + } + }, + 'MI': function(v) { + parser.N60.call(this, v, 4); + }, + 'SS': function(v) { + parser.N60.call(this, v, 5); + }, + 'AM/PM': function(v) { + this.values[this.index] = ''; + if (v) { + if (this.date[3] > 12) { + this.values[this.index] = 'PM'; + } else { + this.values[this.index] = 'AM'; + } + } + this.index++; + }, + 'WD': function(v) { + if (typeof(this.values[this.index]) === 'undefined') { + this.values[this.index] = ''; + } + if (parseInt(v) >= 0 && parseInt(v) < 7) { + this.values[this.index] = v; + } + if (this.value[this.index].length == 1) { + this.index++; + } + }, + '0{1}(.{1}0+)?': function(v) { + // Get decimal + var decimal = getDecimal.call(this); + // Negative number + var neg = false; + // Create if is blank + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } else { + if (this.values[this.index] == '-') { + neg = true; + } + } + var current = ParseValue.call(this, this.values[this.index], decimal); + if (current) { + this.values[this.index] = current.join(decimal); + } + // New entry + if (parseInt(v) >= 0 && parseInt(v) < 10) { + if (this.values[this.index] != '0' || v == decimal) { + this.values[this.index] += v; + } + } else if (decimal && v == decimal) { + if (this.values[this.index].indexOf(decimal) == -1) { + if (! this.values[this.index]) { + this.values[this.index] = '0'; + } + this.values[this.index] += v; + } + } else if (v == '-') { + // Negative signed + neg = true; + } + + if (neg === true && this.values[this.index][0] !== '-') { + this.values[this.index] = '-' + this.values[this.index]; + } + }, + '0{1}(.{1}0+)?%': function(v) { + parser['0{1}(.{1}0+)?'].call(this, v); + + if (this.values[this.index].match(/[\-0-9]/g)) { + if (this.values[this.index] && this.values[this.index].indexOf('%') == -1) { + this.values[this.index] += '%'; + } + } else { + this.values[this.index] = ''; + } + }, + '#(.{1})##0?(.{1}0+)?( ?;(.*)?)?': function(v) { + // Parse number + parser['0{1}(.{1}0+)?'].call(this, v); + // Get decimal + var decimal = getDecimal.call(this); + // Get separator + var separator = this.tokens[this.index].substr(1,1); + // Negative + var negative = this.values[this.index][0] === '-' ? true : false; + // Current value + var current = ParseValue.call(this, this.values[this.index], decimal); + + // Get main and decimal parts + if (current !== '') { + // Format number + var n = current[0].match(/[0-9]/g); + if (n) { + // Format + n = n.join(''); + var t = []; + var s = 0; + for (var j = n.length - 1; j >= 0 ; j--) { + t.push(n[j]); + s++; + if (! (s % 3)) { + t.push(separator); + } + } + t = t.reverse(); + current[0] = t.join(''); + if (current[0].substr(0,1) == separator) { + current[0] = current[0].substr(1); + } + } else { + current[0] = ''; + } + + // Value + this.values[this.index] = current.join(decimal); + + // Negative + if (negative) { + this.values[this.index] = '-' + this.values[this.index]; + } + } + }, + '0': function(v) { + if (v.match(/[0-9]/g)) { + this.values[this.index] = v; + this.index++; + } + }, + '[0-9a-zA-Z$]+': function(v) { + if (isBlank(this.values[this.index])) { + this.values[this.index] = ''; + } + var t = this.tokens[this.index]; + var s = this.values[this.index]; + var i = s.length; + + if (t[i] == v) { + this.values[this.index] += v; + + if (this.values[this.index] == t) { + this.index++; + } + } else { + this.values[this.index] = t; + this.index++; + + if (v.match(/[\-0-9]/g)) { + // Repeat the character + this.position--; + } + } + }, + 'A': function(v) { + if (v.match(/[a-zA-Z]/gi)) { + this.values[this.index] = v; + this.index++; + } + }, + '.': function(v) { + parser['[0-9a-zA-Z$]+'].call(this, v); + } + } + + /** + * Get the tokens in the mask string + */ + var getTokens = function(str) { + if (this.type == 'general') { + var t = [].concat(tokens.general); + } else { + var t = [].concat(tokens.currency, tokens.datetime, tokens.percentage, tokens.numeric, tokens.general); + } + // Expression to extract all tokens from the string + var e = new RegExp(t.join('|'), 'gi'); + // Extract + return str.match(e); + } + + /** + * Get the method of one given token + */ + var getMethod = function(str) { + if (! this.type) { + var types = Object.keys(tokens); + } else if (this.type == 'general') { + var types = [ 'general' ]; + } else if (this.type == 'datetime') { + var types = [ 'numeric', 'datetime', 'general' ]; + } else { + var types = [ 'currency', 'percentage', 'numeric', 'general' ]; + } + + // Found + for (var i = 0; i < types.length; i++) { + var type = types[i]; + for (var j = 0; j < tokens[type].length; j++) { + var e = new RegExp(tokens[type][j], 'gi'); + var r = str.match(e); + if (r) { + return { type: type, method: tokens[type][j] } + } + } + } + } + + /** + * Identify each method for each token + */ + var getMethods = function(t) { + var result = []; + for (var i = 0; i < t.length; i++) { + var m = getMethod.call(this, t[i]); + if (m) { + result.push(m.method); + } else { + result.push(null); + } + } + + // Compatibility with excel + for (var i = 0; i < result.length; i++) { + if (result[i] == 'MM') { + // Not a month, correct to minutes + if (result[i-1] && result[i-1].indexOf('H') >= 0) { + result[i] = 'MI'; + } else if (result[i-2] && result[i-2].indexOf('H') >= 0) { + result[i] = 'MI'; + } else if (result[i+1] && result[i+1].indexOf('S') >= 0) { + result[i] = 'MI'; + } else if (result[i+2] && result[i+2].indexOf('S') >= 0) { + result[i] = 'MI'; + } + } + } + + return result; + } + + /** + * Get the type for one given token + */ + var getType = function(str) { + var m = getMethod.call(this, str); + if (m) { + var type = m.type; + } + + if (type) { + var numeric = 0; + // Make sure the correct type + var t = getTokens.call(this, str); + for (var i = 0; i < t.length; i++) { + m = getMethod.call(this, t[i]); + if (m && isNumeric(m.type)) { + numeric++; + } + } + if (numeric > 1) { + type = 'general'; + } + } + + return type; + } + + /** + * Parse character per character using the detected tokens in the mask + */ + var parse = function() { + // Parser method for this position + if (typeof(parser[this.methods[this.index]]) == 'function') { + parser[this.methods[this.index]].call(this, this.value[this.position]); + this.position++; + } else { + this.values[this.index] = this.tokens[this.index]; + this.index++; + } + } + + var isFormula = function(value) { + var v = (''+value)[0]; + return v == '=' ? true : false; + } + + var toPlainString = function(num) { + return (''+ +num).replace(/(-?)(\d*)\.?(\d*)e([+-]\d+)/, + function(a,b,c,d,e) { + return e < 0 + ? b + '0.' + Array(1-e-c.length).join(0) + c + d + : b + c + d + Array(e-d.length+1).join(0); + }); + } + + /** + * Mask function + * @param {mixed|string} JS input or a string to be parsed + * @param {object|string} When the first param is a string, the second is the mask or object with the mask options + */ + var obj = function(e, config, returnObject) { + // Options + var r = null; + var t = null; + var o = { + // Element + input: null, + // Current value + value: null, + // Mask options + options: {}, + // New values for each token found + values: [], + // Token position + index: 0, + // Character position + position: 0, + // Date raw values + date: [0,0,0,0,0,0], + // Raw number for the numeric values + number: 0, + } + + // This is a JavaScript Event + if (typeof(e) == 'object') { + // Element + o.input = e.target; + // Current value + o.value = Value.call(e.target); + // Current caret position + o.caret = Caret.call(e.target); + // Mask + if (t = e.target.getAttribute('data-mask')) { + o.mask = t; + } + // Type + if (t = e.target.getAttribute('data-type')) { + o.type = t; + } + // Options + if (e.target.mask) { + if (e.target.mask.options) { + o.options = e.target.mask.options; + } + if (e.target.mask.locale) { + o.locale = e.target.mask.locale; + } + } else { + // Locale + if (t = e.target.getAttribute('data-locale')) { + o.locale = t; + if (o.mask) { + o.options.style = o.mask; + } + } + } + // Extra configuration + if (e.target.attributes && e.target.attributes.length) { + for (var i = 0; i < e.target.attributes.length; i++) { + var k = e.target.attributes[i].name; + var v = e.target.attributes[i].value; + if (k.substr(0,4) == 'data') { + o.options[k.substr(5)] = v; + } + } + } + } else { + // Options + if (typeof(config) == 'string') { + // Mask + o.mask = config; + } else { + // Mask + var k = Object.keys(config); + for (var i = 0; i < k.length; i++) { + o[k[i]] = config[k[i]]; + } + } + + if (typeof(e) === 'number') { + // Get decimal + getDecimal.call(o, o.mask); + // Replace to the correct decimal + e = (''+e).replace('.', o.options.decimal); + } + + // Current + o.value = e; + + if (o.input) { + // Value + Value.call(o.input, e); + // Focus + jSuites.focus(o.input); + // Caret + o.caret = Caret.call(o.input); + } + } + + // Mask detected start the process + if (! isFormula(o.value) && (o.mask || o.locale)) { + // Compatibility ixes + if (o.mask) { + // Legacy + o.mask = o.mask.replace('[-]', ''); + // Excel mask TODO: Improve + if (o.mask.indexOf('##')) { + var d = o.mask.split(';'); + if (d[0]) { + d[0] = d[0].replace('*', ''); + d[0] = d[0].replace(/_/g, ''); + d[0] = d[0].replace(/-/g, ''); + d[0] = d[0].replace('(',''); + d[0] = d[0].replace(')',''); + d[0] = d[0].replace('##0.###','##0.000'); + d[0] = d[0].replace('##0.##','##0.00'); + d[0] = d[0].replace('##0.#','##0.0'); + } + o.mask = d[0]; + } + // Get type + if (! o.type) { + o.type = getType.call(o, o.mask); + } + // Get tokens + o.tokens = getTokens.call(o, o.mask); + } + // On new input + if (typeof(e) !== 'object' || ! e.inputType || e.inputType == 'insertText' || e.inputType == 'insertFromPaste') { + // Start tranformation + if (o.locale) { + if (o.input) { + Format.call(o, o.input); + } else { + var newValue = FormatValue.call(o, o.value); + } + } else { + // Get tokens + o.methods = getMethods.call(o, o.tokens); + // Go through all tokes + while (o.position < o.value.length && typeof(o.tokens[o.index]) !== 'undefined') { + // Get the approate parser + parse.call(o); + } + + if (isNumeric(o.type)) { + // Complement things in the end of the mask + while (typeof(o.tokens[o.index]) !== 'undefined') { + var t = getMethod.call(o, o.tokens[o.index]); + if (t && t.type == 'general') { + o.values[o.index] = o.tokens[o.index]; + } + o.index++; + } + + var adjustNumeric = true; + } else { + var adjustNumeric = false; + } + + // New value + var newValue = o.values.join(''); + + // Reset value + if (o.input) { + t = newValue.length - o.value.length; + if (t > 0) { + var caret = o.caret + t; + } else { + var caret = o.caret; + } + Value.call(o.input, newValue, caret, adjustNumeric); + } + } + } + + // Update raw data + if (o.input) { + var label = null; + if (isNumeric(o.type)) { + // Extract the number + o.number = Extract.call(o, Value.call(o.input)); + // Keep the raw data as a property of the tag + if (o.type == 'percentage') { + label = o.number / 100; + } else { + label = o.number; + } + } else if (o.type == 'datetime') { + label = getDate.call(o); + + if (o.date[0] && o.date[1] && o.date[2]) { + o.input.setAttribute('data-completed', true); + } + } + + if (label) { + o.input.setAttribute('data-value', label); + } + } + + if (newValue !== undefined) { + if (returnObject) { + return o; + } else { + return newValue; + } + } + } + } + + // Extract the tokens from a mask + obj.prepare = function(str, o) { + if (! o) { + o = {}; + } + return getTokens.call(o, str); + } + + /** + * Apply the mask to a element (legacy) + */ + obj.apply = function(e) { + var v = Value.call(e.target); + if (e.key.length == 1) { + v += e.key; + } + Value.call(e.target, obj(v, e.target.getAttribute('data-mask'))); + } + + /** + * Legacy support + */ + obj.run = function(value, mask, decimal) { + return obj(value, { mask, decimal }); + } + + /** + * Extract number from masked string + */ + obj.extract = function(v, options, returnObject) { + if (isBlank(v)) { + return v; + } + if (typeof(options) != 'object') { + return value; + } else { + if (! options.options) { + options.options = {}; + } + } + + // Compatibility + if (! options.mask && options.format) { + options.mask = options.format; + } + + // Get decimal + getDecimal.call(options, options.mask); + + var type = null; + if (options.type == 'percent' || options.options.style == 'percent') { + type = 'percentage'; + } else if (options.mask) { + type = getType.call(options, options.mask); + } + + + if (type === 'datetime') { + if (v instanceof Date) { + var t = jSuites.calendar.getDateString(value, options.mask); + } + + var o = obj(v, options, true); + var value = getDate.call(o); + if ((o.date[0] && o.date[1] && o.date[2]) && ! (o.date[3] || o.date[4] || o.date[5])) { + var t = jSuites.calendar.now(o.date); + value = jSuites.calendar.dateToNum(t); + } + } else { + var value = Extract.call(options, v); + // Percentage + if (type == 'percentage') { + value /= 100; + } + var o = options; + } + + o.value = value; + + if (returnObject) { + return o; + } else { + return value; + } + } + + /** + * Render + */ + obj.render = function(value, options, fullMask) { + if (isBlank(value)) { + return value; + } + + if (typeof(options) != 'object') { + return value; + } else { + if (! options.options) { + options.options = {}; + } + } + + // Compatibility + if (! options.mask && options.format) { + options.mask = options.format; + } + + var type = null; + if (options.type == 'percent' || options.options.style == 'percent') { + type = 'percentage'; + } else if (options.mask) { + type = getType.call(options, options.mask); + } else if (value instanceof Date) { + type = 'datetime'; + } + + // Fill with blanks + var fillWithBlanks = false; + + if (type =='datetime' || options.type == 'calendar') { + var t = jSuites.calendar.getDateString(value, options.mask); + if (t) { + value = t; + } + + if (options.mask && fullMask) { + fillWithBlanks = true; + } + } else { + // Percentage + if (type == 'percentage') { + value *= 100; + } + // Number of decimal places + if (typeof(value) === 'number') { + var t = null; + if (options.mask && fullMask) { + var e = new RegExp('0{1}(.{1})0+', 'ig'); + var d = options.mask.match(e); + if (d && d[0]) { + d = d[0].length - 2; + t = value.toFixed(d); + } else { + t = (''+value); + } + } else if (options.locale && fullMask) { + var d = (''+value).split('.'); + if (! d[1]) { + d[1] = '00'; + } else { + if (d[1].length == 1) { + d[1] += '0'; + } + } + t = d.join('.'); + } else { + t = toPlainString(value); + } + + if (t !== null) { + value = t; + // Get decimal + getDecimal.call(options, options.mask); + // Replace to the correct decimal + if (options.options.decimal) { + value = value.replace('.', options.options.decimal); + } + } + } else { + if (options.mask && fullMask) { + fillWithBlanks = true; + } + } + } + + if (fillWithBlanks) { + var s = options.mask.length - value.length; + if (s > 0) { + for (var i = 0; i < s; i++) { + value += ' '; + } + } + } + + value = obj(value, options); + + return value; + } + + obj.set = function(e, m) { + if (m) { + e.setAttribute('data-mask', m); + // Reset the value + var event = new Event('input', { + bubbles: true, + cancelable: true, + }); + e.dispatchEvent(event); + } + } + + if (typeof document !== 'undefined') { + document.addEventListener('input', function(e) { + if (e.target.getAttribute('data-mask') || e.target.mask) { + obj(e); + } + }); + } + + return obj; +})(); + +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, + padding: 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'); + while (el.children[0]) { + temp.appendChild(el.children[0]); + } + + obj.content = document.createElement('div'); + obj.content.className = 'jmodal_content'; + obj.content.innerHTML = el.innerHTML; + + while (temp.children[0]) { + obj.content.appendChild(temp.children[0]); + } + + obj.container = document.createElement('div'); + obj.container.className = 'jmodal'; + obj.container.appendChild(obj.content); + + if (obj.options.padding) { + obj.content.style.padding = obj.options.padding; + } + 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'; + backdrop.onclick = function() { + obj.close(); + } + 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', + dataType: 'text/html', + 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"], + ] + + palette.baby = [ + ["eddcd2","fff1e6","fde2e4","fad2e1","c5dedd","dbe7e4","f0efeb","d6e2e9","bcd4e6","99c1de"], + ["e1c4b3","ffd5b5","fab6ba","f5a8c4","aacecd","bfd5cf","dbd9d0","baceda","9dc0db","7eb1d5"], + ["daa990","ffb787","f88e95","f282a9","8fc4c3","a3c8be","cec9b3","9dbcce","82acd2","649dcb"], + ["d69070","ff9c5e","f66770","f05f8f","74bbb9","87bfae","c5b993","83aac3","699bca","4d89c2"], + ["c97d5d","f58443","eb4d57","e54a7b","66a9a7","78ae9c","b5a67e","7599b1","5c88b7","4978aa"], + ] + + if (palette[o]) { + return palette[o]; + } else { + return palette.material; + } +} + +jSuites.picker = (function(el, options) { + // Already created, update options + if (el.picker) { + return el.picker.setOptions(options, true); + } + + // New instance + var obj = { type: 'picker' }; + obj.options = {}; + + var dropdownHeader = null; + var dropdownContent = null; + + /** + * Create the content options + */ + var createContent = function() { + dropdownContent.innerHTML = ''; + + // 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.classList.add('jpicker-item'); + dropdownItem.k = keys[i]; + dropdownItem.v = obj.options.data[keys[i]]; + // Label + dropdownItem.innerHTML = obj.getLabel(keys[i]); + // Append + dropdownContent.appendChild(dropdownItem); + } + } + + /** + * Set or reset the options for the picker + */ + obj.setOptions = function(options, reset) { + // Default configuration + var defaults = { + value: 0, + data: null, + render: null, + onchange: null, + onselect: null, + onopen: null, + onclose: null, + onload: null, + width: null, + header: true, + right: false, + content: false, + columns: null, + height: null, + } + + // Legacy purpose only + if (options && options.options) { + options.data = options.options; + } + + // Loop through the initial configuration + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Start using the options + if (obj.options.header === false) { + dropdownHeader.style.display = 'none'; + } else { + dropdownHeader.style.display = ''; + } + + // Width + if (obj.options.width) { + dropdownHeader.style.width = parseInt(obj.options.width) + 'px'; + } else { + dropdownHeader.style.width = ''; + } + + // Height + if (obj.options.height) { + dropdownContent.style.maxHeight = obj.options.height + 'px'; + dropdownContent.style.overflow = 'scroll'; + } else { + dropdownContent.style.overflow = ''; + } + + if (obj.options.columns > 0) { + dropdownContent.classList.add('jpicker-columns'); + dropdownContent.style.width = obj.options.width ? obj.options.width : 36 * obj.options.columns + 'px'; + } + + if (isNaN(obj.options.value)) { + obj.options.value = '0'; + } + + // Create list from data + createContent(); + + // Set value + obj.setValue(obj.options.value); + + // Set options all returns the own instance + return obj; + } + + obj.getValue = function() { + return obj.options.value; + } + + obj.setValue = function(v) { + // Set label + obj.setLabel(v); + + // Update value + obj.options.value = String(v); + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + + if (dropdownContent.children[v].getAttribute('type') !== 'generic') { + obj.close(); + } + } + + obj.getLabel = function(v) { + var label = obj.options.data[v] || null; + if (typeof(obj.options.render) == 'function') { + label = obj.options.render(label); + } + return label; + } + + obj.setLabel = function(v) { + if (obj.options.content) { + var label = '' + obj.options.content + ''; + } else { + var label = obj.getLabel(v); + } + + dropdownHeader.innerHTML = label; + } + + obj.open = function() { + if (! el.classList.contains('jpicker-focus')) { + // Start tracking the element + jSuites.tracking(obj, true); + + // 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'; + } + + if (typeof obj.options.onopen == 'function') { + obj.options.onopen(el, obj); + } + } + } + + obj.close = function() { + if (el.classList.contains('jpicker-focus')) { + el.classList.remove('jpicker-focus'); + + // Start tracking the element + jSuites.tracking(obj, false); + + if (typeof obj.options.onclose == 'function') { + obj.options.onclose(el, obj); + } + } + } + + /** + * Create floating picker + */ + var init = function() { + // Class + el.classList.add('jpicker'); + el.setAttribute('tabindex', '900'); + el.onmousedown = function(e) { + if (! el.classList.contains('jpicker-focus')) { + obj.open(); + } + } + + // Dropdown Header + dropdownHeader = document.createElement('div'); + dropdownHeader.classList.add('jpicker-header'); + + // Dropdown content + dropdownContent = document.createElement('div'); + dropdownContent.classList.add('jpicker-content'); + dropdownContent.onclick = function(e) { + var item = jSuites.findElement(e.target, 'jpicker-item'); + if (item) { + if (item.parentNode === dropdownContent) { + // Update label + obj.setValue(item.k); + // Call method + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange.call(obj, el, obj, item.v, item.v, item.k); + } + } + } + } + + // Append content and header + el.appendChild(dropdownHeader); + el.appendChild(dropdownContent); + + // Default value + el.value = options.value || 0; + + // Set options + obj.setOptions(options); + + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj); + } + + // Change + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Reference + el.picker = obj; + } + + init(); + + 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'; + } + + // Update value + obj.options.value = value; + + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, value); + } + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: 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); + } + + // Change + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Reference + el.progressbar = obj; + + return obj; +}); + +jSuites.rating = (function(el, options) { + // Already created, update options + if (el.rating) { + return el.rating.setOptions(options, true); + } + + // New instance + var obj = {}; + obj.options = {}; + + obj.setOptions = function(options, reset) { + // 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 { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Make sure the container is empty + el.innerHTML = ''; + + // 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); + } + + // Selected option + 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'); + } + } + } + + return obj; + } + + // 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); + } + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + obj.getValue = function() { + return obj.options.value; + } + + var init = function() { + // Start plugin + obj.setOptions(options); + + // Class + el.classList.add('jrating'); + + // 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'); + } + }); + + // Change + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + // Reference + el.rating = obj; + } + + init(); + + return obj; +}); + + +jSuites.search = (function(el, options) { + if (el.search) { + return el.search; + } + + var index = null; + + var select = function(e) { + if (e.target.classList.contains('jsearch_item')) { + var element = e.target; + } else { + var element = e.target.parentNode; + } + + obj.selectIndex(element); + e.preventDefault(); + } + + var createList = function(data) { + // Reset container + container.innerHTML = ''; + // Print results + if (! data.length) { + // Show container + el.style.display = ''; + } else { + // Show container + el.style.display = 'block'; + + // Show items (only 10) + var len = data.length < 11 ? data.length : 10; + for (var i = 0; i < len; i++) { + if (typeof(data[i]) == 'string') { + var text = data[i]; + var value = data[i]; + } else { + // 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'); + div.setAttribute('data-value', value); + div.setAttribute('data-text', text); + div.className = 'jsearch_item'; + + if (data[i].id) { + div.setAttribute('id', data[i].id) + } + + if (obj.options.forceSelect && 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.innerHTML = text; + div.appendChild(item); + + // Append item to the container + container.appendChild(div); + } + } + } + + var execute = function(str) { + if (str != obj.terms) { + // New terms + obj.terms = str; + // New index + if (obj.options.forceSelect) { + index = 0; + } else { + index = null; + } + // Array or remote search + if (Array.isArray(obj.options.data)) { + var test = function(o) { + if (typeof(o) == 'string') { + if ((''+o).toLowerCase().search(str.toLowerCase()) >= 0) { + return true; + } + } else { + for (var key in o) { + var value = o[key]; + if ((''+value).toLowerCase().search(str.toLowerCase()) >= 0) { + return true; + } + } + } + return false; + } + + var results = obj.options.data.filter(function(item) { + return test(item); + }); + + // Show items + createList(results); + } else { + // Get remove results + jSuites.ajax({ + url: obj.options.data + str, + method: 'GET', + dataType: 'json', + success: function(data) { + // Show items + createList(data); + } + }); + } + } + } + + // Search timer + var timer = null; + + // Search methods + var obj = function(str) { + if (timer) { + clearTimeout(timer); + } + timer = setTimeout(function() { + execute(str); + }, 500); + } + if(options.forceSelect === null) { + options.forceSelect = true; + } + obj.options = { + data: options.data || null, + input: options.input || null, + onselect: options.onselect || null, + forceSelect: options.forceSelect, + }; + + obj.selectIndex = function(item) { + var id = item.getAttribute('id'); + var text = item.getAttribute('data-text'); + var value = item.getAttribute('data-value'); + // Onselect + if (typeof(obj.options.onselect) == 'function') { + obj.options.onselect(obj, text, value, id); + } + // Close container + obj.close(); + } + + obj.open = function() { + el.style.display = 'block'; + } + + obj.close = function() { + if (timer) { + clearTimeout(timer); + } + // Current terms + obj.terms = ''; + // Remove results + container.innerHTML = ''; + // Hide + el.style.display = ''; + } + + obj.isOpened = function() { + return el.style.display ? true : false; + } + + obj.keydown = function(e) { + if (obj.isOpened()) { + if (e.key == 'Enter') { + // Enter + if (index!==null && container.children[index]) { + obj.selectIndex(container.children[index]); + e.preventDefault(); + } else { + obj.close(); + } + } else if (e.key === 'ArrowUp') { + // Up + if (index!==null && container.children[0]) { + container.children[index].classList.remove('selected'); + if(!obj.options.forceSelect && index === 0) { + index = null; + } else { + index = Math.max(0, index-1); + container.children[index].classList.add('selected'); + } + } + e.preventDefault(); + } else if (e.key === 'ArrowDown') { + // Down + if(index == null) { + index = -1; + } else { + container.children[index].classList.remove('selected'); + } + if (index < 9 && container.children[index+1]) { + index++; + } + container.children[index].classList.add('selected'); + e.preventDefault(); + } + } + } + + obj.keyup = function(e) { + if (obj.options.input) { + obj(obj.options.input.value); + } else { + // Current node + var node = jSuites.getNode(); + if (node) { + obj(node.innerText); + } + } + } + + // Add events + if (obj.options.input) { + obj.options.input.addEventListener("keyup", obj.keyup); + obj.options.input.addEventListener("keydown", obj.keydown); + } + + // Append element + var container = document.createElement('div'); + container.classList.add('jsearch_container'); + container.onmousedown = select; + el.appendChild(container); + + el.classList.add('jsearch'); + el.search = obj; + + return obj; +}); + + +jSuites.slider = (function(el, options) { + var obj = {}; + obj.options = {}; + obj.currentImage = null; + + if (options) { + obj.options = options; + } + + // Focus + el.setAttribute('tabindex', '900') + + // Items + obj.options.items = []; + + if (! el.classList.contains('jslider')) { + el.classList.add('jslider'); + el.classList.add('unselectable'); + + if (obj.options.height) { + el.style.minHeight = obj.options.height; + } + if (obj.options.width) { + el.style.width = obj.options.width; + } + if (obj.options.grid) { + el.classList.add('jslider-grid'); + var number = el.children.length; + if (number > 4) { + el.setAttribute('data-total', number - 4); + } + el.setAttribute('data-number', (number > 4 ? 4 : number)); + } + + // Add slider counter + var counter = document.createElement('div'); + counter.classList.add('jslider-counter'); + + // 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]); + + // counter click event + var item = document.createElement('div'); + item.onclick = function() { + var index = Array.prototype.slice.call(counter.children).indexOf(this); + obj.show(obj.currentImage = obj.options.items[index]); + } + counter.appendChild(item); + } + } + // Add caption + var caption = document.createElement('div'); + caption.className = 'jslider-caption'; + + // Add close buttom + var controls = document.createElement('div'); + var close = document.createElement('div'); + close.className = 'jslider-close'; + close.innerHTML = ''; + + close.onclick = function() { + obj.close(); + } + controls.appendChild(caption); + controls.appendChild(close); + } + + obj.updateCounter = function(index) { + for (var i = 0; i < counter.children.length; i ++) { + if (counter.children[i].classList.contains('jslider-counter-focus')) { + counter.children[i].classList.remove('jslider-counter-focus'); + break; + } + } + counter.children[index].classList.add('jslider-counter-focus'); + } + + obj.show = function(target) { + if (! target) { + var target = el.children[0]; + } + + // Focus element + el.classList.add('jslider-focus'); + el.classList.remove('jslider-grid'); + el.appendChild(controls); + el.appendChild(counter); + + // Update counter + var index = obj.options.items.indexOf(target); + obj.updateCounter(index); + + // Remove display + for (var i = 0; i < el.children.length; i++) { + el.children[i].style.display = ''; + } + target.style.display = 'block'; + + // Is there any previous + if (target.previousElementSibling) { + el.classList.add('jslider-left'); + } else { + el.classList.remove('jslider-left'); + } + + // Is there any next + if (target.nextElementSibling && target.nextElementSibling.tagName == 'IMG') { + el.classList.add('jslider-right'); + } else { + el.classList.remove('jslider-right'); + } + + obj.currentImage = target; + + // Vertical image + if (obj.currentImage.offsetHeight > obj.currentImage.offsetWidth) { + obj.currentImage.classList.add('jslider-vertical'); + } + + controls.children[0].innerText = obj.currentImage.getAttribute('title'); + } + + obj.open = function() { + obj.show(); + + // Event + if (typeof(obj.options.onopen) == 'function') { + obj.options.onopen(el); + } + } + + obj.close = function() { + // Remove control classes + el.classList.remove('jslider-focus'); + el.classList.remove('jslider-left'); + el.classList.remove('jslider-right'); + // Show as a grid depending on the configuration + if (obj.options.grid) { + el.classList.add('jslider-grid'); + } + // Remove display + for (var i = 0; i < el.children.length; i++) { + el.children[i].style.display = ''; + } + // Remove controls from the component + counter.remove(); + controls.remove(); + // Current image + obj.currentImage = null; + // Event + if (typeof(obj.options.onclose) == 'function') { + obj.options.onclose(el); + } + } + + obj.reset = function() { + el.innerHTML = ''; + } + + obj.next = function() { + var nextImage = obj.currentImage.nextElementSibling; + if (nextImage && nextImage.tagName === 'IMG') { + obj.show(obj.currentImage.nextElementSibling); + } + } + + obj.prev = function() { + if (obj.currentImage.previousElementSibling) { + obj.show(obj.currentImage.previousElementSibling); + } + } + + var mouseUp = function(e) { + // Open slider + if (e.target.tagName == 'IMG') { + obj.show(e.target); + } else if (! e.target.classList.contains('jslider-close') && ! (e.target.parentNode.classList.contains('jslider-counter') || e.target.classList.contains('jslider-counter'))){ + // Arrow controls + var offsetX = e.offsetX || e.changedTouches[0].clientX; + if (e.target.clientWidth - offsetX < 40) { + // Show next image + obj.next(); + } else if (offsetX < 40) { + // Show previous image + obj.prev(); + } + } + } + + if ('ontouchend' in document.documentElement === true) { + el.addEventListener('touchend', mouseUp); + } else { + el.addEventListener('mouseup', 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(); + }); + + el.addEventListener('keydown', function(e) { + if (e.which == 27) { + obj.close(); + } + }); + + el.slider = obj; + + return obj; +}); + +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'); + } + } + + el.val = function() { + var id = null; + var data = []; + for (var i = 0; i < el.children.length; i++) { + if (id = el.children[i].getAttribute('data-id')) { + data.push(id); + } + } + return data; + } + + 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, + palette: null, + maxWidth: 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) { + if (obj.options.animation) { + var rect = obj.headers.children[index].getBoundingClientRect(); + + if (obj.options.palette == 'modern') { + border.style.width = rect.width - 4 + 'px'; + border.style.left = obj.headers.children[index].offsetLeft + 2 + 'px'; + } else { + border.style.width = rect.width + 'px'; + border.style.left = obj.headers.children[index].offsetLeft + 'px'; + } + + if (obj.options.position == 'bottom') { + border.style.top = '0px'; + } else { + 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 = ''; + } + } + + obj.setBorder = setBorder; + + // 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 { + // Set border + setBorder(index); + + obj.headers.parentNode.style.display = ''; + + 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.remove = 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, cb) { + 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); + + // Callback + if (typeof(cb) == 'function') { + cb(div, h); + } + + // Return element + return div; + } + } + + obj.getActive = function() { + for (var i = 0; i < obj.headers.children.length; i++) { + if (obj.headers.children[i].classList.contains('jtabs-selected')) { + return i + } + } + return 0; + } + + obj.updateContent = function(position, newContent) { + if (typeof newContent !== 'string') { + var contentItem = newContent; + } else { + var contentItem = document.createElement('div'); + contentItem.innerHTML = newContent; + } + + if (obj.content.children[position].classList.contains('jtabs-selected')) { + newContent.classList.add('jtabs-selected'); + } + + obj.content.replaceChild(newContent, obj.content.children[position]); + } + + obj.updatePosition = function(f, t) { + // Ondrop update position of content + if (f > t) { + obj.content.insertBefore(obj.content.children[f], obj.content.children[t]); + } else { + obj.content.insertBefore(obj.content.children[f], obj.content.children[t].nextSibling); + } + + // Open destination tab + obj.open(t); + + // Call event + if (typeof(obj.options.onchangeposition) == 'function') { + obj.options.onchangeposition(obj.headers, f, t); + } + } + + obj.move = function(f, t) { + if (f > t) { + obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t]); + } else { + obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t].nextSibling); + } + + obj.updatePosition(f, t); + } + + obj.setBorder = setBorder; + + 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'); + + if (obj.options.palette) { + el.classList.add('jtabs-modern'); + } else { + el.classList.remove('jtabs-modern'); + } + + // 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); + if (obj.options.maxWidth) { + header.style.maxWidth = parseInt(obj.options.maxWidth) + 'px'; + } + + // Controls + var controls = document.createElement('div'); + controls.className = 'jtabs-controls'; + controls.setAttribute('draggable', 'false'); + header.appendChild(controls); + + // Append DOM elements + if (obj.options.position == 'bottom') { + el.appendChild(obj.content); + el.appendChild(header); + } else { + 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++) { + // Title + if (obj.options.data[i].titleElement) { + var headerItem = obj.options.data[i].titleElement; + } else { + var headerItem = document.createElement('div'); + } + // Icon + if (obj.options.data[i].icon) { + var iconContainer = document.createElement('div'); + var icon = document.createElement('i'); + icon.classList.add('material-icons'); + icon.innerHTML = obj.options.data[i].icon; + iconContainer.appendChild(icon); + headerItem.appendChild(iconContainer); + } + // Title + if (obj.options.data[i].title) { + var title = document.createTextNode(obj.options.data[i].title); + headerItem.appendChild(title); + } + // Width + if (obj.options.data[i].width) { + headerItem.style.width = obj.options.data[i].width; + } + // Content + if (obj.options.data[i].contentElement) { + var contentItem = obj.options.data[i].contentElement; + } else { + var contentItem = document.createElement('div'); + 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) { + if (e.target.parentNode.classList.contains('jtabs-headers')) { + var target = e.target; + } else { + if (e.target.tagName == 'I') { + var target = e.target.parentNode.parentNode; + } else { + var target = e.target.parentNode; + } + } + + var index = obj.selectIndex(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) { + obj.updatePosition(b,c); + }, + }); + } + + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj); + } + } + + // Loading existing nodes as the data + if (el.children[0] && el.children[0].children.length) { + // Create from existing elements + for (var i = 0; i < el.children[0].children.length; i++) { + var item = obj.options.data && obj.options.data[i] ? obj.options.data[i] : {}; + + if (el.children[1] && el.children[1].children[i]) { + item.titleElement = el.children[0].children[i]; + item.contentElement = el.children[1].children[i]; + } else { + item.contentElement = el.children[0].children[i]; + } + + obj.options.data[i] = item; + } + } + + // 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) { + // Redefine configuration + if (el.tags) { + return el.tags.setOptions(options, true); + } + + var obj = { type:'tags' }; + obj.options = {}; + + // Limit + var limit = function() { + return obj.options.limit && el.children.length >= obj.options.limit ? true : false; + } + + // Search helpers + var search = null; + var searchContainer = null; + + obj.setOptions = function(options, reset) { + /** + * @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: '', + limit: null, + limitMessage: null, + search: null, + placeholder: null, + validation: null, + onbeforechange: null, + onlimit: 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 { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Placeholder + if (obj.options.placeholder) { + el.setAttribute('data-placeholder', obj.options.placeholder); + } else { + el.removeAttribute('data-placeholder'); + } + el.placeholder = obj.options.placeholder; + + // Update value + obj.setValue(obj.options.value); + + // Validate items + filter(); + + // Create search box + if (obj.options.search) { + if (! searchContainer) { + searchContainer = document.createElement('div'); + el.parentNode.insertBefore(searchContainer, el.nextSibling); + + // Create container + search = jSuites.search(searchContainer, { + data: obj.options.search, + onselect: function(a,b,c) { + obj.selectIndex(b,c); + } + }); + } + } else { + if (searchContainer) { + search = null; + searchContainer.remove(); + searchContainer = null; + } + } + + return obj; + } + + /** + * 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 ret = obj.options.onbeforechange(el, obj, obj.options.value, value); + if (ret === false) { + return false; + } else { + if (ret != null) { + value = ret; + } + } + } + + // Make sure search is closed + if (search) { + search.close(); + } + + if (limit()) { + if (typeof(obj.options.onlimit) == 'function') { + obj.options.onlimit(obj, obj.options.limit); + } else if (obj.options.limitMessage) { + alert(obj.options.limitMessage + ' ' + obj.options.limit); + } + } else { + // Get node + var node = jSuites.getNode(); + + if (node && node.parentNode && node.parentNode.classList.contains('jtags') && + node.nextSibling && (! (node.nextSibling.innerText && node.nextSibling.innerText.trim()))) { + div = node.nextSibling; + } else { + // Remove not used last item + if (el.lastChild) { + if (! el.lastChild.innerText.trim()) { + el.removeChild(el.lastChild); + } + } + + // Mix argument string or array + if (! value || typeof(value) == 'string') { + var div = createElement(value, value, node); + } else { + for (var i = 0; i <= value.length; i++) { + if (! limit()) { + if (! value[i] || typeof(value[i]) == 'string') { + var t = value[i] || ''; + var v = null; + } else { + var t = value[i].text; + var v = value[i].value; + } + + // Add element + var div = createElement(t, v); + } + } + } + + // Change + change(); + } + + // Place caret + if (focus) { + setFocus(div); + } + } + } + + obj.setLimit = function(limit) { + obj.options.limit = limit; + var n = el.children.length - limit; + while (el.children.length > limit) { + el.removeChild(el.lastChild); + } + } + + // Remove a item node + obj.remove = function(node) { + // Remove node + node.parentNode.removeChild(node); + // Make sure element is not blank + if (! el.children.length) { + obj.add('', true); + } else { + change(); + } + } + + /** + * 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 {mixed} value - A string or array object with values + */ + obj.setValue = function(mixed) { + if (! mixed) { + obj.reset(); + } else { + if (el.value != mixed) { + if (Array.isArray(mixed)) { + obj.add(mixed); + } else { + // Remove whitespaces + var text = (''+mixed).trim(); + // Tags + var data = extractTags(text); + // Reset + el.innerHTML = ''; + // Add tags to the element + obj.add(data); + } + } + } + } + + /** + * Reset the data from the element + */ + obj.reset = function() { + // Empty class + el.classList.add('jtags-empty'); + // Empty element + el.innerHTML = '
'; + // Execute changes + 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(text, value) { + var node = jSuites.getNode(); + if (node) { + // Append text to the caret + node.innerText = text; + // Set node id + if (value) { + node.setAttribute('data-value', value); + } + // Remove any error + node.classList.remove('jtags_error'); + if (! limit()) { + // Add new item + obj.add('', true); + } + } + } + + /** + * Search for suggestions + * @param {object} node - Target node for any suggestions + */ + obj.search = function(node) { + // Search for + var terms = node.innerText; + } + + // 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 setFocus = function(node) { + if (el.children.length > 1) { + var range = document.createRange(); + var sel = window.getSelection(); + if (! node) { + var node = el.childNodes[el.childNodes.length-1]; + } + range.setStart(node, node.length) + range.collapse(true) + sel.removeAllRanges() + sel.addRange(range) + el.scrollLeft = el.scrollWidth; + } + } + + var createElement = function(label, value, node) { + var div = document.createElement('div'); + div.innerHTML = label ? label : ''; + if (value) { + div.setAttribute('data-value', value); + } + + if (node && node.parentNode.classList.contains('jtags')) { + el.insertBefore(div, node.nextSibling); + } else { + el.appendChild(div); + } + + return div; + } + + var change = function() { + // Value + var value = obj.getValue(); + + if (value != obj.options.value) { + obj.options.value = value; + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, obj, obj.options.value); + } + + // Lemonade JS + if (el.value != obj.options.value) { + el.value = obj.options.value; + if (typeof(el.onchange) == 'function') { + el.onchange({ + type: 'change', + target: el, + value: el.value + }); + } + } + } + + filter(); + } + + /** + * 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'); + } + } else { + el.children[i].classList.remove('jtags_error'); + } + } + } + + isEmpty(); + } + + var isEmpty = function() { + // Can't be empty + if (! el.innerText.trim()) { + el.innerHTML = '
'; + el.classList.add('jtags-empty'); + } else { + el.classList.remove('jtags-empty'); + } + } + + /** + * 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; + + // Verify if is empty + isEmpty(); + + // Comma + if (e.key === 'Tab' || e.key === ';' || e.key === ',') { + var n = window.getSelection().anchorOffset; + if (n > 1) { + if (limit()) { + if (typeof(obj.options.onlimit) == 'function') { + obj.options.onlimit(obj, obj.options.limit) + } + } else { + obj.add('', true); + } + } + e.preventDefault(); + } else if (e.key == 'Enter') { + if (! search || ! search.isOpened()) { + var n = window.getSelection().anchorOffset; + if (n > 1) { + if (! limit()) { + obj.add('', true); + } + } + e.preventDefault(); + } + } else if (e.key == 'Backspace') { + // Back space - do not let last item to be removed + if (el.children.length == 1 && window.getSelection().anchorOffset < 1) { + e.preventDefault(); + } + } + + // Search events + if (search) { + search.keydown(e); + } + } + + /** + * 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 (search) { + search.keyup(e); + } + } + + filter(); + } + + /** + * Processing event paste on the element + * @param e {object} + */ + var tagsPaste = function(e) { + if (e.clipboardData || e.originalEvent.clipboardData) { + var text = (e.originalEvent || e).clipboardData.getData('text/plain'); + } else if (window.clipboardData) { + var text = window.clipboardData.getData('Text'); + } + + var data = extractTags(text); + if (data.length > 1) { + obj.add(data, true); + 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); + } + } + } + + // Set focus in the last item + if (e.target == el) { + setFocus(); + } + } + + var tagsFocus = function() { + if (! el.classList.contains('jtags-focus')) { + if (! el.children.length || obj.getValue(el.children.length - 1)) { + if (! limit()) { + createElement(''); + } + } + + if (typeof(obj.options.onfocus) == 'function') { + obj.options.onfocus(el, obj, obj.getValue()); + } + + el.classList.add('jtags-focus'); + } + } + + var tagsBlur = function() { + if (el.classList.contains('jtags-focus')) { + if (search) { + search.close(); + } + + for (var i = 0; i < el.children.length - 1; i++) { + // Create label design + if (! obj.getValue(i)) { + el.removeChild(el.children[i]); + } + } + + change(); + + el.classList.remove('jtags-focus'); + + if (typeof(obj.options.onblur) == 'function') { + obj.options.onblur(el, obj, obj.getValue()); + } + } + } + + var init = function() { + // Bind events + if ('touchend' in document.documentElement === true) { + el.addEventListener('touchend', tagsMouseUp); + } else { + el.addEventListener('mouseup', tagsMouseUp); + } + + el.addEventListener('keydown', tagsKeyDown); + el.addEventListener('keyup', tagsKeyUp); + el.addEventListener('paste', tagsPaste); + el.addEventListener('focus', tagsFocus); + el.addEventListener('blur', tagsBlur); + + // Editable + el.setAttribute('contenteditable', true); + + // Prepare container + el.classList.add('jtags'); + + // Initial options + obj.setOptions(options); + + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj); + } + + // Change methods + el.change = obj.setValue; + + // Global generic value handler + el.val = function(val) { + if (val === undefined) { + return obj.getValue(); + } else { + obj.setValue(val); + } + } + + el.tags = obj; + } + + init(); + + return obj; +}); + +jSuites.toolbar = (function(el, options) { + // New instance + var obj = { type:'toolbar' }; + obj.options = {}; + + // Default configuration + var defaults = { + app: null, + container: false, + badge: false, + title: false, + responsive: false, + maxWidth: null, + 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); + } + + // Arrow + var toolbarArrow = document.createElement('div'); + toolbarArrow.classList.add('jtoolbar-item'); + toolbarArrow.classList.add('jtoolbar-arrow'); + + var toolbarFloating = document.createElement('div'); + toolbarFloating.classList.add('jtoolbar-floating'); + toolbarArrow.appendChild(toolbarFloating); + + 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 = ''; + } + + obj.update = function(a, b) { + for (var i = 0; i < toolbarContent.children.length; i++) { + // Toolbar element + var toolbarItem = toolbarContent.children[i]; + // State management + if (typeof(toolbarItem.updateState) == 'function') { + toolbarItem.updateState(el, obj, toolbarItem, a, b); + } + } + } + + 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].updateState) { + toolbarItem.updateState = items[i].updateState; + } + + if (items[i].active) { + toolbarItem.classList.add('jtoolbar-active'); + } + + if (items[i].type == 'select' || items[i].type == 'dropdown') { + 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 = items[i].onclick.bind(items[i], el, obj, toolbarItem); + } + + toolbarContent.appendChild(toolbarItem); + } + + // Fits to the page + obj.refresh(); + } + + obj.open = function() { + toolbarArrow.classList.add('jtoolbar-arrow-selected'); + + var rect = toolbarFloating.getBoundingClientRect(); + if (rect.bottom > window.innerHeight) { + toolbarFloating.style.bottom = '0'; + } else { + toolbarFloating.style.removeProperty('bottom'); + } + + toolbarFloating.style.right = '0'; + + toolbarArrow.children[0].focus(); + // Start tracking + jSuites.tracking(obj, true); + } + + obj.close = function() { + toolbarArrow.classList.remove('jtoolbar-arrow-selected') + // End tracking + jSuites.tracking(obj, false); + } + + obj.refresh = function() { + if (obj.options.responsive == true) { + // Width of the c + var rect = el.parentNode.getBoundingClientRect(); + if (! obj.options.maxWidth) { + obj.options.maxWidth = rect.width; + } + // Max width + var width = parseInt(obj.options.maxWidth); + // Remove arrow + toolbarArrow.remove(); + // Move all items to the toolbar + while (toolbarFloating.firstChild) { + toolbarContent.appendChild(toolbarFloating.firstChild); + } + // Available parent space + var available = obj.options.maxWidth; + // Toolbar is larger than the parent, move elements to the floating element + if (available < toolbarContent.offsetWidth) { + // Give space to the floating element + available -= 50; + // Move to the floating option + while (toolbarContent.lastChild && available < toolbarContent.offsetWidth) { + toolbarFloating.insertBefore(toolbarContent.lastChild, toolbarFloating.firstChild); + } + } + // Show arrow + if (toolbarFloating.children.length > 0) { + toolbarContent.appendChild(toolbarArrow); + } + } + } + + el.onclick = function(e) { + var element = jSuites.findElement(e.target, 'jtoolbar-item'); + if (element) { + obj.selectItem(element); + } + + if (e.target.classList.contains('jtoolbar-arrow')) { + obj.open(); + } + } + + window.addEventListener('resize', function() { + obj.refresh(); + }); + + // Toolbar + el.classList.add('jtoolbar'); + // Reset content + el.innerHTML = ''; + // Container + if (obj.options.container == true) { + el.classList.add('jtoolbar-container'); + } + // Content + var toolbarContent = document.createElement('div'); + el.appendChild(toolbarContent); + // Special toolbar for mobile applications + if (obj.options.app) { + el.classList.add('jtoolbar-mobile'); + } + // Create toolbar + obj.create(obj.options.items); + // Shortcut + el.toolbar = obj; + + return obj; +}); + +jSuites.validations = function(value, options) { + if (typeof(jSuites.validations[options.type]) === 'function') { + return jSuites.validations[options.type](value, options); + } + return null; +}; + +// Legacy +jSuites.validations.email = function(data) { + var pattern = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/); + return data && pattern.test(data) ? true : false; +} + +jSuites.validations.required = function(data) { + return data.trim() ? true : false; +} + +jSuites.validations.number = function(data) { + return jSuites.isNumber(data); +} + +jSuites.validations.login = function(data) { + var pattern = new RegExp(/^[a-zA-Z0-9\_\-\.\s+]+$/); + return data && pattern.test(data) ? true : false; +} + +/** + * Options: Object, + * Properties: + * Constraint, + * Reference, + * Value + */ + +var valueComparisons = function(data, options) { + if (options.constraint === '=') { + return data === options.reference; + } + if (options.constraint === '<') { + return data < options.reference; + } + if (options.constraint === '<=') { + return data <= options.reference; + } + if (options.constraint === '>') { + return data > options.reference; + } + if (options.constraint === '>=') { + return data >= options.reference; + } + if (options.constraint === 'between') { + return data >= options.reference[0] && data <= options.reference[1]; + } + if (options.constraint === 'not between') { + return data < options.reference[0] || data > options.reference[1]; + } + + return null; +} + +jSuites.validations.number = function(data, options) { + if (!jSuites.isNumeric(data)) { + return false; + } + + if (options === undefined || options.constraint === undefined) { + return true; + } + + return valueComparisons(data, options); +} + +jSuites.validations.date = function(data, options) { + if (new Date(data) == 'Invalid Date') { + return false; + } + + if (options === undefined || options.constraint === undefined) { + return true; + } else if (typeof(options) === 'object') { + data = new Date(data).getTime(); + + if (Array.isArray(options.reference)) { + options.reference = options.reference.map(function(reference) { + return new Date(reference).getTime(); + }); + } else { + options.reference = new Date(options.reference).getTime(); + } + + return valueComparisons(data, options); + } + return null; +} + +jSuites.validations.itemList = function(data, options) { + return options.reference.some(function(reference) { + return reference == data; + }); +} + +jSuites.validations.text = function(data, options) { + if (typeof data !== 'string') { + return false; + } + + if (options === undefined || options.constraint === undefined) { + return true; + } + if (options.constraint === '=') { + return data === options.reference; + } + if (options.constraint === 'contains') { + return data.includes(options.reference); + } + if (options.constraint === 'not contain') { + return !data.includes(options.reference); + } + if (options.constraint === 'email') { + return jSuites.validations.email(data); + } + if (options.constraint === 'url') { + var pattern = new RegExp(/(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig); + return pattern.test(data) ? true : false; + } + return null; +} + +jSuites.validations.constraints = function() { +} + + + + return jSuites; + +}))); \ No newline at end of file diff --git a/web/_static/jsuites/jsuites.layout.css b/web/_static/jsuites/jsuites.layout.css new file mode 100644 index 0000000..8ef5842 --- /dev/null +++ b/web/_static/jsuites/jsuites.layout.css @@ -0,0 +1,2306 @@ + +/** + * (c) jSuites Javascript Web Components + * + * Website: https://jsuites.net + * 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.red { + background-color: #a23131; + border: 1px solid transparent; + color: #fff; +} + +.jbutton.blue { + border:1px solid transparent; + color:#fff; + background-color:#1a73e8; +} + +.jbutton.mobile { + padding:4px; + padding-left:25px; + padding-right:25px; + cursor:pointer; + min-width:100px; + outline:none; +} + +.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; +} + +@media only screen and (max-width : 800px) { + .jbutton { + margin: 2px; + } +} + +.jbuttons-group { + display: flex; + cursor: pointer; + align-items: center; + justify-content: center; + -webkit-tap-highlight-color: transparent; +} + +.jbuttons-group .jbutton { + border-radius: 0px; + border: 1px solid gray; + margin: 0px; + font-size: 0.9em; +} + +.jbuttons-group.mobile .jbutton { + border-color: var(--active-color); + color: var(--active-color); + padding:4px; + padding-left:25px; + padding-right:25px; + cursor:pointer; + min-width:100px; + outline:none; +} + +.jbuttons-group .jbutton.selected { + color: white; + background-color: var(--active-color); +} + +.jbuttons-group .jbutton:first-child { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} + +.jbuttons-group .jbutton:last-child { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +/*.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); } + +.jrange { + -webkit-appearance: none; + width: 100%; + height: 4px; + background: #d3d3d3; + outline: none; + opacity: 0.7; + -webkit-transition: .2s; + transition: opacity .2s; + padding: 0px; +} + +.jrange:hover { + opacity: 1; +} + +.jrange::-webkit-slider-thumb { + background: #4CAF50; + cursor: pointer; +} + +.jrange::-moz-range-thumb { + background: #4CAF50; + cursor: pointer; +} + +.jcrop { + position: relative; + overflow: hidden; +} +.jcrop-area { + position: absolute; + border: 1px solid transparent; + background: url('data:image/gif;base64,R0lGODlhWAIBAPAAAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAAABACwAAAAAWAIBAAACQ0QeoIbL51BaMjZ6VcWQT509n2h1oEl65bidbNim7kqr9nzLeszDPtoD/l7CIvFYwyl3wyTT6Awic9Jok3pdVrFQRQEAIfkECQAAAQAsAAAAAFgCAQAAAkIEgmGWur1OivBNi+hlW2bscJ8YemVFaqOpnh3Kgu0s16kd33rOw/4LXP2EQRfxaEzSdkMlrrnsFaPQ59SKpF6Z1wIAIfkECQAAAQAsAAAAAFgCAQAAAkKEg2GXC6kWdFM2i+hlGUf+PZvYgVpJhpXpneq4pu7c1uwt2zke9/CP8gWBr6GxiKTxiMqdU5jUQZtTKdN6pF6X2QIAIfkECQAAAQAsAAAAAFgCAQAAAkOEERmHyroOfE5WM22iW0d8NR04ip/JnRmphivqpXJMs7Ndw/iu9+/vCpaAQ2GriDwqbz4jk7jMQZ9OaZU3tSapSEABACH5BAkAAAEALAAAAABYAgEAAAJDDA6hhsvnUFoyNnpVxZBPnT2faHWgSXrluJ1s2KbuSqv2fMt6zMM+2gP+XsIi8VjDKXfDJNPoDCJz0miTel1WsVBFAQAh+QQJAAABACwAAAAAWAIBAAACQkyAYJa6vU6K8E2L6GVbZuxwnxh6ZUVqo6meHcqC7SzXqR3fes7D/gtc/YRBF/FoTNJ2QyWuuewVo9Dn1IqkXpnXAgAh+QQJAAABACwAAAAAWAIBAAACQoyBYJcbqRZ0UzaL6GUZR/49m9iBWkmGlemd6rim7tzW7C3bOR738I/yBYGvobGIpPGIyp1TmNRBm1Mp03qkXpfZAgAh+QQFAAABACwAAAAAWAIBAAACQowDCYfKug58TlYzbaJbR3w1HTiKn8mdGamGK+qlckyzs13D+K737+8KloBDYauIPCpvPiOTuMxBn05plTe1JqnJAgA7') repeat-x top border-box, + url('data:image/gif;base64,R0lGODlhWAIBAPAAAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAAABACwAAAAAWAIBAAACQ0QeoIbL51BaMjZ6VcWQT509n2h1oEl65bidbNim7kqr9nzLeszDPtoD/l7CIvFYwyl3wyTT6Awic9Jok3pdVrFQRQEAIfkECQAAAQAsAAAAAFgCAQAAAkIEgmGWur1OivBNi+hlW2bscJ8YemVFaqOpnh3Kgu0s16kd33rOw/4LXP2EQRfxaEzSdkMlrrnsFaPQ59SKpF6Z1wIAIfkECQAAAQAsAAAAAFgCAQAAAkKEg2GXC6kWdFM2i+hlGUf+PZvYgVpJhpXpneq4pu7c1uwt2zke9/CP8gWBr6GxiKTxiMqdU5jUQZtTKdN6pF6X2QIAIfkECQAAAQAsAAAAAFgCAQAAAkOEERmHyroOfE5WM22iW0d8NR04ip/JnRmphivqpXJMs7Ndw/iu9+/vCpaAQ2GriDwqbz4jk7jMQZ9OaZU3tSapSEABACH5BAkAAAEALAAAAABYAgEAAAJDDA6hhsvnUFoyNnpVxZBPnT2faHWgSXrluJ1s2KbuSqv2fMt6zMM+2gP+XsIi8VjDKXfDJNPoDCJz0miTel1WsVBFAQAh+QQJAAABACwAAAAAWAIBAAACQkyAYJa6vU6K8E2L6GVbZuxwnxh6ZUVqo6meHcqC7SzXqR3fes7D/gtc/YRBF/FoTNJ2QyWuuewVo9Dn1IqkXpnXAgAh+QQJAAABACwAAAAAWAIBAAACQoyBYJcbqRZ0UzaL6GUZR/49m9iBWkmGlemd6rim7tzW7C3bOR738I/yBYGvobGIpPGIyp1TmNRBm1Mp03qkXpfZAgAh+QQFAAABACwAAAAAWAIBAAACQowDCYfKug58TlYzbaJbR3w1HTiKn8mdGamGK+qlckyzs13D+K737+8KloBDYauIPCpvPiOTuMxBn05plTe1JqnJAgA7') repeat-x bottom border-box, + url('data:image/gif;base64,R0lGODlhAQCQAfAAAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAAABACwAAAAAAQCQAQACM0QeoIbL51BaMjZ6VcWQT509n2h1oEl65bidbNim7kqr9nzLeszDPtoD/l7CIvFYwyllBQAh+QQJAAABACwAAAAAAQCQAQACMwSCYZa6vU6K8E2L6GVbZuxwnxh6ZUVqo6meHcqC7SzXqR3fes7D/gtc/YRBF/FoTNJuBQAh+QQJAAABACwAAAAAAQCQAQACM4SDYZcLqRZ0UzaL6GUZR/49m9iBWkmGlemd6rim7tzW7C3bOR738I/yBYGvobGIpPEaBQAh+QQJAAABACwAAAAAAQCQAQACNIQRGYfKug58TlYzbaJbR3w1HTiKn8mdGamGK+qlckyzs13D+K737+8KloBDYauIPCo5gAIAIfkECQAAAQAsAAAAAAEAkAEAAjMMDqGGy+dQWjI2elXFkE+dPZ9odaBJeuW4nWzYpu5Kq/Z8y3rMwz7aA/5ewiLxWMMpZQUAIfkECQAAAQAsAAAAAAEAkAEAAjNMgGCWur1OivBNi+hlW2bscJ8YemVFaqOpnh3Kgu0s16kd33rOw/4LXP2EQRfxaEzSbgUAIfkECQAAAQAsAAAAAAEAkAEAAjOMgWCXG6kWdFM2i+hlGUf+PZvYgVpJhpXpneq4pu7c1uwt2zke9/CP8gWBr6GxiKTxGgUAIfkEBQAAAQAsAAAAAAEAkAEAAjOMAwmHyroOfE5WM22iW0d8NR04ip/JnRmphivqpXJMs7Ndw/iu9+/vCpaAQ2GriDwqUwUAOw==') repeat-y left border-box, + url('data:image/gif;base64,R0lGODlhAQCQAfAAAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAAABACwAAAAAAQCQAQACM0QeoIbL51BaMjZ6VcWQT509n2h1oEl65bidbNim7kqr9nzLeszDPtoD/l7CIvFYwyllBQAh+QQJAAABACwAAAAAAQCQAQACMwSCYZa6vU6K8E2L6GVbZuxwnxh6ZUVqo6meHcqC7SzXqR3fes7D/gtc/YRBF/FoTNJuBQAh+QQJAAABACwAAAAAAQCQAQACM4SDYZcLqRZ0UzaL6GUZR/49m9iBWkmGlemd6rim7tzW7C3bOR738I/yBYGvobGIpPEaBQAh+QQJAAABACwAAAAAAQCQAQACNIQRGYfKug58TlYzbaJbR3w1HTiKn8mdGamGK+qlckyzs13D+K737+8KloBDYauIPCo5gAIAIfkECQAAAQAsAAAAAAEAkAEAAjMMDqGGy+dQWjI2elXFkE+dPZ9odaBJeuW4nWzYpu5Kq/Z8y3rMwz7aA/5ewiLxWMMpZQUAIfkECQAAAQAsAAAAAAEAkAEAAjNMgGCWur1OivBNi+hlW2bscJ8YemVFaqOpnh3Kgu0s16kd33rOw/4LXP2EQRfxaEzSbgUAIfkECQAAAQAsAAAAAAEAkAEAAjOMgWCXG6kWdFM2i+hlGUf+PZvYgVpJhpXpneq4pu7c1uwt2zke9/CP8gWBr6GxiKTxGgUAIfkEBQAAAQAsAAAAAAEAkAEAAjOMAwmHyroOfE5WM22iW0d8NR04ip/JnRmphivqpXJMs7Ndw/iu9+/vCpaAQ2GriDwqUwUAOw==') repeat-y right border-box; + display: none; +} + +.jcrop canvas { + position: absolute; + background: transparent; + left: 0; + top: 0; +} + +.jcrop.jcrop_edition { + background-repeat: initial; + background-size: initial; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFuGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTExLTIxVDIwOjQzOjQ4WiIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMC0xMS0yMVQyMDo0Mzo0OFoiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTExLTIxVDIwOjQzOjQ4WiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3ZmI2ZmZiNS00NmVmLWNhNDctOGUxMy1mYWY4NTA5MzJlNDIiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpjOWE3NGEyZi02MGJlLWJjNDItODc3Ny0zY2E2ZjkxMTRmOGQiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjMWQzMzMxNy1jZDE4LTY5NDEtYWY5Ni0xMWNjZjE4ODE1NjgiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpjMWQzMzMxNy1jZDE4LTY5NDEtYWY5Ni0xMWNjZjE4ODE1NjgiIHN0RXZ0OndoZW49IjIwMjAtMTEtMjFUMjA6NDM6NDhaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjdmYjZmZmI1LTQ2ZWYtY2E0Ny04ZTEzLWZhZjg1MDkzMmU0MiIgc3RFdnQ6d2hlbj0iMjAyMC0xMS0yMVQyMDo0Mzo0OFoiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7KEhjgAAAAPklEQVRIie3QsQ0AIAwDQcIE3n/JZINkBSMakN716wpHZi57kvx4++npoKGhoR+lo7v9uqr8+M9DoKGhoW82fHEJBd4qufYAAAAASUVORK5CYII=) +} + +.jcrop.jcrop_edition .jcrop-area { + display: block; +} + +@media screen and (min-width:0\0) and (min-resolution: +72dpi) { + .jcrop-area { + background: none; + border-image: url('data:image/gif;base64,R0lGODlhCgAKAJECAAAAAP///////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEI5RDc5MTFDNkE2MTFFM0JCMDZEODI2QTI4MzJBOTIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEI5RDc5MTBDNkE2MTFFM0JCMDZEODI2QTI4MzJBOTIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4MDgzQzNDMjA5MzREQ0ZDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4MDgzQzNDMjA5MzREQ0ZDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEBQoAAgAsAAAAAAoACgAAAhWEERkn7W3ei7KlagMWF/dKgYeyGAUAIfkEBQoAAgAsAAAAAAoACgAAAg+UYwLJ7RnQm7QmsCyVKhUAIfkEBQoAAgAsAAAAAAoACgAAAhCUYgLJHdiinNSAVfOEKoUCACH5BAUKAAIALAAAAAAKAAoAAAIRVISAdusPo3RAzYtjaMIaUQAAIfkEBQoAAgAsAAAAAAoACgAAAg+MDiem7Q8bSLFaG5il6xQAIfkEBQoAAgAsAAAAAAoACgAAAg+UYRLJ7QnQm7SmsCyVKhUAIfkEBQoAAgAsAAAAAAoACgAAAhCUYBLJDdiinNSEVfOEKoECACH5BAUKAAIALAAAAAAKAAoAAAIRFISBdusPo3RBzYsjaMIaUQAAOw==') 1 repeat; + } +} + +@-moz-document url-prefix() { + .jcrop-area { + background: none; + border-image: url('data:image/gif;base64,R0lGODlhCgAKAJECAAAAAP///////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEI5RDc5MTFDNkE2MTFFM0JCMDZEODI2QTI4MzJBOTIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEI5RDc5MTBDNkE2MTFFM0JCMDZEODI2QTI4MzJBOTIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4MDgzQzNDMjA5MzREQ0ZDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4MDgzQzNDMjA5MzREQ0ZDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEBQoAAgAsAAAAAAoACgAAAhWEERkn7W3ei7KlagMWF/dKgYeyGAUAIfkEBQoAAgAsAAAAAAoACgAAAg+UYwLJ7RnQm7QmsCyVKhUAIfkEBQoAAgAsAAAAAAoACgAAAhCUYgLJHdiinNSAVfOEKoUCACH5BAUKAAIALAAAAAAKAAoAAAIRVISAdusPo3RAzYtjaMIaUQAAIfkEBQoAAgAsAAAAAAoACgAAAg+MDiem7Q8bSLFaG5il6xQAIfkEBQoAAgAsAAAAAAoACgAAAg+UYRLJ7QnQm7SmsCyVKhUAIfkEBQoAAgAsAAAAAAoACgAAAhCUYBLJDdiinNSEVfOEKoECACH5BAUKAAIALAAAAAAKAAoAAAIRFISBdusPo3RBzYsjaMIaUQAAOw==') 1 repeat; + } +} + +@media only screen and (max-width: 800px) { + .jcrop.jcrop_edition .jcrop-area { + background: none; + width: 100% !important; + height: 100% !important; + top: 0 !important; + left: 0 !important; + z-index: -1 !important; + } +} + + +.jfloating { + position:fixed; + bottom:0px; + right:0px; + margin-right:5px; + + -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; + box-sizing: border-box; + padding-top:50px !important; + z-index:9002; + border-radius: 8px; +} + +.jfloating.jfloating-big { + width: 510px !important; + height: 472px !important; +} + +.jfloating.jfloating-small { + width: 300px !important; + height: 320px !important; +} + +.jfloating.jfloating-large { + width: 600px !important; + height: 600px !important; +} + +.jfloating:before { + position:absolute; + top:0; + left:0; + width:100%; + content:attr(title); + padding:15px; + box-sizing: border-box; + font-size:1.2em; + box-shadow: 1px 1px 3px rgba(0,0,0,.2); + background-color: #fff; + border-radius: 8px 8px 0px 0px; + background-color: #404040; + font-size: .93rem; + font-weight: 600; + color: white; + letter-spacing: .5px; +} + +.jfloating:after { + content:''; + 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='%23FFF' 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; +} + +.jfloating_content { + padding:20px; + overflow-y:auto; + max-height:100%; + box-sizing: border-box; + height: -webkit-fill-available; +} + +.jfloating.jfloating-minimized { + height: 50px !important; +} + +.jfloating.jfloating-minimized .jfloating_content { + display: none; +} + + +@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; + margin-right: 0px !important; + } + .section { + margin-right:0px !important; + } + .section-content { + padding: 12px !important; + } +} + +/* mobile */ +@media (max-device-width: 600px) { + .small-screen-only { + display: block; + } + .medium-screen-only { + display: none; + } + .big-screen-only { + display: none; + } +} + +/* tablet */ +@media (max-device-width:992px) and (min-device-width:601px) { + .small-screen-only { + display: none; + } + .medium-screen-only { + display: block; + } + .big-screen-only { + display: none; + } +} + +/* desktop */ +@media (min-device-width: 993px) { + .small-screen-only { + display: none; + } + .medium-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; + line-height: initial; +} + +.jdropdown .jdropdown-header { + padding-top: 8px; + padding-bottom: 8px; +} + +.input[data-mask] { + white-space: nowrap; + overflow: hidden; +} + +.input[data-mask] * { + display: none; +} + +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; +} + +.nowrap { + flex-wrap:nowrap; +} + +.center { + text-align:center; +} + +.justify { + text-align:justify; +} + +.separator { + background-color:#eee; + height:1px; +} + +.clear { + clear:both; +} + +.top { + padding-left:2px; + padding-right:2px; +} + +.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; + box-sizing: border-box; +} + +.row.container { + flex-wrap: nowrap; +} + +.row.middle { + -ms-flex-align: center; + -webkit-align-items: center; + -webkit-box-align: center; + align-items: center; +} + +.column { + box-sizing: border-box; +} + +.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; +} + +@media only screen and (max-width: 480px) { + .column { + min-width: 100%; + } + .cmr1 { + margin-right: 0px; + } + .cmr2 { + margin-right: 0px; + } + .cml1 { + margin-left: 0px; + } + .cml2 { + margin-left: 0px; + } +} + +.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; + margin-right: 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; +} + +.cmr1 { + margin-right: 10px; +} + +.cmr2 { + margin-right: 20px; +} + +.cml1 { + margin-left: 10px; +} + +.cml2 { + margin-left: 20px; +} + +.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; +} + +.breadcrumb { + display: inline-flex; + list-style: none; + margin: 0px; + padding: 0px; +} + +.breadcrumb > li:after { + content: '\00BB'; + padding: 8px; + font-size: 1.2em; +} + +.breadcrumb > li:last-child:after { + opacity: 0; +} + +.breadcrumb a:hover { + color: #000; + text-decoration: underline; +} + +.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 { + outline: 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; +} + +.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; +} + +.disabled { + pointer-events: none; + opacity: 0.5; +} + +::-webkit-input-placeholder { + color: #ccc; +} + +:-moz-placeholder { + color: #ccc; +} + +::-moz-placeholder { + color: #ccc; +} + +:-ms-input-placeholder { + color: #ccc; +} + + +.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%; } +} + +.jmenu .close { + position: absolute; + top: 20px; + right: 20px; +} + +.jmenu nav { + font-family: Roboto; + position: relative; + margin-left: 5px; + margin-bottom: 25px; +} + +.jmenu nav[data-icon] { + padding-left: 28px; +} + +.jmenu nav[data-icon]:before { + position: absolute; + margin-top: -2px; + top: 0px; + left: 0px; + content: attr(data-icon); + width: 24px; + height: 24px; + font-size: 24px; + line-height: 24px; + font-family: 'Material icons'; +} + +.jmenu nav h2 { + text-transform: uppercase; + cursor: pointer; + display: flex; + align-items: center; + font-weight: bold; + font-size: 0.9em; +} + +.jmenu nav h2::before { + margin-left: -18px; + position: absolute; + width: 18px; + height: 18px; + content: ''; + background-repeat: no-repeat; + 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='M10 17l5-5-5-5v10z'/%3E%3Cpath d='M0 24V0h24v24H0z' fill='none'/%3E%3C/svg%3E"); + transition: transform .25s ease-in-out; +} + +.jmenu nav[data-icon] h2::before { + margin-left: -44px; +} + +.jmenu nav.selected h2::before { + transform: rotate(90deg); + -ms-transform: rotate(90deg); + -webkit-transform: rotate(90deg); +} + +.jmenu nav div { + font-family: Roboto; + padding: 2px; + padding-bottom: 10px; + display: none; +} + +.jmenu nav.selected div { + display: block; +} + +.jmenu nav h3 { + font-size: 1em; + font-weight: normal; + color: #999; + margin-left: 10px; +} + +.jmenu ul { + margin: 0px; + padding-left: 20px; + padding-bottom: 20px; +} + +.jmenu div ul:last-child { + padding-bottom: 0px; +} + +.jmenu li { + margin-bottom: 2px; + list-style: none; +} + +.jmenu i { + margin-left: 2px; + margin-right: 5px; +} + +.jmenu a { + color: #555; + text-decoration: none; +} + +.jmenu a:hover, .jmenu a.selected { + text-decoration: underline; + font-weight: bold; +} + +.jmenu .title { + border-bottom: 1px solid #ddd; + margin-bottom: 20px; + padding-bottom: 5px; +} + +@media only screen and (max-device-width : 800px) { + .jmenu { + height:100vh; + position: fixed; + top:0px; + left:0px; + background-color:#fff; + z-index:9000; + overflow: scroll; + padding-left: 20px; + box-shadow: 1px 1px 0px 0.1px #ccc !important; + -webkit-box-shadow: 1px 0px 1px 0.1px #ccc !important; + -moz-box-shadow: 1px 1px 0px 0.1px #ccc !important; + } + + .jmenu li { + margin-bottom: 10px; + } +} + +.jorg { + position: relative; + overflow: hidden; +} + +.jorg-hide-scrollbars { + overflow: hidden !important; +} + +.jorg.fullscreen-mode { + position: fixed; + top: 0 !important; + left: 0 !important; + width: 100vw !important; + height: 100vh !important; + background: #fff; +} + +.jorg-scrollParent { + overflow: auto; +} +.jorg > ul { + margin: 0; + width: 100%; + height: 100%; + padding: 0px; + position: relative; + overflow: auto; + display: block !important; +} + +.jorg-scrollParent { + overflow: auto; +} +.jorg > ul { + margin: 0; + width: 100%; + height: 100%; + position: relative; + overflow: auto; + padding: 40px; + display: block !important; +} + +.jorg > ul > li { + position: absolute; + left: 0; + min-width: 100%; + background: transparent; + min-height: 100%; +} + +.jorg-search { + position: absolute; + left: 25px; + top: 25px; +} + +.jorg-tf-tree { + font-size: 16px; +} + +.jorg-tf-tree ul { + box-sizing: border-box; +} + +.jorg-tf-tree ul { + display: inline-flex; +} + +.jorg-tf-tree li { + align-items: center; + display: flex; + flex-direction: column; + flex-wrap: wrap; + padding: 0 1em; + position: relative +} + +.jorg-tf-tree li ul { + margin: 2em 0; + margin-right: 40px; +} + +.jorg-tf-tree li li:before { + border-top: 3.5px solid #CCC; + content: ""; + display: block; + height: .0625em; + left: -.03125em; + position: absolute; + top: -1.03125em; + width: 100% +} + +.jorg-tf-tree li li:first-child:before { + left: calc(50% - .03125em); + max-width: calc(50% + .0625em) +} + +.jorg-tf-tree li li:last-child:before { + left: auto; + max-width: calc(50% + .0625em); + right: calc(50% - .03125em) +} + +.jorg-tf-tree li li:only-child:before { + display: none +} + +.jorg-tf-tree li li:only-child>.jorg-tf-nc:before, +.jorg-tf-tree li li:only-child>.tf-node-content:before { + height: 1.0625em; + top: -1.0625em +} + +.jorg-tf-tree .jorg-tf-nc, +.jorg-tf-tree .tf-node-content { + border: 3.5px solid #CCC; + display: inline-block; + padding: .5em 1em; + position: relative +} + +.jorg-tf-tree .jorg-tf-nc:before, +.jorg-tf-tree .tf-node-content:before { + top: -1.03125em +} + +.jorg-tf-tree .jorg-tf-nc:after, +.jorg-tf-tree .jorg-tf-nc:before, +.jorg-tf-tree .tf-node-content:after, +.jorg-tf-tree .tf-node-content:before { + border-left: 3.5px solid #CCC; + content: ""; + display: block; + height: 1em; + left: calc(50% - .03125em); + position: absolute; + width: .0625em +} + +.jorg-tf-tree .jorg-tf-nc:after, +.jorg-tf-tree .tf-node-content:after { + top: calc(100% + .04725em) +} + +.jorg-tf-tree .jorg-tf-nc:only-child:after, +.jorg-tf-tree .tf-node-content:only-child:after, +.jorg-tf-tree>ul>li>.jorg-tf-nc:before, +.jorg-tf-tree>ul>li>.tf-node-content:before { + display: none +} + +.jorg-tf-tree.tf-gap-sm li { + padding: 0 .6em +} + +.jorg-tf-tree.tf-gap-sm li>.jorg-tf-nc:before, +.jorg-tf-tree.tf-gap-sm li>.tf-node-content:before { + height: .6em; + top: -.6em +} + +.jorg-tf-tree.tf-gap-sm li>.jorg-tf-nc:after, +.jorg-tf-tree.tf-gap-sm li>.tf-node-content:after { + height: .6em +} + +.jorg-tf-tree.tf-gap-sm li ul { + margin: 1.2em 0 +} + +.jorg-tf-tree.tf-gap-sm li li:before { + top: -.63125em +} + +.jorg-tf-tree.tf-gap-sm li li:only-child>.jorg-tf-nc:before, +.jorg-tf-tree.tf-gap-sm li li:only-child>.tf-node-content:before { + height: .6625em; + top: -.6625em +} + +.jorg-tf-tree.tf-gap-lg li { + padding: 0 1.5em +} + +.jorg-tf-tree.tf-gap-lg li>.jorg-tf-nc:before, +.jorg-tf-tree.tf-gap-lg li>.tf-node-content:before { + height: 1.5em; + top: -1.5em +} + +.jorg-tf-tree.tf-gap-lg li>.jorg-tf-nc:after, +.jorg-tf-tree.tf-gap-lg li>.tf-node-content:after { + height: 1.5em +} + +.jorg-tf-tree.tf-gap-lg li ul { + margin: 3em 0 +} + +.jorg-tf-tree.tf-gap-lg li li:before { + top: -1.53125em +} + +.jorg-tf-tree.tf-gap-lg li li:only-child>.jorg-tf-nc:before, +.jorg-tf-tree.tf-gap-lg li li:only-child>.tf-node-content:before { + height: 1.5625em; + top: -1.5625em +} + +.jorg-tf-tree li.jorg-tf-dotted-children .jorg-tf-nc:after, +.jorg-tf-tree li.jorg-tf-dotted-children .jorg-tf-nc:before, +.jorg-tf-tree li.jorg-tf-dotted-children .tf-node-content:after, +.jorg-tf-tree li.jorg-tf-dotted-children .tf-node-content:before { + border-left-style: dotted +} + +.jorg-tf-tree li.jorg-tf-dotted-children li:before { + border-top-style: dotted +} + +.jorg-tf-tree li.jorg-tf-dotted-children>.jorg-tf-nc:before, +.jorg-tf-tree li.jorg-tf-dotted-children>.tf-node-content:before { + border-left-style: solid +} + +.jorg-tf-tree li.jorg-tf-dashed-children .jorg-tf-nc:after, +.jorg-tf-tree li.jorg-tf-dashed-children .jorg-tf-nc:before, +.jorg-tf-tree li.jorg-tf-dashed-children .tf-node-content:after, +.jorg-tf-tree li.jorg-tf-dashed-children .tf-node-content:before { + border-left-style: dashed +} + +.jorg-tf-tree li.jorg-tf-dashed-children li:before { + border-top-style: dashed +} + +.jorg-tf-tree li.jorg-tf-dashed-children>.jorg-tf-nc:before, +.jorg-tf-tree li.jorg-tf-dashed-children>.tf-node-content:before { + border-left-style: solid +} + +/* ORGANOGRAM STYLES */ + +.jorg-unselectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.jorg-tf-tree ul.jorg-vertical { + margin: 2em 0px !important; + display: flex; + flex-direction: column; + padding: 0px; + padding-left: 4em !important; + position: relative; +} + +.jorg-tf-tree ul.jorg-vertical li:before { + content: none; +} + +.jorg-tf-tree ul.jorg-vertical li { + margin-bottom: 40px; +} + +.jorg-tf-tree ul.jorg-vertical span.jorg-tf-nc:before { + content: none; +} + +.jorg-tf-tree span.jorg-after-none:after { + content: none; +} + +.jorg-tf-tree ul.jorg-vertical:before { + content: ''; + position: absolute; + width: 3px; + height: calc(100% - 2.75em); + top: -2em; + left: 3em; + background:#CCC; +} + +.jorg-tf-tree ul.jorg-vertical li span.jorg-tf-nc:before { + content: ''; + position: absolute; + width: 26px; + left: -30px; + top: calc(50% + 2px); + height: 3px; + background: #CCC; +} + +.jorg-disable-scrollbars::-webkit-scrollbar { + width: 0px; + background: transparent; /* Chrome/Safari/Webkit */ +} + +.jorg-disable-scrollbars { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE 10+ */ +} + +.jorg-tf-nc { + width: 180px; + background: var(--white); + height: 80px; + word-break: break-word; + color: rgba(0,0,0,.7); + border: 1px solid rgb(228, 228, 228) !important; + display: flex !important; + flex-direction: column; + padding: 0 !important; +} + +.jorg-user-status { + width: 100%; + height: 4px; + background: lightgreen; +} + +.jorg-user-info { + width: 100%; + height: calc(100% - 4px); + display: flex; + flex-direction: row; +} + +.jorg-user-content { + font-family: Roboto,Arial,Tahoma,Verdana,sans-serif; + text-align: left; + width: 108px; + height: 100%; + display: flex; + justify-content: center; + align-items: flex-start; + flex-direction: column; + overflow: hidden; +} + +.jorg-user-content span:nth-child(1) { + color: rgba(0,0,0,.38); + font-weight: 500; + line-height: 18px; + text-transform: uppercase; +} +.jorg-user-content, .jorg-user-img { + font-size: 14px; +} + +.jorg-user-img { + width: 72px; + height: 100%; + display: flex; + justify-content: center; + align-items: center; +} +.jorg-user-img img { + width: 50px; + height: 50px; + background: var(--white); + border-radius: 50%; +} + +.jorg-node-icon { + width: 18px; + height: 18px; + border-radius: 50%; + position: absolute; + bottom: -9px; + left: 0; + right: 0; + opacity: 0; + margin-left: auto; + margin-right: auto; + z-index: 1000; + transition: .2s opacity ease-in; + cursor: pointer; + font-weight: bold; + font-size: 1rem; +} + +.jorg-node-icon.remove { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23607D8B' width='18px' height='18px'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z'/%3E%3C/svg%3E"); + background-size: 100% 100%; +} + +.jorg-node-icon.plus { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24' viewBox='0 0 24 24' fill='%23607D8B' width='24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z'/%3E%3C/svg%3E"); + background-size: 100% 100%; +} + +.jorg-tf-nc:hover .jorg-node-icon { + opacity: 1; +} + +.jorg-search-animation { + animation: jorg-searching-hide .3s forwards; +} + +.jorg-search-animation.visible { + animation: jorg-searching-visible .3s forwards; +} + +@keyframes jorg-searching-hide { + 0% { + opacity: 1; + } + 100% { + opacity: 0; + } +} + +@keyframes jorg-searching-visible { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +.jorg-tf-nc[visibility='hidden']::after { + display: none; +} + +.jorg-zoom-container { + position: absolute; + right: 25px; + top: 25px; + background: transparent; + margin-left: 25px; + display: flex; + justify-content: space-between; +} + +.jorg-action { + font-size: 30px; + line-height: 30px; + width: 30px; + height: 30px; + cursor: pointer; +} + + +@media only screen and (max-width : 800px) { + .jorg { + width: 100vw !important; + } + + .jorg > ul { + width: 95% !important; + } +} + +.jtemplate-pagination { + display:flex; + cursor:pointer; + margin-top:10px; + margin-bottom:10px; +} + +.jtemplate-pagination { + display: flex; + margin-bottom: 15px; +} + +.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-empty:empty { + display:none; +} + +.jtemplate-results { + margin-top:15px; + margin-bottom:15px; +} + + +.jtimeline { + overflow: hidden; + min-height:calc(100vh - 90px); + min-width: 300px; +} + +.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; + padding-right:12px; + padding-left:12px; + margin-left:4px; + text-align: center; + cursor: pointer; +} + +.jtimeline-navigation i { + font-size: 1.5rem !important; + line-height:32px; + display:inline-block; +} + +.jtimeline-container { + position: relative; + 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; + max-width:calc(100% - 30px); +} + +.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; +} + +.jtimeline-action { + cursor: pointer; +} + +@media only screen and (min-width: 992px) { + .jtimeline-header { + position: relative !important; + } + + .jtimeline-container { + padding: 0px !important; + } +} + + diff --git a/web/_static/jsuites/jsuites.layout.js b/web/_static/jsuites/jsuites.layout.js new file mode 100644 index 0000000..65b64b7 --- /dev/null +++ b/web/_static/jsuites/jsuites.layout.js @@ -0,0 +1,3456 @@ +jSuites.crop = (function(el, options) { + // Already created, update options + if (el.crop) { + return el.crop.setOptions(options, true); + } + + // New instance + var obj = {}; + obj.options = {}; + + el.classList.add('jcrop'); + // Upload icon + el.classList.add('jupload'); + + // Area do crop + var crop = document.createElement('div'); + crop.classList.add('jcrop-area'); + el.appendChild(crop); + + // Canvas editor + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + el.appendChild(canvas); + + // Image + var drawImage = function() { + if (el.clientHeight > obj.image.height) { + var pointY = (el.clientHeight - obj.image.height) / 2; + } else { + var pointY = 0; + } + + if (el.clientWidth > obj.image.width) { + var pointX = (el.clientWidth - obj.image.width) / 2; + } else { + var pointX = 0; + } + + obj.image.left = pointX; + obj.image.top = pointY; + + context.translate(pointX, pointY); + context.drawImage(obj.image, 0, 0, obj.image.width, obj.image.height); + } + + obj.image = new Image(); + obj.image.onload = function onload() { + obj.resetCanvas(); + + var w = obj.options.area[0] / this.naturalWidth; + var h = obj.options.area[1] / this.naturalHeight; + + // Proportion + var p = Math.min(h, w); + + // Image size + this.width = this.naturalWidth * p; + this.height = this.naturalHeight * p; + + drawImage(); + + // Edition model + el.classList.add('jcrop_edition'); + + // Reset selection on desktop only + if (jSuites.getWindowWidth() > 800) { + obj.resetCropSelection(); + } + + // Onchange + if (typeof(obj.options.onchange) == 'function') { + obj.options.onchange(el, obj.image); + } + }; + + // Properties + var properties = { + zoom: { + origin: { x: null, y: null, }, + scale: 1, + fingerDistance: 0 + }, + contrast: 0, + brightness: 0, + rotate: 0, + saturation: 0, + }; + + var secondCanvas = document.createElement('canvas'); + var secondContext = secondCanvas.getContext('2d'); + var secondImage = document.createElement('img'); + + // Reload filters + var refreshFilters = function() { + secondCanvas.width = obj.image.width; + secondCanvas.height = obj.image.height; + + secondContext.clearRect(0, 0, secondContext.width, secondContext.height); + + secondImage.width = secondCanvas.width; + secondImage.height = secondCanvas.height; + + if (obj.image) { + //drawImage(); + secondContext.drawImage(obj.image, 0, 0, obj.image.width, obj.image.height); + } + + // Performs the contrast, if its value is different from the initial + if (properties.contrast) { + runContrast(); + } + + // Performs the brightness, if its value is different from the initial + if (properties.brightness) { + runBrightness(); + } + + if (properties.greyScale) { + runGreyScale(); + } + + if (properties.saturation) { + runSaturation(); + } + + secondImage.src = secondCanvas.toDataURL(obj.getImageType); + secondImage.onload = function() { + context.drawImage(secondImage, 0, 0, secondImage.width, secondImage.height); + } + } + + /** + * Set options + */ + obj.setOptions = function(options, reset) { + // Default configuration + var defaults = { + area: [ 800, 600 ], + crop: [ 200, 150 ], + value: null, + onload: null, + onchange: null, + remoteParser: null, + allowResize: true, + text: { + extensionNotAllowed: 'The extension is not allowed', + }, + eventListeners: {} + }; + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Default for mobile + if (jSuites.getWindowWidth() < 800) { + if (! obj.options.area[0]) { + obj.options.area[0] = window.clientWidth * 2; + } + if (! obj.options.area[1]) { + obj.options.area[1] = window.clientHeight * 2; + } + } + + // Set options + el.style.width = obj.options.area[0] + 'px'; + el.style.height = obj.options.area[1] + 'px'; + + canvas.width = obj.options.area[0]; + canvas.height = obj.options.area[1]; + + // Reset all + obj.reset(); + + // Initial image + if (typeof obj.options.value === 'string') { + obj.image.src = obj.options.value; + } + + return obj; + } + + /** + * Reset crop to the initial conditions + */ + obj.resetCropSelection = function() { + crop.style.left = (obj.options.area[0]/2 - obj.options.crop[0]/2) + 'px'; + crop.style.top = (obj.options.area[1]/2 - obj.options.crop[1]/2) + 'px'; + crop.style.width = obj.options.crop[0] + 'px'; + crop.style.height = obj.options.crop[1] + 'px'; + crop.style.zIndex = 1; + } + + obj.getCropSelection = function() { + obj.getSelectionCoordinates(); + } + + // Reset canvas + obj.resetCanvas = function() { + context.setTransform(1, 0, 0, 1, 0, 0); + context.clearRect(0,0,canvas.width,canvas.height); + } + + // Reset all the properties + obj.reset = function() { + // Reset crop selection + obj.resetCropSelection() + // Reset canvas + obj.resetCanvas(); + // Reset state + properties = { + zoom: { + origin: { x: null, y: null }, + scale: 1, + }, + contrast: 0, + brightness: 0, + rotate: 0, + greyScale: 0, + saturation: 0, + } + // Reset file input + attachmentInput.value = ''; + // Stop edition + el.classList.remove('jcrop_edition') + } + + var callListeningFunction = function(type) { + if (typeof obj.options.eventListeners[type] === 'function') { + var types = { + zoom: properties.zoom.scale, + rotate: properties.rotate, + brightness: properties.brightness, + contrast: properties.contrast, + }; + + obj.options.eventListeners[type](types[type]); + } + } + + // Apply the contrast on the image data + var runContrast = function() { + var contrast = properties.contrast; + var imageData = secondContext.getImageData(0, 0, secondCanvas.width, secondCanvas.height); + var data = imageData.data; // Note: original dataset modified directly! + contrast *= 255; + var factor = (contrast + 255) / (255.01 - contrast); //add .1 to avoid /0 error. + + for (var i = 0; i < data.length; i+=4) { + data[i] = factor * (data[i] - 128) + 128; + data[i+1] = factor * (data[i+1] - 128) + 128; + data[i+2] = factor * (data[i+2] - 128) + 128; + } + + secondContext.putImageData(imageData, 0, 0); + + return imageData; //optional (e.g. for filter function chaining) + } + + // Change the contrast and apply that to the image + obj.contrast = function(val) { // contrast input as percent; range [-1..1] + if (! Number.isNaN(parseFloat(val))) { + properties.contrast = val; + } + + callListeningFunction('contrast'); + + refreshFilters(); + } + + // Apply the brightness on the image data + var runBrightness = function () { // brightness input as percent; range [-1..1] + var brightness = properties.brightness; + var imageData = secondContext.getImageData(0, 0, secondCanvas.width, secondCanvas.height); + + var data = imageData.data; // Note: original dataset modified directly! + brightness *= 255; + + for (var i = 0; i < data.length; i+=4) { + data[i] += brightness; + data[i+1] += brightness; + data[i+2] += brightness; + } + + secondContext.putImageData(imageData, 0, 0); + + return imageData; //optional (e.g. for filter function chaining) + } + + // Change the brightness and apply that to the image + obj.brightness = function(val) { + if (! Number.isNaN(parseFloat(val))) { + properties.brightness = val; + } + + callListeningFunction('brightness'); + + refreshFilters(); + } + + /** + * Returns the current image type + */ + obj.getImageType = function() { + var dataType = obj.image.src.substr(0,20); + if (dataType.includes('data')){ + return dataType.split('/')[1].split(';')[0]; + } + return null; + } + /** + * Returns cropped area coordinates + */ + obj.getSelectionCoordinates = function() { + return { + left: crop.offsetLeft, + top: crop.offsetTop, + right: crop.offsetLeft + crop.clientWidth, + bottom: crop.offsetTop + crop.clientHeight + } + } + + /** + * Returns cropped image on canvas + */ + obj.getCroppedImage = function() { + return jSuites.image.create({ + extension: obj.getImageType(), + file: obj.getCroppedContent(), + name: '', + size: '', + }); + } + + /** + * Get cropped base64 content + */ + obj.getCroppedContent = function() { + var coordinates = obj.getSelectionCoordinates(); + var canvasCropped = document.createElement('canvas'); + var contextCropped = canvasCropped.getContext('2d'); + canvasCropped.width = crop.clientWidth; + canvasCropped.height = crop.clientHeight; + + // Get cropped selection + var imageData = context.getImageData(coordinates.left, coordinates.top, crop.clientWidth, crop.clientHeight); + contextCropped.putImageData(imageData,0,0); + return canvasCropped.toDataURL(obj.getImageType()); + } + + /** + * Get cropped as blob + */ + obj.getCroppedAsBlob = function(callback) { + if (! typeof(callback) == 'function') { + console.error('Callback not defined') + return false; + } + + var coordinates = obj.getSelectionCoordinates(); + var canvasCropped = document.createElement('canvas'); + var contextCropped = canvasCropped.getContext('2d'); + canvasCropped.width = crop.clientWidth; + canvasCropped.height = crop.clientHeight; + + // Get cropped selection + var imageData = context.getImageData(coordinates.left, coordinates.top, crop.clientWidth, crop.clientHeight); + contextCropped.putImageData(imageData,0,0); + + // Callback + canvasCropped.toBlob(callback); + } + + /** + * Returns the current image on canvas + */ + obj.getImage = function() { + return obj.image; + } + + /** + * Returns the attachment input + */ + obj.getFileInput = function() { + return attachmentInput; + } + + /** + * Returns the current canvas + */ + obj.getCanvas = function() { + return canvas; + } + + /** + * Load a image from the computer + */ + obj.addFromFile = function(file) { + var type = file.type.split('/'); + if (type[0] == 'image') { + var imageFile = new FileReader(); + imageFile.addEventListener("load", function (v) { + obj.image.src = v.target.result; + }); + imageFile.readAsDataURL(file); + } else { + alert(obj.options.text.extensionNotAllowed); + } + } + + /** + * Load a image from a remote URL + */ + obj.addFromUrl = function(src) { + if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) { + console.error('remoteParser not defined in your initialization'); + } else { + src = obj.options.remoteParser + src; + obj.image.src = src; + } + } + + // X-axis spacing of the zoom at the last scroll change + var zoomOffsetX; + + // Y-axis spacing of the zoom at the last scroll change + var zoomOffsetY; + + // Mouse position on the x-axis in the last use of the scroll + var lastX; + + // Mouse position on the y-axis in the last use of the scroll + var lastY; + + // Last zoom applied + var lastScale; + + // Runs image movements + var runMove = function() { + // If the mouse was moved after the last scroll, it moves the image in relation to the x-axis + if (lastX && lastX !== properties.zoom.origin.x) { + var temp = Math.abs(properties.zoom.origin.x - zoomOffsetX - obj.image.left); + temp /= lastScale; + temp -= properties.zoom.origin.x - obj.image.left; + + obj.image.left -= temp; + } + + // If the mouse was moved after the last scroll, it moves the image in relation to the y-axis + if (lastY && lastY !== properties.zoom.origin.y) { + var temp = Math.abs(properties.zoom.origin.y - zoomOffsetY - obj.image.top); + temp /= lastScale; + temp -= properties.zoom.origin.y - obj.image.top; + + obj.image.top -= temp; + } + + // Update variables + zoomOffsetX = (properties.zoom.origin.x - obj.image.left) - (properties.zoom.origin.x - obj.image.left) * properties.zoom.scale; + zoomOffsetY = (properties.zoom.origin.y - obj.image.top) - (properties.zoom.origin.y - obj.image.top) * properties.zoom.scale; + lastX = properties.zoom.origin.x; + lastY = properties.zoom.origin.y; + lastScale = properties.zoom.scale; + + // Move image + context.translate(obj.image.left + zoomOffsetX, obj.image.top + zoomOffsetY); + } + + // Reload resizers and filters + var refreshResizers = function() { + // Clear canvas + context.setTransform(1, 0, 0, 1, 0, 0); + context.clearRect(0, 0, canvas.width, canvas.height); + + runMove(); + + // Performs the zoom, if its value is different from the initial + if (properties.zoom.scale !== 1) { + runZoom(); + } + + // Performs the rotation, if its value is different from the initial + if (properties.rotate) { + runRotate(); + } + + // Calls the filter reloader + if (properties.brightness || properties.contrast) { + context.drawImage(secondImage, 0, 0, secondImage.width, secondImage.height); + } else { + context.drawImage(obj.image, 0, 0, obj.image.width, obj.image.height); + } + } + + // Apply the zoom on the image + var runZoom = function() { + context.scale(properties.zoom.scale, properties.zoom.scale); + } + + /** + * Change the zoom and apply that to the image + * @param mixed value / null to refresh or int for a new percentage of zoom + */ + obj.zoom = function(value) { + if (value) { + properties.zoom.scale = value; + } + + callListeningFunction('zoom'); + + refreshResizers(); + } + + // Apply the rotations on the image + var runRotate = function() { + var value = properties.rotate; + value *= 180; + + context.translate(obj.image.width / 2, obj.image.height / 2); + context.rotate(value * Math.PI / 180); + context.translate(- obj.image.width / 2, - obj.image.height / 2); + } + + // Change the rotation and apply that to the image + obj.rotate = function(val) { // rotate input as percent; range [-1..1] + if (! Number.isNaN(parseFloat(val))) { + properties.rotate = val; + } + + callListeningFunction('rotate'); + + refreshResizers(); + } + + // HTML element to load a image from the computer + 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]); + } + } + + /** Events start here **/ + var editorAction = null; + var scaling = null; + + var editorMouseUp = function(e) { + editorAction = false; + } + + var editorMouseDown = function(e) { + if (e.target.classList.contains('jcrop-area')) { + var rect = e.target.getBoundingClientRect(); + + var offsetX = (e.target.style.left !== '') ? e.target.style.left : '0px'; + var offsetY = (e.target.style.top !== '') ? e.target.style.top : '0px'; + + if (e.target.style.cursor) { + editorAction = { + e: e.target, + x: e.clientX, + y: e.clientY, + w: rect.width, + h: rect.height, + d: e.target.style.cursor, + xOffset: e.clientX - parseInt(offsetX.slice(0, offsetX.length - 2)), + yOffset: e.clientY - parseInt(offsetY.slice(0, offsetY.length - 2)), + } + + 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; + } + } + + var editorMouseMove = function(e) { + e = e || window.event; + if (typeof(e.buttons) !== undefined) { + var mouseButton = e.buttons; + } else if (typeof(e.button) !== undefined) { + var mouseButton = e.button; + } else { + var mouseButton = e.which; + } + + if (! e.buttons) { + if (e.target.classList.contains('jcrop-area')) { + var rect = e.target.getBoundingClientRect(); + if (obj.options.allowResize == true) { + 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'; + } + } else { + e.target.style.cursor = 'move'; + } + } + } + + if (mouseButton == 1 && editorAction && editorAction.d) { + // Change position or size + if (editorAction.d == 'move') { + // Change the position of the cropper + var cropOffsetX = e.clientX - editorAction.xOffset; + var cropOffsetY = e.clientY - editorAction.yOffset; + + if (cropOffsetX < 0) { + editorAction.e.style.left = '0px'; + } else if (cropOffsetX > el.offsetWidth - crop.offsetWidth - 2) { + editorAction.e.style.left = el.offsetWidth - crop.offsetWidth - 2 + 'px'; + } else { + editorAction.e.style.left = cropOffsetX + 'px'; + } + + if (cropOffsetY < 0) { + editorAction.e.style.top = '0px'; + } else if (cropOffsetY > el.offsetHeight - crop.offsetHeight - 2){ + editorAction.e.style.top = el.offsetHeight - crop.offsetHeight - 2 + 'px'; + } else { + editorAction.e.style.top = cropOffsetY + 'px'; + } + } else { + // Change the size of the cropper + if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') { + // Handles size changes involving the right side of the cropper + var newWidth = editorAction.w + e.clientX - editorAction.x; + var offset = editorAction.e.style.left.slice(0, editorAction.e.style.left.length - 2); + + if (newWidth < obj.options.crop[0]) { + editorAction.e.style.width = obj.options.crop[0] + 'px'; + } else if (newWidth + parseInt(offset) > el.offsetWidth - 2) { + editorAction.e.style.width = el.offsetWidth - offset - 2 + 'px'; + } else { + editorAction.e.style.width = editorAction.w + e.clientX - editorAction.x + 'px'; + } + } else if (editorAction.d == 'w-resize' || editorAction.d == 'nw-resize' || editorAction.d == 'sw-resize') { + // Handles size changes involving the left side of the cropper + var newOffset = e.clientX - editorAction.xOffset; + var newWidth = editorAction.x + editorAction.w - e.clientX; + + if (newWidth < obj.options.crop[0]) { + editorAction.e.style.left = editorAction.x + editorAction.w - obj.options.crop[0] - editorAction.xOffset + 'px'; + editorAction.e.style.width = obj.options.crop[0] + 'px'; + } else if (newOffset < 0) { + editorAction.e.style.left = '0px'; + editorAction.e.style.width = editorAction.x + editorAction.w - editorAction.xOffset + 'px'; + } else { + editorAction.e.style.left = newOffset + 'px'; + editorAction.e.style.width = newWidth + 'px'; + } + } + + if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') { + // Handles size changes involving the top side of the cropper + var newHeight = editorAction.h + e.clientY - editorAction.y; + var offset = editorAction.e.style.top.slice(0, editorAction.e.style.top.length - 2); + + if (newHeight < obj.options.crop[1]) { + editorAction.e.style.height = obj.options.crop[1] + 'px'; + } else if (newHeight + parseInt(offset) > el.offsetHeight - 2) { + editorAction.e.style.height = el.offsetHeight - parseInt(offset) - 2 + 'px'; + } else { + editorAction.e.style.height = newHeight + 'px'; + } + } else if (editorAction.d == 'n-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'nw-resize') { + // Handles size changes involving the bottom side of the cropper + var newOffset = e.clientY - editorAction.yOffset; + var newHeight = editorAction.h + editorAction.y - e.clientY; + + if (newHeight < obj.options.crop[1]) { + editorAction.e.style.top = editorAction.y + editorAction.h - obj.options.crop[1] - editorAction.yOffset + 'px'; + editorAction.e.style.height = obj.options.crop[1] + 'px'; + } else if (newOffset < 0) { + editorAction.e.style.top = '0px'; + editorAction.e.style.height = editorAction.y + editorAction.h - editorAction.yOffset + 'px'; + } else { + editorAction.e.style.top = newOffset + 'px'; + editorAction.e.style.height = newHeight + 'px'; + } + } + } + } + } + + // image state to change its current position in el container (mobile only) + var imageState = { + mousedown: false, + mouseX: 0, + mouseY: 0 + } + + var touchstartListener = function(e) { + if (! e.target.classList.contains('jcrop-area')) { + imageState.mousedown = true; + } + + if (e.changedTouches && e.changedTouches[0]) { + imageState.mouseX = e.changedTouches[0].clientX; + imageState.mouseY = e.changedTouches[0].clientY; + } else { + imageState.mouseX = e.clientX; + imageState.mouseY = e.clientY; + } + + if (e.touches) { + if(e.touches.length == 2) { + imageState.mousedown = false; + scaling = true; + pinchStart(e); + } + } + } + var touchEndListener = function(e) { + if (scaling) { + scaling = false; + } + } + + var imageMoveListener = function(e) { + if (el.classList.contains('jcrop_edition') && ! scaling) { + // Mark position + 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; + } + + var currentX = x; + var newX = currentX - imageState.mouseX; + imageState.mouseX = currentX; + + var currentY = y; + var newY = currentY - imageState.mouseY; + imageState.mouseY = currentY; + + if (imageState.mousedown) { + obj.image.left += newX/properties.zoom.scale; + obj.image.top += newY/properties.zoom.scale; + refreshResizers(); + } + + e.preventDefault(); + } + + if(scaling) { + pinchMove(e); + } + } + + document.addEventListener('mouseup', function(e) { + imageState.mousedown = false; + }); + + el.addEventListener('mouseup', editorMouseUp); + el.addEventListener('mousedown', editorMouseDown); + el.addEventListener('mousemove', editorMouseMove); + el.addEventListener('touchstart',touchstartListener); + + el.addEventListener('touchend', touchEndListener); + el.addEventListener('touchmove', imageMoveListener); + el.addEventListener('mousedown',touchstartListener); + el.addEventListener('mousemove', imageMoveListener); + + el.addEventListener("dblclick", 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) { + // Create temp element + var div = document.createElement('div'); + div.innerHTML = html; + + // Extract images + var img = div.querySelector('img'); + + if (img) { + obj.addFromUrl(img.src); + } + } + + el.style.border = '1px solid #eee'; + + return false; + }); + + el.addEventListener("wheel", function(e) { + if (el.classList.contains('jcrop_edition')) { + // Update scale + if (e.deltaY > 0) { + if (properties.zoom.scale > 0.1) { + properties.zoom.scale *= 0.97; + } + } else { + if (properties.zoom.scale < 5) { + properties.zoom.scale *= 1.03; + } + } + properties.zoom.scale = parseFloat(properties.zoom.scale.toFixed(2)); + + // Update coordinates + var rect = el.getBoundingClientRect(); + var x = e.clientX - rect.left; + var y = e.clientY - rect.top; + + // Zoom on the image + var c = context.getImageData(x, y, 1, 1).data; + if (c[3] != 0) { + properties.zoom.origin.x = x; + properties.zoom.origin.y = y; + } else { + } + + // Apply zoom + obj.zoom(); + + e.preventDefault(); + } + }); + + // mobile events + el.addEventListener("click", function(e) { + if (! el.classList.contains('jcrop_edition')) { + jSuites.click(attachmentInput); + } + }); + + // Initial options + obj.setOptions(options); + + // Onchange + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj); + } + + // Mobile pinch zoom + var pinchStart = function(e) { + var rect = el.getBoundingClientRect(); + properties.zoom.fingerDistance = Math.hypot( + e.touches[0].pageX - e.touches[1].pageX, + e.touches[0].pageY - e.touches[1].pageY); + + properties.zoom.origin.x = ((e.touches[0].pageX - rect.left) + (e.touches[1].pageX - rect.left))/2; + properties.zoom.origin.y = ((e.touches[0].pageY - rect.top) + (e.touches[1].pageY - rect.top))/2; + } + + var pinchMove = function(e) { + e.preventDefault(); + + var dist2 = Math.hypot(e.touches[0].pageX - e.touches[1].pageX,e.touches[0].pageY - e.touches[1].pageY); + + if (dist2 > properties.zoom.fingerDistance) { + var dif = dist2 - properties.zoom.fingerDistance; + var newZoom = properties.zoom.scale + properties.zoom.scale * dif * 0.0025; + if (newZoom <= 5.09) { + obj.zoom(newZoom); + } + } + + if (dist2 < properties.zoom.fingerDistance) { + var dif = properties.zoom.fingerDistance - dist2; + var newZoom = properties.zoom.scale - properties.zoom.scale * dif * 0.0025; + if (newZoom >= 0.1) { + obj.zoom(newZoom); + } + } + properties.zoom.fingerDistance = dist2; + } + + el.crop = obj; + + return obj; +}); + +jSuites.floating = (function(el, options) { + var obj = {}; + obj.options = {}; + + // Default configuration + var defaults = { + type: 'big', + title: 'Untitled', + width: 510, + height: 472, + } + + // 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 methods + + var setContent = function() { + var temp = document.createElement('div'); + while (el.children[0]) { + temp.appendChild(el.children[0]); + } + + obj.content = document.createElement('div'); + obj.content.className = 'jfloating_content'; + obj.content.innerHTML = el.innerHTML; + + while (temp.children[0]) { + obj.content.appendChild(temp.children[0]); + } + + obj.container = document.createElement('div'); + obj.container.className = 'jfloating'; + obj.container.appendChild(obj.content); + + if (obj.options.title) { + obj.container.setAttribute('title', obj.options.title); + } else { + obj.container.classList.add('no-title'); + } + + // validate element dimensions + if (obj.options.width) { + obj.container.style.width = parseInt(obj.options.width) + 'px'; + } + + if (obj.options.height) { + obj.container.style.height = parseInt(obj.options.height) + 'px'; + } + + el.innerHTML = ''; + el.appendChild(obj.container); + } + + var setEvents = function() { + if (obj.container) { + obj.container.addEventListener('click', function(e) { + var rect = e.target.getBoundingClientRect(); + + if (e.target.classList.contains('jfloating')) { + 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() { + obj.close(); + }, 100); + } else { + obj.setState(); + } + } + }); + } + } + + var setType = function() { + obj.container.classList.add('jfloating-' + obj.options.type); + } + + obj.state = { + isMinized: false, + } + + obj.setState = function() { + if (obj.state.isMinized) { + obj.container.classList.remove('jfloating-minimized'); + } else { + obj.container.classList.add('jfloating-minimized'); + } + obj.state.isMinized = ! obj.state.isMinized; + } + + obj.close = function() { + jSuites.floating.elements.splice(jSuites.floating.elements.indexOf(obj.container), 1); + obj.updatePosition(); + el.remove(); + } + + obj.updatePosition = function() { + for (var i = 0; i < jSuites.floating.elements.length; i ++) { + var floating = jSuites.floating.elements[i]; + var prevFloating = jSuites.floating.elements[i - 1]; + floating.style.right = i * (prevFloating ? prevFloating.offsetWidth : floating.offsetWidth) * 1.01 + 'px'; + } + } + + obj.init = function() { + // Set content into root + setContent(); + + // Set dialog events + setEvents(); + + // Set dialog type + setType(); + + // Update floating position + jSuites.floating.elements.push(obj.container); + obj.updatePosition(); + + el.floating = obj; + } + + obj.init(); + + return obj; +}); + +jSuites.floating.elements = []; + +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]; + } + } + + // 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 = jSuites.translate('Please enter here the code received by email'); + 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 = jSuites.translate('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 = jSuites.translate('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 = jSuites.translate('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 = jSuites.translate('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 = jSuites.translate('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 = jSuites.translate('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 = jSuites.translate('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 = jSuites.translate('Please type here the code shown 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 = jSuites.translate('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 = jSuites.translate('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 = jSuites.translate('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.message) == 'function') { + obj.options.message(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 = jSuites.translate('Create a 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 = jSuites.translate('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 = jSuites.translate('Confirm the 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 = jSuites.translate('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 = jSuites.translate('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(jSuites.translate('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(jSuites.translate('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') { + if (! jSuites.validations.email(inputUsername.value)) { + var message = jSuites.translate('Invalid e-mail address'); + } + if (! jSuites.validations.login(inputLogin.value)) { + var message = jSuites.translate('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 = jSuites.translate('Password is too short'); + } else if (inputPassword.value != inputRepeatPassword.value) { + var message = jSuites.translate('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(jSuites.translate('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; + +jSuites.menu = (function(el, options) { + var obj = {}; + + obj.show = function() { + el.style.display = 'block'; + jSuites.animation.slideLeft(el, 1); + } + + obj.hide = function() { + jSuites.animation.slideLeft(el, 0, function() { + el.style.display = ''; + }); + } + + obj.load = function() { + if (localStorage) { + var menu = el.querySelectorAll('nav'); + var selected = null; + for (var i = 0; i < menu.length; i++) { + menu[i].classList.remove('selected'); + if (menu[i].getAttribute('data-id')) { + var state = localStorage.getItem('jmenu-' + menu[i].getAttribute('data-id')); + if (state == 1) { + menu[i].classList.add('selected'); + } + } + } + var href = window.location.pathname; + if (href) { + var menu = document.querySelector('.jmenu a[href="'+ href +'"]'); + if (menu) { + menu.classList.add('selected'); + } + } + } + } + + obj.select = function(o, e) { + if (o.tagName == 'NAV') { + var m = el.querySelectorAll('nav'); + for (var i = 0; i < m.length; i++) { + m[i].style.display = 'none'; + } + o.style.display = ''; + o.classList.add('selected'); + } else { + var m = el.querySelectorAll('nav a'); + for (var i = 0; i < m.length; i++) { + m[i].classList.remove('selected'); + } + o.classList.add('selected'); + + // Better navigation + if (options && options.collapse == true) { + if (o.classList.contains('show')) { + m = el.querySelectorAll('nav'); + for (var i = 0; i < m.length; i++) { + m[i].style.display = ''; + } + o.style.display = 'none'; + } else { + m = el.querySelectorAll('nav'); + for (var i = 0; i < m.length; i++) { + m[i].style.display = 'none'; + } + + m = el.querySelector('.show'); + if (m) { + m.style.display = 'block'; + } + + m = jSuites.findElement(o.parentNode, 'selected'); + if (m) { + m.style.display = ''; + } + } + } + } + + if (options && typeof(options.onclick) == 'function') { + options.onclick(obj, e); + } + + // Close menu if is oped + if (jSuites.getWindowWidth() < 800) { + obj.hide(); + } + } + + var action = function(e) { + if (e.target.tagName == 'H2') { + if (e.target.parentNode.classList.contains('selected')) { + e.target.parentNode.classList.remove('selected'); + localStorage.setItem('jmenu-' + e.target.parentNode.getAttribute('data-id'), 0); + } else { + e.target.parentNode.classList.add('selected'); + localStorage.setItem('jmenu-' + e.target.parentNode.getAttribute('data-id'), 1); + } + } else if (e.target.tagName == 'A') { + // Mark link as selected + obj.select(e.target, e); + } + } + + if ('ontouchstart' in document.documentElement === true) { + el.addEventListener('touchsend', action); + } else { + el.addEventListener('mouseup', action); + } + + // Add close action + var i = document.createElement('i'); + i.className = 'material-icons small-screen-only close'; + i.innerText = 'close'; + i.onclick = function() { + obj.hide(); + } + el.appendChild(i); + + // Add menu class + el.classList.add('jmenu'); + + // Load state + obj.load(); + + if (options && typeof(options.onload) == 'function') { + options.onload(el); + } + + // Keep reference + el.menu = obj; + + return obj; +}); + + +jSuites.organogram = (function(el, options) { + if (el.organogram) { + return el.organogram.setOptions(options, true); + } + + var obj = {}; + obj.options = {}; + + // Defines the state to deal with mouse events + var state = { + x: 0, + y: 0, + initialWidth: 0, + initialTop: 100, + fingerDistance: 0, + mobileDown: false, + scaling: false, + scale: 1, + } + + var getRoleById = function(id) { + for (var i = 0; i < obj.options.roles.length; i++) { + if (id == obj.options.roles[i].id) { + return obj.options.roles[i]; + } + } + return false; + } + + var getContent = function(node) { + var role = node.role; + var color = node.color || 'lightgreen'; + if (obj.options.roles && node.role >= 0) { + var o = getRoleById(node.role); + if (o) { + role = o.name; + var color = o.color; + } + } + + return `
+ `; + } + + // Creates the shape of a node to be added to the organogram chart tree + var mountNodes = function(node, container) { + var li = document.createElement('li'); + var span = document.createElement('span'); + span.className = 'jorg-tf-nc'; + span.innerHTML = getContent(node); + span.setAttribute('id', node.id); + var ul = document.createElement('ul'); + li.appendChild(span); + li.appendChild(ul); + container.appendChild(li); + + return ul; + } + + // Return the render mode ( vertical or horizontal ) + var getRenderMode = function(container) { + if (container.parentNode == el) { + return 'horizontal'; + } + if (container.children.length > 1) { + for (var i = 0; i < container.children.length; i ++) { + if (Array.from(container.children[i].children).find(element => element.tagName == 'UL')) { + return 'horizontal'; + } + } + return 'vertical'; + } + return 'vertical'; + } + + // Node visibility feature + var setNodeVisibility = function(node) { + var className = "jorg-node-icon"; + var icon = document.createElement('div'); + var ulNode = node.nextElementSibling; + node.appendChild(icon); + + if (ulNode) { + icon.className = className + ' remove'; + } else { + icon.className = className + ' plus' + return ; + } + + icon.addEventListener('click', function(e) { + if (node.nextElementSibling.style.display == 'none') { + node.nextElementSibling.style.display = 'inline-flex'; + node.removeAttribute('visibility'); + e.target.className = className + ' remove'; + } else { + node.nextElementSibling.style.display = 'none'; + node.setAttribute('visibility','hidden'); + e.target.className = className + ' plus'; + } + ul.children[0].style.width = state.initialWidth + 'px'; + }); + } + + // Renders the organogram + var render = function (parent, container) { + for (var i = 0; i < obj.options.data.length; i ++) { + if (obj.options.data[i].parent == parent) { + var ul = mountNodes(obj.options.data[i], container); + render(obj.options.data[i].id, ul); + } + } + + // Check render mode / vertical / horizontal + var mode = getRenderMode(container); + + if (mode == 'vertical' && obj.options.vertical) { + container.previousElementSibling.classList.add('jorg-after-none'); + container.classList.add('jorg-vertical'); + } else { + container.classList.add('jorg-horizontal'); + } + + if (! container.childNodes.length) { + container.remove(); + } else if (container.previousElementSibling) { + setNodeVisibility(container.previousElementSibling); + } + } + + // Sets the full screen mode + var setFullScreenMode = function(e) { + var windowScrollTop = document.body.scrollTop || document.documentElement.scrollTop; + + if (el.classList.contains('fullscreen-mode')) { + el.classList.remove('fullscreen-mode'); + document.body.classList.remove('jorg-hide-scrollbars'); + el.style.top = '0px'; + e.target.innerText ='slideshow'; + } else { + el.classList.add('fullscreen-mode'); + document.body.classList.add('jorg-hide-scrollbars'); + el.style.top = windowScrollTop + 'px'; + e.target.innerText ='close_fullscreen'; + } + } + + // Deals with zoom in and zoom out in the organogram + var zoom = function(e) { + e = event || window.event; + // Current zoom + var currentZoom = state.scale = el.children[0].style.zoom * 1; + var prevWidth = el.children[0].offsetWidth; + var prevHeight = el.children[0].offsetHeight; + var widthVar, heightVar; + // Action + if (e.target.classList.contains('jorg-zoom-in') || e.deltaY < 0) { + el.children[0].style.zoom = currentZoom + obj.options.zoom; + widthVar = prevWidth - el.children[0].offsetWidth; + heightVar = prevHeight - el.children[0].offsetHeight; + el.children[0].scrollLeft += (widthVar/2) + el.children[0].scrollTop += (heightVar/2) + } else if (currentZoom > .5) { + el.children[0].style.zoom = state.scale = currentZoom - obj.options.zoom; + widthVar = el.children[0].offsetWidth - prevWidth; + heightVar = el.children[0].offsetHeight - prevHeight; + el.children[0].scrollLeft -= (widthVar/2); + el.children[0].scrollTop -= (heightVar/2); + } + e.preventDefault(); + } + + // Finds a node in the organogram chart by a node propertie + var findNode = function(o) { + if (o && typeof o == 'object') { + var keys = Object.keys(o); + for (var i = 0; i < keys.length; i ++) { + var property = keys[i]; + var node = obj.options.data.find(node => node[property] == o[property]); + if (node) { + return Array.prototype.slice.call(document.querySelectorAll('.jorg-tf-nc')).find(n => n.getAttribute('id') == node.id); + } else { + continue; + } + } + } + return 0; + } + + // + var setInitialPosition = function() { + if (ul && ul.children[0]) { + ul.children[0].style.left = (ul.clientWidth / 2 - ul.children[0].clientWidth / 2) + 'px'; + ul.children[0].style.top = '100px'; + } + } + + // + var setInitialWidth = function() { + if (ul.children[0]) { + state.initialWidth = ul.children[0].clientWidth; + } + } + + // + var animateOnSearch = function(newLeft, newTop) { + ul.classList.add('jorg-search-animation'); + ul.onanimationend = function(e) { + if (e.animationName == 'jorg-searching-hide') { + ul.children[0].style.left = newLeft + 'px'; + ul.children[0].style.top = newTop + 'px'; + ul.classList.remove('jorg-search-animation'); + ul.classList.add('jorg-searching-visible'); + }else if(e.animationName == 'jorg-searching-visible') { + ul.classList.remove('jorg-searching-visible'); + } + } + } + + /** + * Set the options + * @param {object} options + */ + obj.setOptions = function(options, reset) { + // Default configuration + var defaults = { + data: null, + url: null, + zoom: 0.1, + width: 800, + height: 600, + search: true, + searchPlaceHolder: 'Search', + vertical: false, + roles: null, + // Events + onload: null, + onchange: null, + onclick: null + }; + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else { + if (typeof(obj.options[property]) == 'undefined' || reset === true) { + obj.options[property] = defaults[property]; + } + } + } + + // Show search box + if (obj.options.search) { + el.appendChild(search); + } else { + if (search.parentElement) { + el.removeChild(search); + } + } + + // Make sure correct format + obj.options.width = parseInt(obj.options.width); + obj.options.height = parseInt(obj.options.height); + + // Update placeholder + search.placeholder = obj.options.searchPlaceHolder; + + // Set default dimensions + if (options.width || options.height) { + obj.setDimensions(obj.options.width, obj.options.height); + } + + // Only execute when is not the first time + if (el.organogram) { + obj.refresh(); + } + + return obj; + } + + /** + * Reset roles + */ + obj.setRoles = function(roles) { + if (roles) { + obj.options.roles = roles; + obj.refresh(); + } + } + + obj.setUrl = function(url) { + jSuites.ajax({ + url: url, + method: 'GET', + dataType: 'json', + success: function(result) { + obj.setData(result); + } + }); + } + + /** + * Refreshes the organozation chart + */ + obj.update = function() { + el.children[0].innerHTML = ''; + render(0,el.children[0]); + } + + /** + * applies a zoom in the organization chart + */ + obj.zoom = function(scale) { + if (scale < .5 ) { + scale = .5; + } + ul.style.zoom = state.scale = scale; + } + + /** + * Reset the organogram chart tree + */ + obj.refresh = function() { + el.children[0].innerHTML = ''; + render(0,el.children[0]); + setInitialPosition(); + setInitialWidth(); + } + + /** + * Show or hide childrens of a node + */ + obj.show = function(id) { + var node = findNode({ id: id }); + // Check if the node exists and if it has an icon + if (node && node.lastChild) { + // Click on the icon + node.lastChild.click(); + } + } + + /** + * Appends a new element in the organogram chart + */ + obj.addItem = function(item) { + if (typeof item == 'object' && item.hasOwnProperty('id') && item.hasOwnProperty('parent') && ! isNaN(item.parent) && ! isNaN(item.id)) { + var findedParent = obj.options.data.find(function(node) { + if (node.id == item.parent) { + return true; + } + return false; + }); + + if (findedParent) { + obj.options.data.push(item); + + obj.refresh(); + + if (typeof obj.options.onchange == 'function') { + obj.options.onchange(el, obj); + } + } + else { + console.log('cannot add this item'); + } + } + } + + var removeItemRecursively = function(id) { + var itemIndex = obj.options.data.findIndex(function(node) { + return node.id == id; + }); + + if (itemIndex > 0) { + obj.options.data.splice(itemIndex, 1); + + var itemChildrenList = obj.options.data.filter(function(node) { + return node.parent === id; + }); + + itemChildrenList.forEach(function(childItem) { + removeItemRecursively(childItem.id); + }); + } + } + + /** + * Removes a item from the organogram chart + */ + obj.removeItem = function(id) { + removeItemRecursively(id); + + obj.refresh(); + } + + /** + * Sets a new value for the data array and re-render the organogram. + */ + obj.setData = function(data) { + if (typeof(data) == 'object') { + obj.options.data = data; + obj.refresh(); + } + } + + /** + * Search for any item with the string and centralize it. + */ + obj.search = function(str) { + var input = str.toLowerCase(); + + if (options) { + var data = obj.options.data; + var searchedNode = data.find(node => node.name.toLowerCase() == input); + if (searchedNode) { + var node = findNode({ id: searchedNode.id }); + // Got to the node position + if (node) { + var nodeRect = node.getBoundingClientRect(); + var ulRect = ul.getBoundingClientRect(); + var tm = (nodeRect.top - ulRect.top) - (ul.clientHeight / 2) + (node.clientHeight / 2) + var lm = (nodeRect.left - ulRect.left) - (ul.clientWidth / 2) + (node.clientWidth / 2); + var newTop = (parseFloat(ul.children[0].style.top) - tm); + var newLeft = (parseFloat(ul.children[0].style.left) - lm); + animateOnSearch(newLeft, newTop); + } + } + } + } + + /** + * Change the organogram dimensions + */ + obj.setDimensions = function(width, height) { + el.style.width = width + 'px'; + el.style.height = height + 'px'; + } + + var pinchStart = function(e) { + state.fingerDistance = Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY); + } + + var pinchMove = function(e) { + e.preventDefault(); + + var dist2 = Math.hypot(e.touches[0].pageX - e.touches[1].pageX,e.touches[0].pageY - e.touches[1].pageY); + + if (dist2 > state.fingerDistance) { + var dif = dist2 - state.fingerDistance; + var newZoom = state.scale + state.scale * dif * 0.0025; + if (newZoom <= 5.09) { + obj.zoom(newZoom); + document.getElementById('info').textContent = newZoom; + } + } + + if (dist2 < state.fingerDistance) { + var dif = state.fingerDistance - dist2; + var newZoom = state.scale - state.scale * dif * 0.0025; + if (newZoom >= 0.1) { + obj.zoom(newZoom); + document.getElementById('info').textContent = newZoom; + } + } + state.fingerDistance = dist2; + } + + var moving = false; + + var moveListener = function(e){ + e = e || window.event; + e.preventDefault(); + + if (! state.scaling) { + if (e.which || state.mobileDown) { + moving = true; + + var currentX = e.clientX || e.pageX || (e.changedTouches && (e.changedTouches[0].pageX || e.changedTouches[0].clientX)); + var currentY = e.clientY || e.pageY || (e.changedTouches && (e.changedTouches[0].pageY || e.changedTouches[0].clientY)); + + var x = state.x - currentX; + var y = (state.y - currentY); + var zoomFactor = ul.style.zoom <= 1 ? 1 + (1 - ul.style.zoom) : 1 - (ul.style.zoom - 1) < .5 ? .5 : 1 - (ul.style.zoom - 1); + ul.children[0].style.left = -(state.scrollLeft + x * zoomFactor) + 'px'; + ul.children[0].style.top = (state.scrollTop + y * zoomFactor * -1) + 'px'; + } + } + + if (state.scaling) { + pinchMove(e); + } + } + + var touchListener = function(e) { + e = e || window.event; + + if (e.changedTouches) { + state.mobileDown = true; + } + + state.x = e.clientX || e.pageX || e.changedTouches[0].pageX || e.changedTouches[0].clientX; + state.y = e.clientY || e.pageY || e.changedTouches[0].pageY || e.changedTouches[0].clientY; + state.scrollLeft = - 1 * parseFloat(ul.children[0].style.left) || 0; + state.scrollTop = parseFloat(ul.children[0].style.top); + + if (e.touches) { + if(e.touches.length == 2) { + state.scaling = true; + pinchStart(e); + } + } + } + + var touchEnd = function(e) { + state.mobileDown = false; + if (state.scaling) { + state.scaling = false; + } + + moving = false; + } + + var ul = null; + var search = null; + var zoomContainer = null; + var zoomIn = null; + var zoomOut = null; + var fullscreen = null; + + var init = function() { + // Create zoom action + zoomContainer = document.createElement('div'); + zoomContainer.className = 'jorg-zoom-container'; + obj.zoomContainer = zoomContainer; + + zoomIn = document.createElement('i'); + zoomIn.className = 'jorg-zoom-in material-icons jorg-action'; + zoomIn.innerHTML = "add_box"; + + zoomOut = document.createElement('i'); + zoomOut.className = 'jorg-zoom-out material-icons jorg-action'; + zoomOut.innerHTML = "indeterminate_check_box"; + + fullscreen = document.createElement('i'); + fullscreen.className = 'jorg-fullscreen material-icons jorg-action'; + fullscreen.title = 'Fullscreen'; + fullscreen.innerHTML = "slideshow"; + + zoomContainer.appendChild(fullscreen); + zoomContainer.appendChild(zoomIn); + zoomContainer.appendChild(zoomOut); + + zoomIn.addEventListener('click', zoom); + zoomOut.addEventListener('click', zoom); + fullscreen.addEventListener('click', setFullScreenMode); + + // Create container + ul = document.createElement('ul'); + + // Default zoom + if (! ul.style.zoom) { + ul.style.zoom = '1'; + } + + // Default classes + el.classList.add('jorg'); + el.classList.add('jorg-tf-tree'); + el.classList.add('jorg-unselectable'); + ul.classList.add('jorg-disable-scrollbars'); + + // Append elements + el.appendChild(ul); + el.appendChild(zoomContainer); + + search = document.createElement('input'); + search.type = 'text'; + search.classList.add('jorg-search'); + search.onkeyup = function(e) { + obj.search(e.target.value); + } + search.onblur = function(e) { + e.target.value = ''; + } + + // Event handlers + ul.addEventListener('wheel', zoom); + ul.addEventListener('mousemove', moveListener); + ul.addEventListener('touchmove', moveListener); + ul.addEventListener('touchstart', touchListener); + ul.addEventListener('touchend', touchEnd); + ul.addEventListener('mousedown', touchListener); + + el.addEventListener('click', function(e) { + if (!moving) { + if (typeof(obj.options.onclick) == 'function') { + obj.options.onclick(el, obj, e); + } + } else { + moving = false; + } + }); + + obj.setOptions(options); + + // Create + var create = function() { + render(0, ul); + setInitialPosition(); + setInitialWidth(); + // Set default dimensions + obj.setDimensions(obj.options.width, obj.options.height); + + if (typeof obj.options.onload == 'function') { + obj.options.onload(el, obj); + } + } + + // Loading data + if (obj.options.url) { + jSuites.ajax({ + url: obj.options.url, + method: 'GET', + dataType: 'json', + success: function(result) { + obj.options.data = result; + + create(); + } + }); + } else if (obj.options.data && obj.options.data.length) { + create(); + } + + el.organogram = obj; + } + + init(); + + return obj; +}); + +jSuites.template = (function(el, options) { + // Update configuration + if (el.classList.contains('jtemplate')) { + return el.template.setOptions(options); + } + + var obj = {}; + obj.options = {}; + + // Search controls + var pageNumber = 0; + var searchTimer = null; + var searchResults = null; + + // Parse events inside the template + var parse = function(element) { + // Attributes + var attr = {}; + + if (element.attributes && element.attributes.length) { + for (var i = 0; i < element.attributes.length; i++) { + attr[element.attributes[i].name] = element.attributes[i].value; + } + } + + // Keys + var k = Object.keys(attr); + + if (k.length) { + for (var i = 0; i < k.length; i++) { + // Parse events + if (k[i].substring(0,2) == 'on') { + // Get event + var event = k[i].toLowerCase(); + var value = attr[k[i]]; + + // Get action + element.removeAttribute(event); + if (! element.events) { + element.events = [] + } + + // Keep method to the event + element[k[i].substring(2)] = value; + if (obj.options.version == 2) { + element[event] = function(e) { + Function('template', 'e', element[e.type]).call(element, obj.options.template, e); + } + } else { + element[event] = function(e) { + Function('e', 'element', element[e.type]).call(obj.options.template, e, element); + } + } + } + } + } + + // Check the children + if (element.children.length) { + for (var i = 0; i < element.children.length; i++) { + parse(element.children[i]); + } + } + } + + /** + * Set the options + */ + obj.setOptions = function() { + // Default configuration + var defaults = { + version: null, + url: null, + data: null, + total: null, + filter: null, + template: null, + render: null, + noRecordsFound: 'No records found', + containerClass: null, + // Searchable + search: null, + searchInput: true, + searchPlaceHolder: '', + searchValue: '', + // Remote search + remoteData: false, + // Pagination page number of items + pagination: null, + // Events + onload: null, + onupdate: null, + onchange: null, + onsearch: null, + onclick: null, + oncreateitem: null, + } + + // Loop through our object + for (var property in defaults) { + if (options && options.hasOwnProperty(property)) { + obj.options[property] = options[property]; + } else if (typeof(obj.options[property]) === 'undefined') { + obj.options[property] = defaults[property]; + } + } + + // Pagination container + if (obj.options.pagination) { + el.insertBefore(pagination, el.firstChild); + } else { + if (pagination && pagination.parentNode) { + el.removeChild(pagination); + } + } + + + // Input search + if (obj.options.search && obj.options.searchInput == true) { + el.insertBefore(searchContainer, el.firstChild); + // Input value + obj.searchInput.value = obj.options.searchValue; + } else { + if (searchContainer && searchContainer.parentNode) { + el.removeChild(searchContainer); + } + } + + // Search placeholder + if (obj.options.searchPlaceHolder) { + obj.searchInput.setAttribute('placeholder', obj.options.searchPlaceHolder); + } else { + obj.searchInput.removeAttribute('placeholder'); + } + + // Class for the container + if (obj.options.containerClass) { + container.classList.add(obj.options.containerClass); + } + } + + /** + * Contains the cache of local data loaded + */ + obj.cache = []; + + /** + * Append data to the template and add to the DOMContainer + * @param data + * @param contentDOMContainer + */ + obj.setContent = function(a, b) { + // Get template + var c = obj.options.template[Object.keys(obj.options.template)[0]](a, obj); + // Process events + if ((c instanceof Element || c instanceof HTMLDocument)) { + b.appendChild(c); + } else { + b.innerHTML = c; + } + + parse(b); + + // Oncreate a new item + if (typeof(obj.options.oncreateitem) == 'function') { + obj.options.oncreateitem(el, obj, b.children[0], a); + } + } + + /** + * Add a new option in the data + */ + 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); + } + } + + /** + * Remove the item from the 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'); + } + } + /** + * Reset the data of the element + */ + obj.setData = function(data) { + if (data) { + // Current page number + pageNumber = 0; + // Reset search + 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); + } + } + } + + /** + * Get the current page number + */ + obj.getPage = function() { + return pageNumber; + } + + /** + * Append data to the component + */ + obj.appendData = function(data, p) { + if (p) { + pageNumber = p; + } + + var execute = function(data) { + // Concat data + obj.options.data.concat(data); + + 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]; + 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 (pageNumber) { + ajaxData.p = 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; + + // Data filtering + if (typeof(obj.options.filter) == 'function') { + data = obj.options.filter(data); + } + + // Reset pagination container + pagination.innerHTML = ''; + + 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 * pageNumber); + var finalNumber = (obj.options.pagination * 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++) { + // Check if cache obj contains the element + if (! data[i].element) { + obj.setContent(data[i], content); + content.children[0].dataReference = data[i]; + data[i].element = content.children[0]; + // append element into cache + obj.cache.push(data[i]); + container.appendChild(content.children[0]); + } else { + container.appendChild(data[i].element); + } + } + + if (obj.options.total) { + var numberOfPages = Math.ceil(obj.options.total / obj.options.pagination); + } else { + var numberOfPages = Math.ceil(data.length / obj.options.pagination); + } + + // Update pagination + if (obj.options.pagination > 0 && numberOfPages > 1) { + // Controllers + if (pageNumber < 6) { + var startNumber = 0; + var finalNumber = numberOfPages < 10 ? numberOfPages : 10; + } else if (numberOfPages - pageNumber < 5) { + var startNumber = numberOfPages - 9; + var finalNumber = numberOfPages; + if (startNumber < 0) { + startNumber = 0; + } + } else { + var startNumber = pageNumber - 4; + var finalNumber = pageNumber + 5; + } + + // First + if (startNumber > 0) { + var paginationItem = document.createElement('div'); + paginationItem.innerHTML = '<'; + paginationItem.title = 0; + pagination.appendChild(paginationItem); + } + + // Get page links + for (var i = startNumber; i < finalNumber; i++) { + var paginationItem = document.createElement('div'); + paginationItem.innerHTML = (i + 1); + pagination.appendChild(paginationItem); + + if (pageNumber == i) { + paginationItem.style.fontWeight = 'bold'; + paginationItem.style.textDecoration = 'underline'; + } + } + + // Last + if (finalNumber < numberOfPages) { + var paginationItem = document.createElement('div'); + paginationItem.innerHTML = '>'; + paginationItem.title = numberOfPages - 1; + pagination.appendChild(paginationItem); + } + } + } + } + + obj.render = function(p, forceLoad) { + // Update page number + if (p !== undefined) { + pageNumber = p; + } + + // 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(); + + // On Update + if (typeof(obj.options.onupdate) == 'function') { + obj.options.onupdate(el, obj, pageNumber); + } + + if (forceLoad) { + // Onload + if (typeof(obj.options.onload) == 'function') { + obj.options.onload(el, obj, pageNumber); + } + } + } + + 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 (pageNumber) { + ajaxData.p = 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.total = data.total; + obj.options.data = data.data; + } else { + obj.options.total = null; + 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 { + // Load data for the user + execute(); + } + } + } + + obj.search = function(query) { + // Page number + pageNumber = 0; + // Search query + 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; + } + + searchResults = obj.options.data.filter(function(item) { + return test(item, query); + }); + } + + obj.render(0); + + if (typeof(obj.options.onsearch) == 'function') { + obj.options.onsearch(el, obj, query); + } + } + + obj.refresh = function() { + obj.cache = []; + obj.render(); + } + + obj.reload = function() { + obj.cache = []; + obj.render(0, true); + } + + /** + * Events + */ + 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.addEventListener('mouseup', function(e) { + if (typeof(obj.options.onclick) == 'function') { + obj.options.onclick(el, obj, e); + } + }); + + // Reset content + el.innerHTML = ''; + + // Container + var container = document.createElement('div'); + container.classList.add ('jtemplate-content'); + el.appendChild(container); + + // Pagination container + var pagination = document.createElement('div'); + pagination.className = 'jtemplate-pagination'; + + // Search DOM elements + var searchContainer = document.createElement('div'); + searchContainer.className = 'jtemplate-results'; + obj.searchInput = document.createElement('input'); + 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); + + // Set the options + obj.setOptions(options); + + // Keep the reference in the DOM container + el.template = obj; + + // Render data + obj.render(0, true); + + return obj; +}); + +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: '
No information for this period
', + } + }; + + // 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'); + + obj.options.container = el; + + // 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 = 'keyboard_arrow_left'; + timelineNavigation.appendChild(timelinePrev); + + var timelineNext = document.createElement('div'); + timelineNext.className = 'jtimeline-next'; + timelineNext.innerHTML = 'keyboard_arrow_right'; + 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'); + + } + + // Get item by date + var getEventByDate = function(date) { + return obj.options.data.filter(function(evt) { + return (evt.date.length > 7 ? evt.date.substr(0,7) : evt.date) == date; + }); + } + + obj.setData = function(rows) { + obj.options.data = rows; + obj.render(obj.options.date); + } + + obj.add = function(data) { + var date = data.date.substr(0,7); + + // Format date + data.date = data.date.substr(0,10); + + // Append data + obj.options.data.push(data); + + // Reorder + obj.options.data[obj.options.data.indexOf(data)] = data.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(); + }); + + var data = getEventByDate(date)[0]; + data.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 = []; + var events = getEventByDate(date); + + // Itens + if (! events.length) { + timelineContainer.innerHTML = obj.options.text.noInformation; + } else { + for (var i = 0; i < events.length; i++) { + var v = events[i]; + var d = v.date.length > 10 ? v.date.substr(0,10).split('-') : 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.id = v.id; + timelineEdit.onclick = function() { + if (typeof(obj.options.onaction) == 'function') { + obj.options.onaction(obj, this, this.id); + } + } + 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/_static/jsuites/jsuites.mobile.css b/web/_static/jsuites/jsuites.mobile.css new file mode 100644 index 0000000..4b34bb0 --- /dev/null +++ b/web/_static/jsuites/jsuites.mobile.css @@ -0,0 +1,1012 @@ + +/** + * (c) jSuites Javascript Web Components + * + * Website: https://jsuites.net + * Description: Create amazing web based applications. + * + * MIT License + * + */ + +.japp { + height: 100%; + box-sizing: border-box; + overflow: auto; + 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.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 { + display: flex; + flex-wrap: nowrap; + align-items: flex-start; + height: 100%; + width: 100%; +} + +.japp .page { + padding-top: 0px; + 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 .page.with-navbar { + padding-top: 45px; +} + +.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 { + width: 100%; + display: block; +} + +.japp .options .jdropdown .jdropdown-header { + border: 0px; + padding: 0px !important; + 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) +{ + .japp * { + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; + } + + body { + 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; + } + + .japp input, .japp select, .japp textarea, .japp div { + font-family:-apple-system,SF UI Text,Helvetica Neue,Helvetica,Arial,sans-serif !important; + } + + .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 .jtemplate-empty { + text-align:center; + padding-top:10px; + padding-bottom:10px; + margin-right:10px; +} + + +.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/_static/jsuites/jsuites.mobile.js b/web/_static/jsuites/jsuites.mobile.js new file mode 100644 index 0000000..e152da1 --- /dev/null +++ b/web/_static/jsuites/jsuites.mobile.js @@ -0,0 +1,1016 @@ +jSuites.app = (function(el, options) { + var obj = {}; + obj.options = {}; + + // Default configuration + var defaults = { + path: 'views', + onbeforechangepage: null, + onchangepage: null, + onbeforecreatepage: null, + oncreatepage: null, + onerrorpage: null, + onloadpage: null, + toolbar: null, + route: null, + ident: null, + detachHiddenPages: 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]; + } + } + + // App + el.classList.add('japp'); + + // Toolbar + var toolbar = document.createElement('div'); + + obj.setToolbar = function(o) { + if (o) { + obj.options.toolbar = o; + } + // Force application + obj.options.toolbar.app = obj; + // Set toolbar + obj.toolbar = jSuites.toolbar(toolbar, obj.options.toolbar); + // Add to the DOM + el.appendChild(toolbar); + } + + obj.hideToolbar = function() { + if (toolbar.style.display == '') { + toolbar.style.display = 'none'; + } + } + + obj.showToolbar = function() { + if (toolbar.style.display == 'none') { + toolbar.style.display = ''; + } + } + + /** + * Page identification + */ + var ident = function(route) { + route = route.split('?')[0]; + + if (typeof(obj.options.ident) == 'function') { + var ret = obj.options.ident(route); + if (typeof(ret) !== 'undefined') { + return ret; + } + } + + return route; + } + + /* + * 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' || type == 'text/loader') { + eval(script[i].text); + } + } + } + + /** + * Pages + */ + obj.pages = function() { + /** + * Create or access a page + */ + var component = function(route, o, callback, element) { + var options = {}; + + if (o) { + if (typeof(o) == 'object') { + var options = o; + } else { + if (! callback && typeof(o) == 'function') { + callback = o; + } + } + } + + if (typeof(obj.options.route) == 'function') { + route = obj.options.route(route, options); + } + + if (route === false) { + console.error('JSUITES: Permission denied'); + } else { + // Query string does not make part in the route + options.ident = ident(route); + // Current Route + options.route = route; + + // If exists just open + var page = component.container[options.ident]; + if (page) { + page.options.closed = 0; + component.show(page, options, callback); + } else { + // Closed + options.closed = options.closed ? 1 : 0; + + // New page url + if (! options.url) { + options.url = obj.options.path + options.ident + '.html'; + } + + // Create new page + page = component.create(options, callback, element); + + // Container + component.container[options.ident] = page; + } + } + } + + /** + * Create a new page + */ + component.create = function(o, callback, fromElement) { + // Create page + if (fromElement) { + var page = fromElement; + } else { + var page = document.createElement('div'); + } + + page.classList.add('page'); + + // Keep options + page.options = o ? o : {}; + + // Create page overwrite + var ret = null; + if (typeof(obj.options.onbeforecreatepage) == 'function') { + ret = obj.options.onbeforecreatepage(obj, page); + if (ret === false) { + return false; + } + } + + var success = function(result) { + // Remove to avoid id conflicts + if (component.current && obj.options.detachHiddenPages == true) { + while (component.element.children[0]) { + component.element.children[0].parentNode.removeChild(component.element.children[0]); + } + } + + if (! component.current) { + component.element.appendChild(page); + } else { + component.element.insertBefore(page, component.current.nextSibling); + } + + // Open page + if (result) { + page.innerHTML = result; + } + + // Get javascript + try { + parseScript(page); + } catch (e) { + console.log(e); + } + + // Create page overwrite + if (typeof(obj.options.oncreatepage) == 'function') { + obj.options.oncreatepage(obj, page, result); + } + + // Push to refresh controls + if (typeof(page.options.onpush) == 'function') { + jSuites.refresh(page, page.options.onpush); + } + + // Navbar + if (page.querySelector('.navbar')) { + page.classList.add('with-navbar'); + } + + // Global onload callback + if (typeof(obj.options.onloadpage) == 'function') { + obj.options.onloadpage(obj, page); + } + + // Specific online callback + if (typeof(o.onload) == 'function') { + o.onload(page); + } + + // Always hidden when created + page.style.display = 'none'; + + // Show page + if (! page.options.closed) { + component.show(page, o, callback); + } + } + + // URL + if (o.url.indexOf('?') == -1) { + var url = o.url + '?'; + } else { + var url = o.url + '&'; + } + + if (fromElement) { + success(); + } else { + jSuites.ajax({ + url: url + 'ts=' + new Date().getTime(), + method: 'GET', + dataType: 'html', + queue: true, + success: success, + error: function(a,b) { + if (typeof(obj.options.onerrorpage) == 'function') { + obj.options.onerrorpage(obj, page, a, b); + } + + component.destroy(page); + } + }); + } + + return page; + } + + component.show = function(page, o, callback) { + if (o) { + if (o.onenter) { + page.options.onenter = o.onenter; + } + if (o.onleave) { + page.options.onleave = o.onleave; + } + if (o.route) { + page.options.route = o.route; + } + } + + // Add history + if (! o || ! o.ignoreHistory) { + // Route + if (o && o.route) { + var route = o.route; + } else { + var route = page.options.route; + } + // Add history + window.history.pushState({ route: route }, page.options.title, route); + } + + var pageIsReady = function() { + if (component.current) { + component.current.style.display = 'none'; + + if (component.current && obj.options.detachHiddenPages == true) { + if (component.current.parentNode) { + component.current.parentNode.removeChild(component.current); + } + } + } + + // New page + if (typeof(obj.options.onchangepage) == 'function') { + obj.options.onchangepage(obj, page, component.current, 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; + } + + // Append page in case was detached + if (! page.parentNode) { + component.element.appendChild(page); + } + + if (component.current) { + // Show page + page.style.display = ''; + + if (component.current != page) { + var a = Array.prototype.indexOf.call(component.element.children, component.current); + var b = Array.prototype.indexOf.call(component.element.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); + } + + // Animation only on mobile + var rect = component.element.getBoundingClientRect(); + + // Move to the top + window.scrollTo({ top: 0 }); + + // Page is ready + if (rect.width < 800 && obj.options.detachHiddenPages == false) { + jSuites.animation.slideLeft(component.element, (a < b ? 0 : 1), function() { + if (component.current != page) { + pageIsReady(); + } + }); + } else { + if (component.current != page) { + pageIsReady(); + } + } + } else { + component.current = null; + + pageIsReady(); + } + } else { + // Show + page.style.display = ''; + + // Page is ready + pageIsReady(); + } + + // Select toolbar item + if (page.options.toolbarItem) { + obj.toolbar.selectItem(page.options.toolbarItem); + } + } + + /** + * Get a page by route + */ + component.get = function(route) { + var key = ident(route); + if (component.container[key]) { + return component.container[key]; + } + } + + /** + * Reset the page container + */ + component.reset = function() { + // Container + component.element.innerHTML = ''; + // Current + component.current = null; + } + + /** + * Reset the page container + */ + component.destroy = function(page) { + if (page) { + if (page.parentNode) { + page.remove(); + } + delete component.container[page.options.ident]; + } else { + // Reset container + component.reset(); + // Destroy references + component.container = {}; + } + } + + /** + * Page container controller + */ + component.container = {}; + + component.init = function() { + /** + * Pages DOM container + */ + var pagesContainer = el.querySelector('.pages'); + if (pagesContainer) { + component.element = pagesContainer; + } else { + component.element = document.createElement('div'); + component.element.className = 'pages'; + } + + // Prefetched content + var current = null; + if (el.innerHTML) { + // Create with the prefetched content + current = document.createElement('div'); + while (el.childNodes[0]) { + current.appendChild(el.childNodes[0]); + } + } + + // Append page container to the application + el.appendChild(component.element); + + // Go to the current page + if (current) { + component(window.location.pathname, null, null, current); + } + } + + return component; + }(); + + // Start page object + obj.pages.init(); + + /** + * 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; + }(); + + // Actionsheet + obj.actionsheet = jSuites.actionsheet(el, obj); + + 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 action = null; + + var clicked = 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'); + } + } + + // Grouped buttons + if (e.target.parentNode && e.target.parentNode.classList && e.target.parentNode.classList.contains('jbuttons-group')) { + for (var j = 0; j < e.target.parentNode.children.length; j++) { + e.target.parentNode.children[j].classList.remove('selected'); + } + e.target.classList.add('selected'); + } + + // App links + var tmp = jSuites.findElement(e.target, function(el) { + return el.tagName == 'A' && el.getAttribute('href') ? el : false; + }); + + if (tmp) { + var h = tmp.getAttribute('href'); + if (h.substr(0,2) == '//' || h.substr(0,4) == 'http' || tmp.classList.contains('link') || h.indexOf('#') >= 0) { + action = null; + } else { + var p = jSuites.getPosition(e); + action = { + h: h, + element: tmp, + target: e.target, + x: p[0], + y: p[1], + }; + + // Cancel click operation in 400ms + setTimeout(function() { + action = null; + }, 400); + } + } + } + + var actionDown = function(e) { + e = e || window.event; + if (e.buttons) { + var mouseButton = e.buttons; + } else if (e.button) { + var mouseButton = e.button; + } else { + var mouseButton = e.which; + } + + if (mouseButton < 2) { + clicked(e); + } + } + + var actionUp = function(e) { + obj.actionsheet.close(); + // Action + if (action) { + var p = jSuites.getPosition(e); + // If mouse move cancel the click action + if (Math.abs(action.x - p[0]) < 5 && Math.abs(action.y - p[1]) < 5) { + // Go to the page + obj.pages(action.h); + } + // Prevent default + e.preventDefault(); + action = 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('click', 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 }); + } else { + window.location.href = e.state.route; + } + } else { + window.location.reload(); + } + } + + if (obj.options.toolbar) { + obj.setToolbar(); + } + + el.app = obj; + + return obj; +}); + +jSuites.actionsheet = (function(el, component) { + var obj = function(options) { + // Reset container + actionContent.innerHTML = ''; + + // Create new elements + for (var i = 0; i < options.length; i++) { + var actionGroup = document.createElement('div'); + actionGroup.className = 'jactionsheet-group'; + + for (var j = 0; j < options[i].length; j++) { + var v = 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(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); + } + + obj.close = function() { + if (actionsheet.style.display != 'none') { + // Remove any existing actionsheet + jSuites.animation.slideBottom(actionContent, false, function() { + actionsheet.style.display = 'none'; + }); + } + } + + obj.get = function() { + return actionsheet; + } + + // Init action sheet + 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); + + el.actionsheet = 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/_static/jsuites/jsuites.webcomponents.js b/web/_static/jsuites/jsuites.webcomponents.js new file mode 100644 index 0000000..8cf7dcc --- /dev/null +++ b/web/_static/jsuites/jsuites.webcomponents.js @@ -0,0 +1,501 @@ + +/** + * (c) jSuites Javascript Web Components + * + * Website: https://jsuites.net + * 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); + + -- cgit v1.2.3