12268 lines
393 KiB
JavaScript
12268 lines
393 KiB
JavaScript
/**
|
|
* (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 = {};
|
|
|
|
var Version = '4.14.3';
|
|
|
|
var Events = function() {
|
|
|
|
document.jsuitesComponents = [];
|
|
|
|
var find = function(DOMElement, component) {
|
|
if (DOMElement[component.type] && DOMElement[component.type] == component) {
|
|
return true;
|
|
}
|
|
if (DOMElement.component && DOMElement.component == component) {
|
|
return true;
|
|
}
|
|
if (DOMElement.parentNode) {
|
|
return find(DOMElement.parentNode, component);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
var isOpened = function(e) {
|
|
if (document.jsuitesComponents && document.jsuitesComponents.length > 0) {
|
|
for (var i = 0; i < document.jsuitesComponents.length; i++) {
|
|
if (document.jsuitesComponents[i] && ! find(e, document.jsuitesComponents[i])) {
|
|
document.jsuitesComponents[i].close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Width of the border
|
|
var cornerSize = 15;
|
|
|
|
// Current element
|
|
var element = null;
|
|
|
|
// Controllers
|
|
var editorAction = false;
|
|
|
|
// Event state
|
|
var state = {
|
|
x: null,
|
|
y: null,
|
|
}
|
|
|
|
// Tooltip element
|
|
var tooltip = document.createElement('div')
|
|
tooltip.classList.add('jtooltip');
|
|
|
|
// Events
|
|
var mouseDown = function(e) {
|
|
// Check if this is the floating
|
|
var item = jSuites.findElement(e.target, 'jpanel');
|
|
// Jfloating found
|
|
if (item && ! item.classList.contains("readonly")) {
|
|
// Add focus to the chart container
|
|
item.focus();
|
|
// Keep the tracking information
|
|
var rect = e.target.getBoundingClientRect();
|
|
editorAction = {
|
|
e: item,
|
|
x: e.clientX,
|
|
y: e.clientY,
|
|
w: rect.width,
|
|
h: rect.height,
|
|
d: item.style.cursor,
|
|
resizing: item.style.cursor ? true : false,
|
|
actioned: false,
|
|
}
|
|
|
|
// Make sure width and height styling is OK
|
|
if (! item.style.width) {
|
|
item.style.width = rect.width + 'px';
|
|
}
|
|
|
|
if (! item.style.height) {
|
|
item.style.height = rect.height + 'px';
|
|
}
|
|
|
|
// Remove any selection from the page
|
|
var s = window.getSelection();
|
|
if (s.rangeCount) {
|
|
for (var i = 0; i < s.rangeCount; i++) {
|
|
s.removeRange(s.getRangeAt(i));
|
|
}
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
} else {
|
|
// No floating action found
|
|
editorAction = false;
|
|
}
|
|
|
|
// Verify current components tracking
|
|
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;
|
|
}
|
|
|
|
// Which component I am clicking
|
|
var path = e.path || (e.composedPath && e.composedPath());
|
|
|
|
// If path available get the first element in the chain
|
|
if (path) {
|
|
element = path[0];
|
|
} else {
|
|
// Try to guess using the coordinates
|
|
if (e.target && e.target.shadowRoot) {
|
|
var d = e.target.shadowRoot;
|
|
} else {
|
|
var d = document;
|
|
}
|
|
// Get the first target element
|
|
element = d.elementFromPoint(x, y);
|
|
}
|
|
|
|
isOpened(element);
|
|
}
|
|
|
|
var mouseUp = function(e) {
|
|
if (editorAction && editorAction.e) {
|
|
if (typeof(editorAction.e.refresh) == 'function' && state.actioned) {
|
|
editorAction.e.refresh();
|
|
}
|
|
editorAction.e.style.cursor = '';
|
|
}
|
|
|
|
// Reset
|
|
state = {
|
|
x: null,
|
|
y: null,
|
|
}
|
|
|
|
editorAction = false;
|
|
}
|
|
|
|
var mouseMove = function(e) {
|
|
if (editorAction) {
|
|
var x = e.clientX || e.pageX;
|
|
var y = e.clientY || e.pageY;
|
|
|
|
// Action on going
|
|
if (! editorAction.resizing) {
|
|
if (state.x == null && state.y == null) {
|
|
state.x = x;
|
|
state.y = y;
|
|
}
|
|
|
|
var dx = x - state.x;
|
|
var dy = y - state.y;
|
|
var top = editorAction.e.offsetTop + dy;
|
|
var left = editorAction.e.offsetLeft + dx;
|
|
|
|
// Update position
|
|
editorAction.e.style.top = top + 'px';
|
|
editorAction.e.style.left = left + 'px';
|
|
editorAction.e.style.cursor = "move";
|
|
|
|
state.x = x;
|
|
state.y = y;
|
|
|
|
|
|
// Update element
|
|
if (typeof(editorAction.e.refresh) == 'function') {
|
|
state.actioned = true;
|
|
editorAction.e.refresh('position', top, left);
|
|
}
|
|
} else {
|
|
var width = null;
|
|
var height = null;
|
|
|
|
if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') {
|
|
// Update width
|
|
width = editorAction.w + (x - editorAction.x);
|
|
editorAction.e.style.width = width + 'px';
|
|
|
|
// Update Height
|
|
if (e.shiftKey) {
|
|
var newHeight = (x - editorAction.x) * (editorAction.h / editorAction.w);
|
|
height = editorAction.h + newHeight;
|
|
editorAction.e.style.height = height + 'px';
|
|
} else {
|
|
var newHeight = false;
|
|
}
|
|
}
|
|
|
|
if (! newHeight) {
|
|
if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') {
|
|
height = editorAction.h + (y - editorAction.y);
|
|
editorAction.e.style.height = height + 'px';
|
|
}
|
|
}
|
|
|
|
// Update element
|
|
if (typeof(editorAction.e.refresh) == 'function') {
|
|
state.actioned = true;
|
|
editorAction.e.refresh('dimensions', width, height);
|
|
}
|
|
}
|
|
} else {
|
|
// Resizing action
|
|
var item = jSuites.findElement(e.target, 'jpanel');
|
|
// Found eligible component
|
|
if (item) {
|
|
if (item.getAttribute('tabindex')) {
|
|
var rect = item.getBoundingClientRect();
|
|
if (e.clientY - rect.top < cornerSize) {
|
|
if (rect.width - (e.clientX - rect.left) < cornerSize) {
|
|
item.style.cursor = 'ne-resize';
|
|
} else if (e.clientX - rect.left < cornerSize) {
|
|
item.style.cursor = 'nw-resize';
|
|
} else {
|
|
item.style.cursor = 'n-resize';
|
|
}
|
|
} else if (rect.height - (e.clientY - rect.top) < cornerSize) {
|
|
if (rect.width - (e.clientX - rect.left) < cornerSize) {
|
|
item.style.cursor = 'se-resize';
|
|
} else if (e.clientX - rect.left < cornerSize) {
|
|
item.style.cursor = 'sw-resize';
|
|
} else {
|
|
item.style.cursor = 's-resize';
|
|
}
|
|
} else if (rect.width - (e.clientX - rect.left) < cornerSize) {
|
|
item.style.cursor = 'e-resize';
|
|
} else if (e.clientX - rect.left < cornerSize) {
|
|
item.style.cursor = 'w-resize';
|
|
} else {
|
|
item.style.cursor = '';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var mouseOver = function(e) {
|
|
var message = e.target.getAttribute('data-tooltip');
|
|
if (message) {
|
|
// Instructions
|
|
tooltip.innerText = message;
|
|
|
|
// 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;
|
|
}
|
|
|
|
tooltip.style.top = y + 'px';
|
|
tooltip.style.left = x + 'px';
|
|
document.body.appendChild(tooltip);
|
|
} else if (tooltip.innerText) {
|
|
tooltip.innerText = '';
|
|
document.body.removeChild(tooltip);
|
|
}
|
|
}
|
|
|
|
var dblClick = function(e) {
|
|
var item = jSuites.findElement(e.target, 'jpanel');
|
|
if (item && typeof(item.dblclick) == 'function') {
|
|
// Create edition
|
|
item.dblclick(e);
|
|
}
|
|
}
|
|
|
|
var contextMenu = function(e) {
|
|
var item = document.activeElement;
|
|
if (item && typeof(item.contextmenu) == 'function') {
|
|
// Create edition
|
|
item.contextmenu(e);
|
|
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
} else {
|
|
// Search for possible context menus
|
|
item = jSuites.findElement(e.target, function(o) {
|
|
return o.tagName && o.getAttribute('aria-contextmenu-id');
|
|
});
|
|
|
|
if (item) {
|
|
var o = document.querySelector('#' + item);
|
|
if (! o) {
|
|
console.error('JSUITES: contextmenu id not found: ' + item);
|
|
} else {
|
|
o.contextmenu.open(e);
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var keyDown = function(e) {
|
|
var item = document.activeElement;
|
|
if (item) {
|
|
if (e.key == "Delete" && typeof(item.delete) == 'function') {
|
|
item.delete();
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
}
|
|
}
|
|
|
|
if (document.jsuitesComponents && document.jsuitesComponents.length) {
|
|
if (item = document.jsuitesComponents[document.jsuitesComponents.length - 1]) {
|
|
if (e.key == "Escape" && typeof(item.close) == 'function') {
|
|
item.close();
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
document.addEventListener('mouseup', mouseUp);
|
|
document.addEventListener("mousedown", mouseDown);
|
|
document.addEventListener('mousemove', mouseMove);
|
|
document.addEventListener('mouseover', mouseOver);
|
|
document.addEventListener('dblclick', dblClick);
|
|
document.addEventListener('keydown', keyDown);
|
|
document.addEventListener('contextmenu', contextMenu);
|
|
}
|
|
|
|
/**
|
|
* Global jsuites event
|
|
*/
|
|
if (typeof(document) !== "undefined" && ! document.jsuitesComponents) {
|
|
Events();
|
|
}
|
|
|
|
jSuites.version = Version;
|
|
|
|
jSuites.setExtensions = function(o) {
|
|
if (typeof(o) == 'object') {
|
|
var k = Object.keys(o);
|
|
for (var i = 0; i < k.length; i++) {
|
|
jSuites[k[i]] = o[k[i]];
|
|
}
|
|
}
|
|
}
|
|
|
|
jSuites.tracking = function(component, state) {
|
|
if (state == true) {
|
|
document.jsuitesComponents = document.jsuitesComponents.filter(function(v) {
|
|
return v !== null;
|
|
});
|
|
|
|
// Start after all events
|
|
setTimeout(function() {
|
|
document.jsuitesComponents.push(component);
|
|
}, 0);
|
|
|
|
} else {
|
|
var index = document.jsuitesComponents.indexOf(component);
|
|
if (index >= 0) {
|
|
document.jsuitesComponents.splice(index, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get or set a property from a JSON from a string.
|
|
*/
|
|
jSuites.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
|
|
if (o) {
|
|
return o[p];
|
|
}
|
|
}
|
|
}
|
|
// Something went wrong
|
|
return false;
|
|
}
|
|
|
|
// Update dictionary
|
|
jSuites.setDictionary = function(d) {
|
|
if (! document.dictionary) {
|
|
document.dictionary = {}
|
|
}
|
|
// Replace the key into the dictionary and append the new ones
|
|
var k = Object.keys(d);
|
|
for (var i = 0; i < k.length; i++) {
|
|
document.dictionary[k[i]] = d[k[i]];
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Translate
|
|
jSuites.translate = function(t) {
|
|
if (document.dictionary) {
|
|
return document.dictionary[t] || t;
|
|
} else {
|
|
return t;
|
|
}
|
|
}
|
|
|
|
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 = [];
|
|
if (value) {
|
|
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 (value[k] instanceof FileList) {
|
|
vars[k] = value[keys[i]];
|
|
} else if (value[keys[i]] === null || value[keys[i]] === undefined) {
|
|
vars[k] = '';
|
|
} else 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 d = parseData(options.data);
|
|
var k = Object.keys(d);
|
|
|
|
// Data form
|
|
if (options.method == 'GET') {
|
|
if (k.length) {
|
|
var data = [];
|
|
for (var i = 0; i < k.length; i++) {
|
|
data.push(k[i] + '=' + encodeURIComponent(d[k[i]]));
|
|
}
|
|
|
|
if (options.url.indexOf('?') < 0) {
|
|
options.url += '?';
|
|
}
|
|
options.url += data.join('&');
|
|
}
|
|
} else {
|
|
var data = new FormData();
|
|
for (var i = 0; i < k.length; i++) {
|
|
if (d[k[i]] instanceof FileList) {
|
|
if (d[k[i]].length) {
|
|
for (var j = 0; j < d[k[i]].length; j++) {
|
|
data.append(k[i], d[k[i]][j], d[k[i]][j].name);
|
|
}
|
|
}
|
|
} else {
|
|
data.append(k[i], d[k[i]]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var httpRequest = new XMLHttpRequest();
|
|
httpRequest.open(options.method, options.url, true);
|
|
httpRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
|
|
|
// Content type
|
|
if (options.contentType) {
|
|
httpRequest.setRequestHeader('Content-Type', options.contentType);
|
|
}
|
|
|
|
// Headers
|
|
if (options.method == 'POST') {
|
|
httpRequest.setRequestHeader('Accept', 'application/json');
|
|
} else {
|
|
if (options.dataType == 'blob') {
|
|
httpRequest.responseType = "blob";
|
|
} else {
|
|
if (! options.contentType) {
|
|
if (options.dataType == 'json') {
|
|
httpRequest.setRequestHeader('Content-Type', 'text/json');
|
|
} 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);
|
|
}
|
|
|
|
// Before send
|
|
if (typeof(jSuites.ajax.beforeSend) == 'function') {
|
|
jSuites.ajax.beforeSend(httpRequest);
|
|
}
|
|
|
|
if (document.ajax && typeof(document.ajax.beforeSend) == 'function') {
|
|
document.ajax.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) {
|
|
if (Array.isArray(httpRequest.data)) {
|
|
httpRequest.send(httpRequest.data.join('&'));
|
|
} else {
|
|
httpRequest.send(httpRequest.data);
|
|
}
|
|
} 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,
|
|
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,
|
|
}
|
|
|
|
// 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.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
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;
|
|
obj.date[2] = 1; // first day of the month
|
|
} 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[index].substr(0,1);
|
|
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 = '<tr><td colspan="7"></td></tr>';
|
|
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 = '<tr><td colspan="7"></td></tr>';
|
|
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 {
|
|
if (elements[i].innerHTML) {
|
|
elements[i].setAttribute('title', elements[i].innerHTML);
|
|
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 o = jSuites.mask(date, { mask: format }, true);
|
|
if (o.date[0] && o.date[1]) {
|
|
if (! o.date[2]) {
|
|
o.date[2] = 1;
|
|
}
|
|
|
|
return o.date[0] + '-' + jSuites.two(o.date[1]) + '-' + jSuites.two(o.date[2]) + ' ' + jSuites.two(o.date[3]) + ':' + jSuites.two(o.date[4])+ ':' + jSuites.two(o.date[5]);
|
|
}
|
|
return '';
|
|
}
|
|
|
|
|
|
var excelInitialTime = Date.UTC(1900, 0, 0);
|
|
var excelLeapYearBug = Date.UTC(1900, 1, 29);
|
|
var millisecondsPerDay = 86400000;
|
|
|
|
/**
|
|
* Date to number
|
|
*/
|
|
jSuites.calendar.dateToNum = function(jsDate) {
|
|
if (typeof(jsDate) === 'string') {
|
|
jsDate = new Date(jsDate + ' GMT+0');
|
|
}
|
|
var jsDateInMilliseconds = jsDate.getTime();
|
|
|
|
if (jsDateInMilliseconds >= excelLeapYearBug) {
|
|
jsDateInMilliseconds += millisecondsPerDay;
|
|
}
|
|
|
|
jsDateInMilliseconds -= excelInitialTime;
|
|
|
|
return jsDateInMilliseconds / millisecondsPerDay;
|
|
}
|
|
|
|
/**
|
|
* Number to date
|
|
*/
|
|
// !IMPORTANT!
|
|
// Excel incorrectly considers 1900 to be a leap year
|
|
jSuites.calendar.numToDate = function(excelSerialNumber) {
|
|
var jsDateInMilliseconds = excelInitialTime + excelSerialNumber * millisecondsPerDay;
|
|
|
|
if (jsDateInMilliseconds >= excelLeapYearBug) {
|
|
jsDateInMilliseconds -= millisecondsPerDay;
|
|
}
|
|
|
|
const d = new Date(jsDateInMilliseconds);
|
|
|
|
var date = [
|
|
d.getUTCFullYear(),
|
|
d.getUTCMonth()+1,
|
|
d.getUTCDate(),
|
|
d.getUTCHours(),
|
|
d.getUTCMinutes(),
|
|
d.getUTCSeconds(),
|
|
];
|
|
|
|
return jSuites.calendar.now(date);
|
|
}
|
|
|
|
// 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;
|
|
if (el.tagName === 'INPUT') {
|
|
el.style.color = el.value;
|
|
el.style.backgroundColor = el.value;
|
|
}
|
|
}
|
|
|
|
// Placeholder
|
|
if (obj.options.placeholder) {
|
|
el.setAttribute('placeholder', obj.options.placeholder);
|
|
} else {
|
|
if (el.getAttribute('placeholder')) {
|
|
el.removeAttribute('placeholder');
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
obj.select = function(color) {
|
|
// Remove current selected 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');
|
|
}
|
|
|
|
obj.options.value = color;
|
|
}
|
|
|
|
/**
|
|
* Open color pallete
|
|
*/
|
|
obj.open = function() {
|
|
if (! container.classList.contains('jcolor-focus')) {
|
|
// Start tracking
|
|
jSuites.tracking(obj, true);
|
|
|
|
// Show color picker
|
|
container.classList.add('jcolor-focus');
|
|
|
|
// Select current color
|
|
if (obj.options.value) {
|
|
obj.select(obj.options.value);
|
|
}
|
|
|
|
// Reset margin
|
|
content.style.marginTop = '';
|
|
content.style.marginLeft = '';
|
|
|
|
var rectContent = content.getBoundingClientRect();
|
|
var availableWidth = jSuites.getWindowWidth();
|
|
var availableHeight = jSuites.getWindowHeight();
|
|
|
|
if (availableWidth < 800 || obj.options.fullscreen == true) {
|
|
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 = '';
|
|
}
|
|
|
|
if (obj.options.position) {
|
|
content.style.position = 'fixed';
|
|
} else {
|
|
content.style.position = '';
|
|
}
|
|
|
|
if (rectContent.left + rectContent.width > availableWidth) {
|
|
content.style.marginLeft = -1 * (rectContent.left + rectContent.width - (availableWidth - 20)) + 'px';
|
|
}
|
|
if (rectContent.top + rectContent.height > availableHeight) {
|
|
content.style.marginTop = -1 * (rectContent.top + rectContent.height - (availableHeight - 20)) + 'px';
|
|
}
|
|
}
|
|
|
|
|
|
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
|
|
obj.select(color);
|
|
|
|
// 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;
|
|
if (el.tagName === 'INPUT') {
|
|
el.style.color = el.value;
|
|
el.style.backgroundColor = el.value;
|
|
}
|
|
|
|
// Element onchange native
|
|
if (typeof(el.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
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);
|
|
|
|
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;
|
|
controls.appendChild(resetButton);
|
|
|
|
// Close button
|
|
closeButton = document.createElement('div');
|
|
closeButton.className = 'jcolor-close';
|
|
closeButton.innerHTML = obj.options.doneLabel;
|
|
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);
|
|
}
|
|
|
|
container.addEventListener("click", function(e) {
|
|
if (e.target.tagName == 'TD') {
|
|
var value = e.target.getAttribute('data-value');
|
|
if (value) {
|
|
obj.setValue(value);
|
|
}
|
|
} else if (e.target.classList.contains('jcolor-reset')) {
|
|
obj.setValue('');
|
|
obj.close();
|
|
} else if (e.target.classList.contains('jcolor-close')) {
|
|
if (jsuitesTabs.getActive() > 0) {
|
|
obj.setValue(slidersResult);
|
|
}
|
|
obj.close();
|
|
} else if (e.target.classList.contains('jcolor-backdrop')) {
|
|
obj.close();
|
|
} else {
|
|
obj.open();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* If element is focus open the picker
|
|
*/
|
|
el.addEventListener("mouseup", function(e) {
|
|
obj.open();
|
|
});
|
|
|
|
// 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;
|
|
}
|
|
|
|
obj.toHex = function(rgb) {
|
|
var hex = function(x) {
|
|
return ("0" + parseInt(x).toString(16)).slice(-2);
|
|
}
|
|
if (/^#[0-9A-F]{6}$/i.test(rgb)) {
|
|
return rgb;
|
|
} else {
|
|
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
|
|
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
|
|
}
|
|
}
|
|
|
|
init();
|
|
|
|
return obj;
|
|
});
|
|
|
|
|
|
|
|
jSuites.contextmenu = (function(el, options) {
|
|
// New instance
|
|
var obj = { type:'contextmenu'};
|
|
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');
|
|
|
|
/**
|
|
* Open contextmenu
|
|
*/
|
|
obj.open = function(e, items) {
|
|
if (items) {
|
|
// Update content
|
|
obj.options.items = items;
|
|
// Create items
|
|
obj.create(items);
|
|
}
|
|
|
|
// Close current contextmenu
|
|
if (jSuites.contextmenu.current) {
|
|
jSuites.contextmenu.current.close();
|
|
}
|
|
|
|
// Add to the opened components monitor
|
|
jSuites.tracking(obj, true);
|
|
|
|
// Show context menu
|
|
el.classList.add('jcontextmenu-focus');
|
|
|
|
// Current
|
|
jSuites.contextmenu.current = obj;
|
|
|
|
// Coordinates
|
|
if ((obj.options.items && obj.options.items.length > 0) || el.children.length) {
|
|
if (e.target) {
|
|
if (e.changedTouches && e.changedTouches[0]) {
|
|
x = e.changedTouches[0].clientX;
|
|
y = e.changedTouches[0].clientY;
|
|
} else {
|
|
var x = e.clientX;
|
|
var y = e.clientY;
|
|
}
|
|
} else {
|
|
var x = e.x;
|
|
var y = e.y;
|
|
}
|
|
|
|
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';
|
|
}
|
|
}
|
|
}
|
|
|
|
obj.isOpened = function() {
|
|
return el.classList.contains('jcontextmenu-focus') ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Close menu
|
|
*/
|
|
obj.close = function() {
|
|
if (el.classList.contains('jcontextmenu-focus')) {
|
|
el.classList.remove('jcontextmenu-focus');
|
|
}
|
|
jSuites.tracking(obj, false);
|
|
}
|
|
|
|
/**
|
|
* Create items based on the declared objectd
|
|
* @param {object} items - List of object
|
|
*/
|
|
obj.create = function(items) {
|
|
// Update content
|
|
el.innerHTML = '';
|
|
|
|
// Add header contextmenu
|
|
var itemHeader = createHeader();
|
|
el.appendChild(itemHeader);
|
|
|
|
// Append items
|
|
for (var i = 0; i < items.length; i++) {
|
|
var itemContainer = createItemElement(items[i]);
|
|
el.appendChild(itemContainer);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* createHeader for context menu
|
|
* @private
|
|
* @returns {HTMLElement}
|
|
*/
|
|
function createHeader() {
|
|
var header = document.createElement('div');
|
|
header.classList.add("header");
|
|
header.addEventListener("click", function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
});
|
|
var title = document.createElement('a');
|
|
title.classList.add("title");
|
|
title.innerHTML = jSuites.translate("Menu");
|
|
|
|
header.appendChild(title);
|
|
|
|
var closeButton = document.createElement('a');
|
|
closeButton.classList.add("close");
|
|
closeButton.innerHTML = jSuites.translate("close");
|
|
closeButton.addEventListener("click", function(e) {
|
|
obj.close();
|
|
});
|
|
|
|
header.appendChild(closeButton);
|
|
|
|
return header;
|
|
}
|
|
|
|
/**
|
|
* 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(e) {
|
|
// Execute method
|
|
this.method(this, e);
|
|
});
|
|
}
|
|
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);
|
|
}
|
|
|
|
window.addEventListener("mousewheel", function() {
|
|
obj.close();
|
|
});
|
|
|
|
el.contextmenu = obj;
|
|
|
|
return obj;
|
|
});
|
|
|
|
|
|
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) {
|
|
// Reset current value
|
|
resetValue();
|
|
|
|
// Make sure the content container is blank
|
|
content.innerHTML = '';
|
|
|
|
// Reset
|
|
obj.header.value = '';
|
|
|
|
// Reset items and values
|
|
obj.items = [];
|
|
|
|
// Prepare data
|
|
if (data && 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]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Append data
|
|
obj.appendData(data);
|
|
|
|
// Update data
|
|
obj.options.data = data;
|
|
} else {
|
|
// Update data
|
|
obj.options.data = [];
|
|
}
|
|
|
|
obj.close();
|
|
}
|
|
|
|
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) {
|
|
// Lemonade JS
|
|
if (el.value != obj.options.value) {
|
|
el.value = obj.options.value;
|
|
if (typeof(el.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
target: el,
|
|
value: el.value
|
|
});
|
|
}
|
|
}
|
|
|
|
// Events
|
|
if (typeof(obj.options.onchange) == 'function') {
|
|
obj.options.onchange(el, obj, oldValue, obj.options.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) {
|
|
// New instance
|
|
var obj = { type:'editor' };
|
|
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,
|
|
userSearch: 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.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
target: el,
|
|
value: el.value
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create node
|
|
var createUserSearchNode = function() {
|
|
// Get coordinates from caret
|
|
var sel = window.getSelection ? window.getSelection() : document.selection;
|
|
var range = sel.getRangeAt(0);
|
|
range.deleteContents();
|
|
// Append text node
|
|
var input = document.createElement('a');
|
|
input.innerText = '@';
|
|
input.searchable = true;
|
|
range.insertNode(input);
|
|
var node = range.getBoundingClientRect();
|
|
range.collapse(false);
|
|
// Position
|
|
userSearch.style.position = 'fixed';
|
|
userSearch.style.top = node.top + node.height + 10 + 'px';
|
|
userSearch.style.left = node.left + 2 + 'px';
|
|
}
|
|
|
|
/**
|
|
* 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(o) {
|
|
if (typeof(o) == 'object') {
|
|
editor.innerHTML = o.content;
|
|
} else {
|
|
editor.innerHTML = o;
|
|
}
|
|
|
|
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]]);
|
|
}
|
|
}
|
|
|
|
// Users
|
|
if (userSearch) {
|
|
// Get tag users
|
|
var tagged = editor.querySelectorAll('a[data-user]');
|
|
if (tagged.length) {
|
|
data.users = [];
|
|
for (var i = 0; i < tagged.length; i++) {
|
|
var userId = tagged[i].getAttribute('data-user');
|
|
if (userId) {
|
|
data.users.push(userId);
|
|
}
|
|
}
|
|
data.users = data.users.join(',');
|
|
}
|
|
}
|
|
|
|
// Get content
|
|
var d = document.createElement('div');
|
|
d.innerHTML = editor.innerHTML;
|
|
var s = d.querySelector('.jsnippet');
|
|
if (s) {
|
|
s.remove();
|
|
}
|
|
|
|
var text = d.innerHTML;
|
|
text = text.replace(/<br>/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);
|
|
editor.removeEventListener('blur', editorBlur);
|
|
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 = '<div><br></div>';
|
|
}
|
|
|
|
if (userSearch) {
|
|
var t = jSuites.getNode();
|
|
if (t) {
|
|
if (t.searchable === true) {
|
|
if (t.innerText && t.innerText.substr(0,1) == '@') {
|
|
userSearchInstance(t.innerText.substr(1));
|
|
}
|
|
} else if (t.searchable === false) {
|
|
if (t.innerText !== t.getAttribute('data-label')) {
|
|
t.searchable = true;
|
|
t.removeAttribute('href');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 (userSearch) {
|
|
if (e.key == '@') {
|
|
createUserSearchNode(editor);
|
|
e.preventDefault();
|
|
} else {
|
|
if (userSearchInstance.isOpened()) {
|
|
userSearchInstance.keydown(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
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 '<div>' + v + '</div>';
|
|
});
|
|
document.execCommand('insertHtml', false, html.join(''));
|
|
}
|
|
} else {
|
|
var d = filter(html);
|
|
// Paste to the editor
|
|
//insertNodeAtCaret(d);
|
|
document.execCommand('insertHtml', false, d.innerHTML);
|
|
}
|
|
}
|
|
|
|
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) {
|
|
if (userSearch && userSearchInstance.isOpened()) {
|
|
userSearchInstance.close();
|
|
}
|
|
|
|
// 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
|
|
});
|
|
}
|
|
|
|
// Add user search
|
|
var userSearch = null;
|
|
var userSearchInstance = null;
|
|
if (obj.options.userSearch) {
|
|
userSearch = document.createElement('div');
|
|
el.appendChild(userSearch);
|
|
|
|
// Component
|
|
userSearchInstance = jSuites.search(userSearch, {
|
|
data: obj.options.userSearch,
|
|
placeholder: jSuites.translate('Type the name a user'),
|
|
onselect: function(a,b,c,d) {
|
|
if (userSearchInstance.isOpened()) {
|
|
var t = jSuites.getNode();
|
|
if (t && t.searchable == true && (t.innerText.trim() && t.innerText.substr(1))) {
|
|
t.innerText = '@' + c;
|
|
t.href = '/' + c;
|
|
t.setAttribute('data-user', d);
|
|
t.setAttribute('data-label', t.innerText);
|
|
t.searchable = false;
|
|
jSuites.focus(t);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 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('<br>');
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Check the form
|
|
obj.getError = function() {
|
|
// Validation
|
|
return obj.validation() ? true : false;
|
|
}
|
|
|
|
// Return the form hash
|
|
obj.setHash = function() {
|
|
return obj.getHash(jSuites.form.getElements(el));
|
|
}
|
|
|
|
// Get the form hash
|
|
obj.getHash = function(str) {
|
|
var hash = 0, i, chr;
|
|
|
|
if (str.length === 0) {
|
|
return hash;
|
|
} else {
|
|
for (i = 0; i < str.length; i++) {
|
|
chr = str.charCodeAt(i);
|
|
hash = ((hash << 5) - hash) + chr;
|
|
hash |= 0;
|
|
}
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
// Is there any change in the form since start tracking?
|
|
obj.isChanged = function() {
|
|
var hash = obj.setHash();
|
|
return (obj.options.currentHash != hash);
|
|
}
|
|
|
|
// Restart tracking
|
|
obj.resetTracker = function() {
|
|
obj.options.currentHash = obj.setHash();
|
|
obj.options.ignore = false;
|
|
}
|
|
|
|
// 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.type == 'file') {
|
|
value = element.files;
|
|
} 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 (type == 'file') {
|
|
// Do nothing
|
|
} 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) {
|
|
if (typeof(num) === 'string') {
|
|
num = num.trim();
|
|
}
|
|
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 = {
|
|
// Text
|
|
text: [ '@' ],
|
|
// 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('#{1}(.{1})#+', 'ig');
|
|
var t = e.exec(v);
|
|
if (t && t[1] && t[1].length == 1) {
|
|
if (t[1] === ',') {
|
|
this.options.decimal = '.';
|
|
} else {
|
|
this.options.decimal = ',';
|
|
}
|
|
} else {
|
|
this.options.decimal = '1.1'.toLocaleString().substring(1,2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
// Signal
|
|
var signal = v[0].match(/[-]+/g);
|
|
if (signal && signal.length) {
|
|
signal = true;
|
|
} else {
|
|
signal = false;
|
|
}
|
|
|
|
v[0] = v[0].match(/[0-9]+/g);
|
|
|
|
if (v[0]) {
|
|
if (signal) {
|
|
v[0].unshift('-');
|
|
}
|
|
v[0] = v[0].join('');
|
|
} else {
|
|
if (signal) {
|
|
v[0] = '-';
|
|
}
|
|
}
|
|
|
|
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, event) {
|
|
if (v == '') {
|
|
return '';
|
|
}
|
|
// Get decimal
|
|
var d = getDecimal.call(this);
|
|
// Convert value
|
|
var o = this.options;
|
|
// Parse value
|
|
v = ParseValue.call(this, v);
|
|
if (v == '') {
|
|
return '';
|
|
}
|
|
// Temporary value
|
|
if (v[0]) {
|
|
var t = parseFloat(v[0] + '.1');
|
|
if (o.style == 'percent') {
|
|
t /= 100;
|
|
}
|
|
} else {
|
|
var t = null;
|
|
}
|
|
|
|
if ((v[0] == '-' || v[0] == '-00') && ! v[1] && (event && event.inputType == "deleteContentBackward")) {
|
|
return '';
|
|
}
|
|
|
|
var n = new Intl.NumberFormat(this.locale, o).format(t);
|
|
n = n.split(d);
|
|
if (typeof(n[1]) !== 'undefined') {
|
|
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, event) {
|
|
var v = Value.call(e);
|
|
if (! v) {
|
|
return;
|
|
}
|
|
|
|
// Get decimal
|
|
var d = getDecimal.call(this);
|
|
var n = FormatValue.call(this, v, event);
|
|
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) {
|
|
// Negative values
|
|
if (current[0] === '-') {
|
|
current[0] = '-0';
|
|
}
|
|
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();
|
|
|
|
if (this.childNodes[0]) {
|
|
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) {
|
|
var v = this.innerText;
|
|
if (this.value && this.value.length > v.length) {
|
|
v = this.value;
|
|
}
|
|
return v;
|
|
} 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) {
|
|
// Jump number of chars
|
|
var t = (a[pos].length - this.values[this.index].length) - 1;
|
|
this.position += t;
|
|
|
|
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) {
|
|
// Replace the zero for a number
|
|
if (this.values[this.index] == '0' && v > 0) {
|
|
this.values[this.index] = '';
|
|
} else if (this.values[this.index] == '-0' && v > 0) {
|
|
this.values[this.index] = '-';
|
|
}
|
|
// Don't add up zeros because does not mean anything here
|
|
if ((this.values[this.index] != '0' && 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);
|
|
},
|
|
'@': function(v) {
|
|
if (isBlank(this.values[this.index])) {
|
|
this.values[this.index] = '';
|
|
}
|
|
this.values[this.index] += 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.text, 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 == 'text') {
|
|
var types = [ 'text' ];
|
|
} 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 fixes
|
|
if (o.mask) {
|
|
// Remove []
|
|
o.mask = o.mask.replace(new RegExp(/\[h]/),'|h|');
|
|
o.mask = o.mask.replace(new RegExp(/\[.*?\]/),'');
|
|
o.mask = o.mask.replace(new RegExp(/\|h\|/),'[h]');
|
|
if (o.mask.indexOf(';') !== -1) {
|
|
var t = o.mask.split(';');
|
|
o.mask = t[0];
|
|
}
|
|
// Excel mask TODO: Improve
|
|
if (o.mask.indexOf('##') !== -1) {
|
|
var d = o.mask.split(';');
|
|
if (d[0]) {
|
|
d[0] = d[0].replace('*', '\t');
|
|
d[0] = d[0].replace(new RegExp(/_-/g), ' ');
|
|
d[0] = d[0].replace(new RegExp(/_/g), '');
|
|
d[0] = d[0].replace('##0.###','##0.000');
|
|
d[0] = d[0].replace('##0.##','##0.00');
|
|
d[0] = d[0].replace('##0.#','##0.0');
|
|
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.indexOf('insert') || ! e.inputType.indexOf('delete')) {
|
|
// Start transformation
|
|
if (o.locale) {
|
|
if (o.input) {
|
|
Format.call(o, o.input, e);
|
|
} 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 appropriate parser
|
|
parse.call(o);
|
|
}
|
|
|
|
// New value
|
|
var newValue = o.values.join('');
|
|
|
|
// Add tokens to the end of string only if string is not empty
|
|
if (isNumeric(o.type) && newValue !== '') {
|
|
// 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
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the type of the mask
|
|
obj.getType = getType;
|
|
|
|
// 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: mask, decimal: decimal });
|
|
}
|
|
|
|
/**
|
|
* Extract number from masked string
|
|
*/
|
|
obj.extract = function(v, options, returnObject) {
|
|
if (isBlank(v)) {
|
|
return v;
|
|
}
|
|
if (typeof(options) != 'object') {
|
|
return value;
|
|
} else {
|
|
options = Object.assign({}, options);
|
|
|
|
if (! options.options) {
|
|
options.options = {};
|
|
}
|
|
}
|
|
|
|
// Compatibility
|
|
if (! options.mask && options.format) {
|
|
options.mask = options.format;
|
|
}
|
|
|
|
// Remove []
|
|
if (options.mask) {
|
|
if (options.mask.indexOf(';') !== -1) {
|
|
var t = options.mask.split(';');
|
|
options.mask = t[0];
|
|
}
|
|
options.mask = options.mask.replace(new RegExp(/\[.*?\]/),'');
|
|
}
|
|
|
|
// 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 === 'general') {
|
|
var o = obj(v, options, true);
|
|
|
|
value = v;
|
|
} else if (type === 'datetime') {
|
|
if (v instanceof Date) {
|
|
var t = jSuites.calendar.getDateString(value, options.mask);
|
|
}
|
|
|
|
var o = obj(v, options, true);
|
|
|
|
if (jSuites.isNumeric(v)) {
|
|
value = v;
|
|
} else {
|
|
var value = getDate.call(o);
|
|
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 (! o.type && type) {
|
|
o.type = type;
|
|
}
|
|
|
|
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 {
|
|
options = Object.assign({}, options);
|
|
|
|
if (! options.options) {
|
|
options.options = {};
|
|
}
|
|
}
|
|
|
|
// Compatibility
|
|
if (! options.mask && options.format) {
|
|
options.mask = options.format;
|
|
}
|
|
|
|
// Remove []
|
|
if (options.mask) {
|
|
if (options.mask.indexOf(';') !== -1) {
|
|
var t = options.mask.split(';');
|
|
options.mask = t[0];
|
|
}
|
|
options.mask = options.mask.replace(new RegExp(/\[h]/),'|h|');
|
|
options.mask = options.mask.replace(new RegExp(/\[.*?\]/),'');
|
|
options.mask = options.mask.replace(new RegExp(/\|h\|/),'[h]');
|
|
}
|
|
|
|
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 d = getDecimal.call(options, options.mask);
|
|
if (options.mask.indexOf(d) !== -1) {
|
|
d = options.mask.split(d);
|
|
d = (''+d[1].match(/[0-9]+/g))
|
|
d = d.length;
|
|
t = value.toFixed(d);
|
|
} else {
|
|
t = value.toFixed(0);
|
|
}
|
|
} else if (options.locale && fullMask) {
|
|
// Append zeros
|
|
var d = (''+value).split('.');
|
|
if (options.options) {
|
|
if (typeof(d[1]) === 'undefined') {
|
|
d[1] = '';
|
|
}
|
|
var len = d[1].length;
|
|
if (options.options.minimumFractionDigits > len) {
|
|
for (var i = 0; i < options.options.minimumFractionDigits - len; i++) {
|
|
d[1] += '0';
|
|
}
|
|
}
|
|
}
|
|
if (! d[1].length) {
|
|
t = d[0]
|
|
} else {
|
|
t = d.join('.');
|
|
}
|
|
var len = d[1].length;
|
|
if (options.options && options.options.maximumFractionDigits < len) {
|
|
t = parseFloat(t).toFixed(options.options.maximumFractionDigits);
|
|
}
|
|
} 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);
|
|
|
|
// Numeric mask, number of zeros
|
|
if (fullMask && type === 'numeric') {
|
|
var maskZeros = options.mask.match(new RegExp(/^[0]+$/gm));
|
|
if (maskZeros && maskZeros.length === 1) {
|
|
var maskLength = maskZeros[0].length;
|
|
if (maskLength > 3) {
|
|
value = '' + value;
|
|
while (value.length < maskLength) {
|
|
value = '0' + value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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,
|
|
backdrop: 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];
|
|
}
|
|
}
|
|
|
|
// 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
|
|
if (obj.options.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 {
|
|
if (obj.options.backdrop) {
|
|
backdrop.style.display = 'block';
|
|
}
|
|
}
|
|
// 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() {
|
|
if (obj.isOpen()) {
|
|
el.style.display = 'none';
|
|
if (obj.options.backdrop) {
|
|
// Backdrop
|
|
backdrop.style.display = '';
|
|
}
|
|
// 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) {
|
|
// Position
|
|
var tracker = null;
|
|
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.which == 27) {
|
|
var modals = document.querySelectorAll('.jmodal');
|
|
for (var i = 0; i < modals.length; i++) {
|
|
modals[i].parentNode.modal.close();
|
|
}
|
|
}
|
|
});
|
|
|
|
document.addEventListener('mouseup', function(e) {
|
|
var item = jSuites.findElement(e.target, 'jmodal');
|
|
if (item) {
|
|
// Get target info
|
|
var rect = item.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) {
|
|
item.parentNode.modal.close();
|
|
}
|
|
}
|
|
|
|
if (tracker) {
|
|
tracker.element.style.cursor = 'auto';
|
|
tracker = null;
|
|
}
|
|
});
|
|
|
|
document.addEventListener('mousedown', function(e) {
|
|
var item = jSuites.findElement(e.target, 'jmodal');
|
|
if (item) {
|
|
// Get target info
|
|
var rect = item.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) {
|
|
// Do nothing
|
|
} else {
|
|
if (e.target.getAttribute('title') && (y - rect.top) < 50) {
|
|
if (document.selection) {
|
|
document.selection.empty();
|
|
} else if ( window.getSelection ) {
|
|
window.getSelection().removeAllRanges();
|
|
}
|
|
|
|
tracker = {
|
|
left: rect.left,
|
|
top: rect.top,
|
|
x: e.clientX,
|
|
y: e.clientY,
|
|
width: rect.width,
|
|
height: rect.height,
|
|
element: item,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
document.addEventListener('mousemove', function(e) {
|
|
if (tracker) {
|
|
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) {
|
|
tracker.element.style.top = (tracker.top + (e.clientY - tracker.y) + (tracker.height / 2)) + 'px';
|
|
tracker.element.style.left = (tracker.left + (e.clientX - tracker.x) + (tracker.width / 2)) + 'px';
|
|
tracker.element.style.cursor = 'move';
|
|
} else {
|
|
tracker.element.style.cursor = 'auto';
|
|
}
|
|
}
|
|
});
|
|
|
|
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.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() {
|
|
/**
|
|
* Available palettes
|
|
*/
|
|
var 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" ],
|
|
],
|
|
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"],
|
|
],
|
|
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"],
|
|
],
|
|
chart: [
|
|
['#C1D37F','#4C5454','#FFD275','#66586F','#D05D5B','#C96480','#95BF8F','#6EA240','#0F0F0E','#EB8258','#95A3B3','#995D81'],
|
|
],
|
|
}
|
|
|
|
/**
|
|
* Get a pallete
|
|
*/
|
|
var component = function(o) {
|
|
// Otherwise get palette value
|
|
if (palette[o]) {
|
|
return palette[o];
|
|
} else {
|
|
return palette.material;
|
|
}
|
|
}
|
|
|
|
component.get = function(o) {
|
|
// Otherwise get palette value
|
|
if (palette[o]) {
|
|
return palette[o];
|
|
} else {
|
|
return palette;
|
|
}
|
|
}
|
|
|
|
component.set = function(o, v) {
|
|
palette[o] = v;
|
|
}
|
|
|
|
return component;
|
|
})();
|
|
|
|
|
|
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.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
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 = '<i class="material-icons">' + obj.options.content + '</i>';
|
|
} 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 top = 0;
|
|
var left = 0;
|
|
|
|
dropdownContent.style.marginLeft = '';
|
|
|
|
var rectHeader = dropdownHeader.getBoundingClientRect();
|
|
var rectContent = dropdownContent.getBoundingClientRect();
|
|
|
|
if (window.innerHeight < rectHeader.bottom + rectContent.height) {
|
|
top = -1 * (rectContent.height + 4);
|
|
} else {
|
|
top = rectHeader.height + 4;
|
|
}
|
|
|
|
if (obj.options.right === true) {
|
|
left = -1 * rectContent.width + rectHeader.width;
|
|
}
|
|
|
|
if (rectContent.left + left < 0) {
|
|
left = left + rectContent.left + 10;
|
|
}
|
|
if (rectContent.left + rectContent.width > window.innerWidth) {
|
|
left = -1 * (10 + rectContent.left + rectContent.width - window.innerWidth);
|
|
}
|
|
|
|
dropdownContent.style.marginTop = parseInt(top) + 'px';
|
|
dropdownContent.style.marginLeft = parseInt(left) + 'px';
|
|
|
|
//dropdownContent.style.marginTop
|
|
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, e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
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.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
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,
|
|
searchByNode: options.searchByNode || null,
|
|
onselect: options.onselect || null,
|
|
forceSelect: options.forceSelect,
|
|
onbeforesearch: options.onbeforesearch || null,
|
|
};
|
|
|
|
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.searchByNode) {
|
|
if (obj.options.input.tagName === 'DIV') {
|
|
var terms = obj.options.input.innerText;
|
|
} else {
|
|
var terms = obj.options.input.value;
|
|
}
|
|
} else {
|
|
// Current node
|
|
var node = jSuites.getNode();
|
|
if (node) {
|
|
var terms = node.innerText;
|
|
}
|
|
}
|
|
|
|
if (typeof(obj.options.onbeforesearch) == 'function') {
|
|
var ret = obj.options.onbeforesearch(obj, terms);
|
|
if (ret) {
|
|
terms = ret;
|
|
} else {
|
|
if (ret === false) {
|
|
// Ignore event
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
obj(terms);
|
|
}
|
|
|
|
// 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) {
|
|
setTimeout(function() {
|
|
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';
|
|
}
|
|
}, 150);
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
setBorder();
|
|
|
|
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]);
|
|
|
|
setBorder();
|
|
}
|
|
|
|
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,
|
|
onbeforepaste: 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 = '<div></div>';
|
|
// 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.oninput) == 'function') {
|
|
el.oninput({
|
|
type: 'input',
|
|
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 = '<div></div>';
|
|
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 (typeof(obj.options.onbeforepaste) == 'function') {
|
|
var ret = obj.options.onbeforepaste(el, obj, data);
|
|
if (ret === false) {
|
|
e.preventDefault();
|
|
return false;
|
|
} else {
|
|
if (ret) {
|
|
data = ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (data.length > 1) {
|
|
obj.add(data, true);
|
|
e.preventDefault();
|
|
} else if (data[0]) {
|
|
document.execCommand('insertText', false, data[0])
|
|
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,
|
|
bottom: true,
|
|
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);
|
|
}
|
|
}
|
|
for (var i = 0; i < toolbarFloating.children.length; i++) {
|
|
// Toolbar element
|
|
var toolbarItem = toolbarFloating.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
|
|
setTimeout(function() {
|
|
obj.refresh();
|
|
}, 0);
|
|
}
|
|
|
|
obj.open = function() {
|
|
toolbarArrow.classList.add('jtoolbar-arrow-selected');
|
|
|
|
var rectElement = el.getBoundingClientRect();
|
|
var rect = toolbarFloating.getBoundingClientRect();
|
|
if (rect.bottom > window.innerHeight || obj.options.bottom) {
|
|
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;
|
|
}
|
|
// Available parent space
|
|
var available = parseInt(obj.options.maxWidth);
|
|
// Remove arrow
|
|
if (toolbarArrow.parentNode) {
|
|
toolbarArrow.parentNode.removeChild(toolbarArrow);
|
|
}
|
|
// Move all items to the toolbar
|
|
while (toolbarFloating.firstChild) {
|
|
toolbarContent.appendChild(toolbarFloating.firstChild);
|
|
}
|
|
// 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
obj.setReadonly = function(state) {
|
|
state = state ? 'add' : 'remove';
|
|
el.classList[state]('jtoolbar-readonly');
|
|
}
|
|
|
|
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() {
|
|
/**
|
|
* Options: Object,
|
|
* Properties:
|
|
* Constraint,
|
|
* Reference,
|
|
* Value
|
|
*/
|
|
|
|
var isNumeric = function(num) {
|
|
return !isNaN(num) && num !== null && num !== '';
|
|
}
|
|
|
|
var numberCriterias = {
|
|
'between': function(value, range) {
|
|
return value >= range[0] && value <= range[1];
|
|
},
|
|
'not between': function(value, range) {
|
|
return value < range[0] || value > range[1];
|
|
},
|
|
'<': function(value, range) {
|
|
return value < range[0];
|
|
},
|
|
'<=': function(value, range) {
|
|
return value <= range[0];
|
|
},
|
|
'>': function(value, range) {
|
|
return value > range[0];
|
|
},
|
|
'>=': function(value, range) {
|
|
return value >= range[0];
|
|
},
|
|
'=': function(value, range) {
|
|
return value == range[0];
|
|
},
|
|
'!=': function(value, range) {
|
|
return value != range[0];
|
|
},
|
|
}
|
|
|
|
var dateCriterias = {
|
|
'valid date': function() {
|
|
return true;
|
|
},
|
|
'=': function(value, range) {
|
|
return value === range[0];
|
|
},
|
|
'<': function(value, range) {
|
|
return value < range[0];
|
|
},
|
|
'<=': function(value, range) {
|
|
return value <= range[0];
|
|
},
|
|
'>': function(value, range) {
|
|
return value > range[0];
|
|
},
|
|
'>=': function(value, range) {
|
|
return value >= range[0];
|
|
},
|
|
'between': function(value, range) {
|
|
return value >= range[0] && value <= range[1];
|
|
},
|
|
'not between': function(value, range) {
|
|
return value < range[0] || value > range[1];
|
|
},
|
|
}
|
|
|
|
var textCriterias = {
|
|
'contains': function(value, range) {
|
|
return value.includes(range[0]);
|
|
},
|
|
'not contains': function(value, range) {
|
|
return !value.includes(range[0]);
|
|
},
|
|
'begins with': function(value, range) {
|
|
return value.startsWith(range[0]);
|
|
},
|
|
'ends with': function(value, range) {
|
|
return value.endsWith(range[0]);
|
|
},
|
|
'=': function(value, range) {
|
|
return value === range[0];
|
|
},
|
|
'valid email': function(value) {
|
|
var pattern = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
|
|
|
|
return pattern.test(value);
|
|
},
|
|
'valid url': function(value) {
|
|
var pattern = new RegExp(/(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig);
|
|
|
|
return pattern.test(value);
|
|
},
|
|
}
|
|
|
|
// Component router
|
|
var component = function(value, options) {
|
|
if (typeof(component[options.type]) === 'function') {
|
|
if (options.allowBlank && value === '') {
|
|
return true;
|
|
}
|
|
|
|
return component[options.type](value, options);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
component.url = function() {
|
|
var pattern = new RegExp(/(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig);
|
|
return pattern.test(data) ? true : false;
|
|
}
|
|
|
|
component.email = function(data) {
|
|
var pattern = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
|
|
return data && pattern.test(data) ? true : false;
|
|
}
|
|
|
|
component.required = function(data) {
|
|
return data.trim() ? true : false;
|
|
}
|
|
|
|
component.exist = function(data, options) {
|
|
return !!data.toString();
|
|
}
|
|
|
|
component['not exist'] = function(data, options) {
|
|
return !data.toString();
|
|
}
|
|
|
|
component.number = function(data, options) {
|
|
if (! isNumeric(data)) {
|
|
return false;
|
|
}
|
|
|
|
if (!options || !options.criteria) {
|
|
return true;
|
|
}
|
|
|
|
if (!numberCriterias[options.criteria]) {
|
|
return false;
|
|
}
|
|
|
|
var values = options.value.map(function(num) {
|
|
return parseFloat(num);
|
|
})
|
|
|
|
return numberCriterias[options.criteria](data, values);
|
|
};
|
|
|
|
component.login = function(data) {
|
|
var pattern = new RegExp(/^[a-zA-Z0-9\_\-\.\s+]+$/);
|
|
return data && pattern.test(data) ? true : false;
|
|
}
|
|
|
|
component.list = function(data, options) {
|
|
var dataType = typeof data;
|
|
if (dataType !== 'string' && dataType !== 'number') {
|
|
return false;
|
|
}
|
|
if (typeof(options.value[0]) === 'string') {
|
|
var list = options.value[0].split(',');
|
|
} else {
|
|
var list = options.value[0];
|
|
}
|
|
|
|
var validOption = list.findIndex(function name(item) {
|
|
return item == data;
|
|
});
|
|
|
|
return validOption > -1;
|
|
}
|
|
|
|
component.date = function(data, options) {
|
|
if (new Date(data) == 'Invalid Date') {
|
|
return false;
|
|
}
|
|
|
|
if (!options || !options.criteria) {
|
|
return true;
|
|
}
|
|
|
|
if (!dateCriterias[options.criteria]) {
|
|
return false;
|
|
}
|
|
|
|
var values = options.value.map(function(date) {
|
|
return new Date(date).getTime();
|
|
});
|
|
|
|
return dateCriterias[options.criteria](new Date(data).getTime(), values);
|
|
}
|
|
|
|
component.text = function(data, options) {
|
|
if (typeof data !== 'string') {
|
|
return false;
|
|
}
|
|
|
|
if (!options || !options.criteria) {
|
|
return true;
|
|
}
|
|
|
|
if (!textCriterias[options.criteria]) {
|
|
return false;
|
|
}
|
|
|
|
return textCriterias[options.criteria](data, options.value);
|
|
}
|
|
|
|
component.textLength = function(data, options) {
|
|
data = data.toString();
|
|
|
|
return component.number(data.length, options);
|
|
}
|
|
|
|
return component;
|
|
})();
|
|
|
|
|
|
|
|
return jSuites;
|
|
|
|
}))); |