discourse-table-builder/assets/vendor/jsuites.js

12268 lines
393 KiB
JavaScript
Raw Normal View History

/**
* (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 = "&#9658;";
itemContainer.appendChild(itemIconSubmenu);
itemContainer.classList.add('jcontexthassubmenu');
var el_submenu = document.createElement('div');
// Class definition
el_submenu.classList.add('jcontextmenu');
// Focusable
el_submenu.setAttribute('tabindex', '900');
// Append items
var submenu = item.submenu;
for (var i = 0; i < submenu.length; i++) {
var itemContainerSubMenu = createItemElement(submenu[i]);
el_submenu.appendChild(itemContainerSubMenu);
}
itemContainer.appendChild(el_submenu);
} else if (item.shortcut) {
var itemShortCut = document.createElement('span');
itemShortCut.innerHTML = item.shortcut;
itemContainer.appendChild(itemShortCut);
}
}
return itemContainer;
}
if (typeof(obj.options.onclick) == 'function') {
el.addEventListener('click', function(e) {
obj.options.onclick(obj, e);
});
}
// Create items
if (obj.options.items) {
obj.create(obj.options.items);
}
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 || '&nbsp;';
// 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
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;
})));