/** * (c) jSuites Javascript Web Components (v3.7.0) * * Author: Paul Hodel * Website: https://bossanova.uk/jsuites/ * Description: Create amazing web based applications. * * MIT License * */ ;(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.jSuites = factory(); }(this, (function () { 'use strict'; var jSuites = function(options) { var obj = {} obj.init = function() { } return obj; } jSuites.ajax = (function(options, complete) { if (Array.isArray(options)) { // Create multiple request controller var multiple = { instance: [], complete: complete, } if (options.length > 0) { for (var i = 0; i < options.length; i++) { options[i].multiple = multiple; multiple.instance.push(jSuites.ajax(options[i])); } } return multiple; } if (! options.data) { options.data = {}; } if (options.type) { options.method = options.type; } // Default method if (! options.method) { options.method = 'GET'; } // Default type if (! options.dataType) { options.dataType = 'json'; } if (options.data) { // Parse object to variables format var parseData = function(value, key) { var vars = []; var keys = Object.keys(value); if (keys.length) { for (var i = 0; i < keys.length; i++) { if (key) { var k = key + '[' + keys[i] + ']'; } else { var k = keys[i]; } if (typeof(value[keys[i]]) == 'object') { var r = parseData(value[keys[i]], k); var o = Object.keys(r); for (var j = 0; j < o.length; j++) { vars[o[j]] = r[o[j]]; } } else { vars[k] = value[keys[i]]; } } } return vars; } var data = []; var d = parseData(options.data); var k = Object.keys(d); for (var i = 0; i < k.length; i++) { data.push(k[i] + '=' + encodeURIComponent(d[k[i]])); } if (options.method == 'GET' && data.length > 0) { if (options.url.indexOf('?') < 0) { options.url += '?'; } options.url += data.join('&'); } } var httpRequest = new XMLHttpRequest(); httpRequest.open(options.method, options.url, true); httpRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); if (options.method == 'POST') { httpRequest.setRequestHeader('Accept', 'application/json'); httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } else { if (options.dataType == 'json') { httpRequest.setRequestHeader('Content-Type', 'text/json'); } } // No cache if (options.cache != true) { httpRequest.setRequestHeader('pragma', 'no-cache'); httpRequest.setRequestHeader('cache-control', 'no-cache'); } // Authentication if (options.withCredentials == true) { httpRequest.withCredentials = true } // Before send if (typeof(options.beforeSend) == 'function') { options.beforeSend(httpRequest); } httpRequest.onload = function() { if (httpRequest.status === 200) { if (options.dataType == 'json') { try { var result = JSON.parse(httpRequest.responseText); if (options.success && typeof(options.success) == 'function') { options.success(result); } } catch(err) { if (options.error && typeof(options.error) == 'function') { options.error(err, result); } } } else { var result = httpRequest.responseText; if (options.success && typeof(options.success) == 'function') { options.success(result); } } } else { if (options.error && typeof(options.error) == 'function') { options.error(httpRequest.responseText); } } // Global queue if (jSuites.ajax.queue && jSuites.ajax.queue.length > 0) { jSuites.ajax.send(jSuites.ajax.queue.shift()); } // Global complete method if (jSuites.ajax.requests && jSuites.ajax.requests.length) { // Get index of this request in the container var index = jSuites.ajax.requests.indexOf(httpRequest); // Remove from the ajax requests container jSuites.ajax.requests.splice(index, 1); // Last one? if (! jSuites.ajax.requests.length) { if (options.complete && typeof(options.complete) == 'function') { options.complete(result); } } // Controllers if (options.multiple && options.multiple.instance) { // Get index of this request in the container var index = options.multiple.instance.indexOf(httpRequest); // Remove from the ajax requests container options.multiple.instance.splice(index, 1); // If this is the last one call method complete if (! options.multiple.instance.length) { if (options.multiple.complete && typeof(options.multiple.complete) == 'function') { options.multiple.complete(result); } } } } } // Data httpRequest.data = data; // Queue if (options.queue == true && jSuites.ajax.requests.length > 0) { jSuites.ajax.queue.push(httpRequest); } else { jSuites.ajax.send(httpRequest) } return httpRequest; }); jSuites.ajax.send = function(httpRequest) { if (httpRequest.data) { httpRequest.send(httpRequest.data.join('&')); } else { httpRequest.send(); } jSuites.ajax.requests.push(httpRequest); } jSuites.ajax.exists = function(url, __callback) { var http = new XMLHttpRequest(); http.open('HEAD', url, false); http.send(); if (http.status) { __callback(http.status); } } jSuites.ajax.requests = []; jSuites.ajax.queue = []; jSuites.animation = {}; jSuites.animation.slideLeft = function(element, direction, done) { if (direction == true) { element.classList.add('slide-left-in'); setTimeout(function() { element.classList.remove('slide-left-in'); if (typeof(done) == 'function') { done(); } }, 400); } else { element.classList.add('slide-left-out'); setTimeout(function() { element.classList.remove('slide-left-out'); if (typeof(done) == 'function') { done(); } }, 400); } } jSuites.animation.slideRight = function(element, direction, done) { if (direction == true) { element.classList.add('slide-right-in'); setTimeout(function() { element.classList.remove('slide-right-in'); if (typeof(done) == 'function') { done(); } }, 400); } else { element.classList.add('slide-right-out'); setTimeout(function() { element.classList.remove('slide-right-out'); if (typeof(done) == 'function') { done(); } }, 400); } } jSuites.animation.slideTop = function(element, direction, done) { if (direction == true) { element.classList.add('slide-top-in'); setTimeout(function() { element.classList.remove('slide-top-in'); if (typeof(done) == 'function') { done(); } }, 400); } else { element.classList.add('slide-top-out'); setTimeout(function() { element.classList.remove('slide-top-out'); if (typeof(done) == 'function') { done(); } }, 400); } } jSuites.animation.slideBottom = function(element, direction, done) { if (direction == true) { element.classList.add('slide-bottom-in'); setTimeout(function() { element.classList.remove('slide-bottom-in'); if (typeof(done) == 'function') { done(); } }, 400); } else { element.classList.add('slide-bottom-out'); setTimeout(function() { element.classList.remove('slide-bottom-out'); if (typeof(done) == 'function') { done(); } }, 100); } } jSuites.animation.fadeIn = function(element, done) { element.classList.add('fade-in'); setTimeout(function() { element.classList.remove('fade-in'); if (typeof(done) == 'function') { done(); } }, 2000); } jSuites.animation.fadeOut = function(element, done) { element.classList.add('fade-out'); setTimeout(function() { element.classList.remove('fade-out'); if (typeof(done) == 'function') { done(); } }, 1000); } jSuites.calendar = (function(el, options) { var obj = {}; obj.options = {}; // Global container if (! jSuites.calendar.current) { jSuites.calendar.current = null; } // Default configuration var defaults = { // Render type: [ default | year-month-picker ] type: 'default', // Restrictions validRange: null, // Starting weekday - 0 for sunday, 6 for saturday startingDay: null, // Date format format: 'DD/MM/YYYY', // Allow keyboard date entry readonly: true, // Today is default today: false, // Show timepicker time: false, // Show the reset button resetButton: true, // Placeholder placeholder: '', // Translations can be done here months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], monthsFull: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], weekdays: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], weekdays_short: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], textDone: 'Done', textReset: 'Reset', textUpdate: 'Update', // Value value: null, // Fullscreen (this is automatic set for screensize < 800) fullscreen: false, // Create the calendar closed as default opened: false, // Events onopen: null, onclose: null, onchange: null, onupdate: null, // Internal mode controller mode: null, position: null, }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Value if (! obj.options.value) { if (el.tagName == 'INPUT' && el.value) { obj.options.value = el.value; } } // Date obj.date = null; if (obj.options.value) { obj.date = jSuites.calendar.toArray(obj.options.value); } else { if (obj.options.today) { var date = new Date(); var y = date.getFullYear(); var m = date.getMonth() + 1; var d = date.getDate(); var h = date.getHours(); var i = date.getMinutes(); obj.date = [ y, m, d, h, i, 0 ]; } } // Calendar elements var calendarReset = document.createElement('div'); calendarReset.className = 'jcalendar-reset'; calendarReset.innerHTML = obj.options.textReset; var calendarConfirm = document.createElement('div'); calendarConfirm.className = 'jcalendar-confirm'; calendarConfirm.innerHTML = obj.options.textDone; var calendarControls = document.createElement('div'); calendarControls.className = 'jcalendar-controls' calendarControls.style.borderBottom = '1px solid #ddd'; if (obj.options.resetButton) { calendarControls.appendChild(calendarReset); } calendarControls.appendChild(calendarConfirm); var calendarContainer = document.createElement('div'); calendarContainer.className = 'jcalendar-container'; var calendarContent = document.createElement('div'); calendarContent.className = 'jcalendar-content'; calendarContainer.appendChild(calendarContent); // Main element if (el.tagName == 'DIV') { var calendar = el; calendar.className = 'jcalendar-inline'; } else { // Add controls to the screen calendarContent.appendChild(calendarControls); var calendar = document.createElement('div'); calendar.className = 'jcalendar'; } calendar.appendChild(calendarContainer); // Table container var calendarTableContainer = document.createElement('div'); calendarTableContainer.className = 'jcalendar-table'; calendarContent.appendChild(calendarTableContainer); // Previous button var calendarHeaderPrev = document.createElement('td'); calendarHeaderPrev.setAttribute('colspan', '2'); calendarHeaderPrev.className = 'jcalendar-prev'; // Header with year and month var calendarLabelYear = document.createElement('span'); calendarLabelYear.className = 'jcalendar-year'; var calendarLabelMonth = document.createElement('span'); calendarLabelMonth.className = 'jcalendar-month'; var calendarHeaderTitle = document.createElement('td'); calendarHeaderTitle.className = 'jcalendar-header'; calendarHeaderTitle.setAttribute('colspan', '3'); calendarHeaderTitle.appendChild(calendarLabelMonth); calendarHeaderTitle.appendChild(calendarLabelYear); var calendarHeaderNext = document.createElement('td'); calendarHeaderNext.setAttribute('colspan', '2'); calendarHeaderNext.className = 'jcalendar-next'; var calendarHeaderRow = document.createElement('tr'); calendarHeaderRow.appendChild(calendarHeaderPrev); calendarHeaderRow.appendChild(calendarHeaderTitle); calendarHeaderRow.appendChild(calendarHeaderNext); var calendarHeader = document.createElement('thead'); calendarHeader.appendChild(calendarHeaderRow); var calendarBody = document.createElement('tbody'); var calendarFooter = document.createElement('tfoot'); // Calendar table var calendarTable = document.createElement('table'); calendarTable.setAttribute('cellpadding', '0'); calendarTable.setAttribute('cellspacing', '0'); calendarTable.appendChild(calendarHeader); calendarTable.appendChild(calendarBody); calendarTable.appendChild(calendarFooter); calendarTableContainer.appendChild(calendarTable); var calendarSelectHour = document.createElement('select'); calendarSelectHour.className = 'jcalendar-select'; calendarSelectHour.onchange = function() { obj.date[3] = this.value; // Event if (typeof(obj.options.onupdate) == 'function') { obj.options.onupdate(el, obj.getValue()); } } for (var i = 0; i < 24; i++) { var element = document.createElement('option'); element.value = i; element.innerHTML = jSuites.two(i); calendarSelectHour.appendChild(element); } var calendarSelectMin = document.createElement('select'); calendarSelectMin.className = 'jcalendar-select'; calendarSelectMin.onchange = function() { obj.date[4] = this.value; // Event if (typeof(obj.options.onupdate) == 'function') { obj.options.onupdate(el, obj.getValue()); } } for (var i = 0; i < 60; i++) { var element = document.createElement('option'); element.value = i; element.innerHTML = jSuites.two(i); calendarSelectMin.appendChild(element); } // Footer controls var calendarControlsFooter = document.createElement('div'); calendarControlsFooter.className = 'jcalendar-controls'; var calendarControlsTime = document.createElement('div'); calendarControlsTime.className = 'jcalendar-time'; calendarControlsTime.style.maxWidth = '140px'; calendarControlsTime.appendChild(calendarSelectHour); calendarControlsTime.appendChild(calendarSelectMin); var calendarControlsUpdateButton = document.createElement('input'); calendarControlsUpdateButton.setAttribute('type', 'button'); calendarControlsUpdateButton.className = 'jcalendar-update'; calendarControlsUpdateButton.value = obj.options.textUpdate; var calendarControlsUpdate = document.createElement('div'); calendarControlsUpdate.style.flexGrow = '10'; calendarControlsUpdate.appendChild(calendarControlsUpdateButton); calendarControlsFooter.appendChild(calendarControlsTime); // Only show the update button for input elements if (el.tagName == 'INPUT') { calendarControlsFooter.appendChild(calendarControlsUpdate); } calendarContent.appendChild(calendarControlsFooter); var calendarBackdrop = document.createElement('div'); calendarBackdrop.className = 'jcalendar-backdrop'; calendar.appendChild(calendarBackdrop); // Update actions button var updateActions = function() { var currentDay = calendar.querySelector('.jcalendar-selected'); if (currentDay && currentDay.classList.contains('jcalendar-disabled')) { calendarControlsUpdateButton.setAttribute('disabled', 'disabled'); calendarSelectHour.setAttribute('disabled', 'disabled'); calendarSelectMin.setAttribute('disabled', 'disabled'); } else { calendarControlsUpdateButton.removeAttribute('disabled'); calendarSelectHour.removeAttribute('disabled'); calendarSelectMin.removeAttribute('disabled'); } } /** * Open the calendar */ obj.open = function (value) { if (! calendar.classList.contains('jcalendar-focus')) { if (! calendar.classList.contains('jcalendar-inline')) { obj.getDays(); // Get content if (obj.options.type == 'year-month-picker') { obj.getMonths(); } // Get time if (obj.options.time) { calendarSelectHour.value = obj.date[3]; calendarSelectMin.value = obj.date[4]; } if (jSuites.calendar.current) { jSuites.calendar.current.close(); } // Current jSuites.calendar.current = obj; // Show calendar calendar.classList.add('jcalendar-focus'); // Get the position of the corner helper if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen) { // Full calendar.classList.add('jcalendar-fullsize'); // Animation jSuites.animation.slideBottom(calendarContent, 1); } else { var rect = el.getBoundingClientRect(); var rectContent = calendarContent.getBoundingClientRect(); if (obj.options.position) { calendarContainer.style.position = 'fixed'; if (window.innerHeight < rect.bottom + rectContent.height) { calendarContainer.style.top = (rect.top - (rectContent.height + 2)) + 'px'; } else { calendarContainer.style.top = (rect.top + rect.height + 2) + 'px'; } calendarContainer.style.left = rect.left + 'px'; } else { if (window.innerHeight < rect.bottom + rectContent.height) { calendarContainer.style.bottom = (1 * rect.height + rectContent.height + 2) + 'px'; } else { calendarContainer.style.top = 2 + 'px'; } } } // Events if (typeof(obj.options.onopen) == 'function') { obj.options.onopen(el); } } } } obj.close = function (ignoreEvents, update) { if (jSuites.calendar.current) { // Current jSuites.calendar.current = null; if (update !== false) { var element = calendar.querySelector('.jcalendar-selected'); if (typeof(update) == 'string') { var value = update; } else if (element && element.classList.contains('jcalendar-disabled')) { var value = obj.options.value } else { var value = obj.getValue(); } obj.setValue(value); } // Events if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { obj.options.onclose(el); } // Hide calendar.classList.remove('jcalendar-focus'); } return obj.options.value; } obj.prev = function() { // Check if the visualization is the days picker or years picker if (obj.options.mode == 'years') { obj.date[0] = obj.date[0] - 12; // Update picker table of days obj.getYears(); } else if (obj.options.mode == 'months') { obj.date[0] = parseInt(obj.date[0]) - 1; // Update picker table of months obj.getMonths(); } else { // Go to the previous month if (obj.date[1] < 2) { obj.date[0] = obj.date[0] - 1; obj.date[1] = 12; } else { obj.date[1] = obj.date[1] - 1; } // Update picker table of days obj.getDays(); } } obj.next = function() { // Check if the visualization is the days picker or years picker if (obj.options.mode == 'years') { obj.date[0] = parseInt(obj.date[0]) + 12; // Update picker table of days obj.getYears(); } else if (obj.options.mode == 'months') { obj.date[0] = parseInt(obj.date[0]) + 1; // Update picker table of months obj.getMonths(); } else { // Go to the previous month if (obj.date[1] > 11) { obj.date[0] = parseInt(obj.date[0]) + 1; obj.date[1] = 1; } else { obj.date[1] = parseInt(obj.date[1]) + 1; } // Update picker table of days obj.getDays(); } } obj.setValue = function(val) { if (! val) { val = '' + val; } // Values var newValue = val; var oldValue = obj.options.value; if (oldValue != newValue) { // Set label var value = obj.setLabel(newValue, obj.options); var date = newValue.split(' '); if (! date[1]) { date[1] = '00:00:00'; } var time = date[1].split(':') var date = date[0].split('-'); var y = parseInt(date[0]); var m = parseInt(date[1]); var d = parseInt(date[2]); var h = parseInt(time[0]); var i = parseInt(time[1]); obj.date = [ y, m, d, h, i, 0 ]; var val = obj.setLabel(newValue, obj.options); // New value obj.options.value = newValue; // Input value if (el.tagName == 'INPUT') { el.value = val; } // Events if (typeof(el.onchange) == 'function') { el.onchange({ type: 'change', target: el }); } if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, newValue, oldValue); } } obj.getDays(); } obj.getValue = function() { if (obj.date) { if (obj.options.time) { return jSuites.two(obj.date[0]) + '-' + jSuites.two(obj.date[1]) + '-' + jSuites.two(obj.date[2]) + ' ' + jSuites.two(obj.date[3]) + ':' + jSuites.two(obj.date[4]) + ':' + jSuites.two(0); } else { return jSuites.two(obj.date[0]) + '-' + jSuites.two(obj.date[1]) + '-' + jSuites.two(obj.date[2]) + ' ' + jSuites.two(0) + ':' + jSuites.two(0) + ':' + jSuites.two(0); } } else { return ""; } } /** * Calendar */ obj.update = function(element) { if (element.classList.contains('jcalendar-disabled')) { // Do nothing } else { obj.date[2] = element.innerText; var elements = calendar.querySelector('.jcalendar-selected'); if (elements) { elements.classList.remove('jcalendar-selected'); } element.classList.add('jcalendar-selected'); if (! obj.options.time) { obj.close(); } else { obj.date[3] = calendarSelectHour.value; obj.date[4] = calendarSelectMin.value; } // Event if (typeof(obj.options.onupdate) == 'function') { obj.options.onupdate(el, obj.getValue()); } } // Update updateActions(); } /** * Set to blank */ obj.reset = function() { // Close calendar obj.setValue(''); obj.close(false, false); } /** * Get calendar days */ obj.getDays = function() { // Mode obj.options.mode = 'days'; // Setting current values in case of NULLs var date = new Date(); // Current selection var year = obj.date && jSuites.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear()); var month = obj.date && jSuites.isNumeric(obj.date[1]) ? obj.date[1] : parseInt(date.getMonth()) + 1; var day = obj.date && jSuites.isNumeric(obj.date[2]) ? obj.date[2] : parseInt(date.getDate()); var hour = obj.date && jSuites.isNumeric(obj.date[3]) ? obj.date[3] : parseInt(date.getHours()); var min = obj.date && jSuites.isNumeric(obj.date[4]) ? obj.date[4] : parseInt(date.getMinutes()); // Selection container obj.date = [ year, month, day, hour, min, 0 ]; // Update title calendarLabelYear.innerHTML = year; calendarLabelMonth.innerHTML = obj.options.months[month - 1]; // Current month and Year var isCurrentMonthAndYear = (date.getMonth() == month - 1) && (date.getFullYear() == year) ? true : false; var currentDay = date.getDate(); // Number of days in the month var date = new Date(year, month, 0, 0, 0); var numberOfDays = date.getDate(); // First day var date = new Date(year, month-1, 0, 0, 0); var firstDay = date.getDay() + 1; // Index value var index = obj.options.startingDay || 0; // First of day relative to the starting calendar weekday firstDay = firstDay - index; // Reset table calendarBody.innerHTML = ''; // Weekdays Row var row = document.createElement('tr'); row.setAttribute('align', 'center'); calendarBody.appendChild(row); // Create weekdays row for (var i = 0; i < 7; i++) { var cell = document.createElement('td'); cell.classList.add('jcalendar-weekday') cell.innerHTML = obj.options.weekdays_short[index]; row.appendChild(cell); // Next week day index++; // Restart index if (index > 6) { index = 0; } } // Index of days var index = 0; var d = 0; // Calendar table for (var j = 0; j < 6; j++) { // Reset cells container var row = document.createElement('tr'); row.setAttribute('align', 'center'); // Data control var emptyRow = true; // Create cells for (var i = 0; i < 7; i++) { // Create cell var cell = document.createElement('td'); cell.classList.add('jcalendar-set-day'); if (index >= firstDay && index < (firstDay + numberOfDays)) { // Day cell d++; cell.innerHTML = d; // Selected if (d == day) { cell.classList.add('jcalendar-selected'); } // Current selection day is today if (isCurrentMonthAndYear && currentDay == d) { cell.style.fontWeight = 'bold'; } // Current selection day var current = jSuites.calendar.now(new Date(year, month-1, d), true); // Available ranges if (obj.options.validRange) { if (! obj.options.validRange[0] || current >= obj.options.validRange[0]) { var test1 = true; } else { var test1 = false; } if (! obj.options.validRange[1] || current <= obj.options.validRange[1]) { var test2 = true; } else { var test2 = false; } if (! (test1 && test2)) { cell.classList.add('jcalendar-disabled'); } } // Control emptyRow = false; } // Day cell row.appendChild(cell); // Index index++; } // Add cell to the calendar body if (emptyRow == false) { calendarBody.appendChild(row); } } // Show time controls if (obj.options.time) { calendarControlsTime.style.display = ''; } else { calendarControlsTime.style.display = 'none'; } // Update updateActions(); } obj.getMonths = function() { // Mode obj.options.mode = 'months'; // Loading month labels var months = obj.options.months; // Update title calendarLabelYear.innerHTML = obj.date[0]; calendarLabelMonth.innerHTML = ''; // Create months table var html = ''; for (i = 0; i < 12; i++) { if ((i > 0) && (!(i % 4))) { html += ''; } var month = parseInt(i) + 1; html += ''; } html += '
' + months[i] +'
'; calendarBody.innerHTML = html; } obj.getYears = function() { // Mode obj.options.mode = 'years'; // Array of years var y = []; for (i = 0; i < 25; i++) { y[i] = parseInt(obj.date[0]) + (i - 12); } // Assembling the year tables var html = ''; for (i = 0; i < 25; i++) { if ((i > 0) && (!(i % 5))) { html += ''; } html += ''; } html += '
'+ y[i] +'
'; calendarBody.innerHTML = html; } obj.setLabel = function(value, mixed) { return jSuites.calendar.getDateString(value, mixed); } obj.fromFormatted = function (value, format) { return jSuites.calendar.extractDateFromString(value, format); } var mouseUpControls = function(e) { var action = e.target.className; // Object id if (action == 'jcalendar-prev') { obj.prev(); e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-next') { obj.next(); e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-month') { obj.getMonths(); e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-year') { obj.getYears(); e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-set-year') { obj.date[0] = e.target.innerText; if (obj.options.type == 'year-month-picker') { obj.getMonths(); } else { obj.getDays(); } e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-set-month') { obj.date[1] = parseInt(e.target.getAttribute('data-value')); if (obj.options.type == 'year-month-picker') { obj.close(); } else { obj.getDays(); } e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update') { obj.close(); e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-close') { obj.close(); e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-backdrop') { obj.close(false, false); e.stopPropagation(); e.preventDefault(); } else if (action == 'jcalendar-reset') { obj.reset(); e.stopPropagation(); e.preventDefault(); } else if (e.target.classList.contains('jcalendar-set-day')) { if (e.target.innerText) { obj.update(e.target); e.stopPropagation(); e.preventDefault(); } } } var keyUpControls = function(e) { if (e.target.value && e.target.value.length > 3) { var test = jSuites.calendar.extractDateFromString(e.target.value, obj.options.format); if (test) { if (e.target.getAttribute('data-completed') == 'true') { obj.setValue(test); } } } } // Handle events el.addEventListener("keyup", keyUpControls); // Add global events calendar.addEventListener("swipeleft", function(e) { jSuites.animation.slideLeft(calendarTable, 0, function() { obj.next(); jSuites.animation.slideRight(calendarTable, 1); }); e.preventDefault(); e.stopPropagation(); }); calendar.addEventListener("swiperight", function(e) { jSuites.animation.slideRight(calendarTable, 0, function() { obj.prev(); jSuites.animation.slideLeft(calendarTable, 1); }); e.preventDefault(); e.stopPropagation(); }); if ('ontouchend' in document.documentElement === true) { calendar.addEventListener("touchend", mouseUpControls); el.addEventListener("touchend", function(e) { obj.open(); }); } else { calendar.addEventListener("mouseup", mouseUpControls); el.addEventListener("mouseup", function(e) { obj.open(); }); } if (! jSuites.calendar.hasEvents) { if ('ontouchstart' in document.documentElement === true) { document.addEventListener("touchstart", jSuites.calendar.isOpen); } else { document.addEventListener("mousedown", jSuites.calendar.isOpen); } document.addEventListener("keydown", function(e) { if (e.which == 13) { // ENTER if (jSuites.calendar.current) { jSuites.calendar.current.close(false, true); } } else if (e.which == 27) { // ESC if (jSuites.calendar.current) { jSuites.calendar.current.close(false, false); } } }); jSuites.calendar.hasEvents = true; } // Append element to the DOM if (el.tagName == 'INPUT') { el.parentNode.insertBefore(calendar, el.nextSibling); // Add properties el.setAttribute('autocomplete', 'off'); el.setAttribute('data-mask', obj.options.format.toLowerCase()); if (obj.options.readonly) { el.setAttribute('readonly', 'readonly'); } if (obj.options.placeholder) { el.setAttribute('placeholder', obj.options.placeholder); } // Element el.classList.add('jcalendar-input'); // Value el.value = obj.setLabel(obj.getValue(), obj.options); } else { // Get days obj.getDays(); // Hour if (obj.options.time) { calendarSelectHour.value = obj.date[3]; calendarSelectMin.value = obj.date[4]; } } // Keep object available from the node el.calendar = obj; el.change = obj.setValue; if (obj.options.opened == true) { obj.open(); } return obj; }); jSuites.calendar.prettify = function(d, texts) { if (! texts) { var texts = { justNow: 'Just now', xMinutesAgo: '{0}m ago', xHoursAgo: '{0}h ago', xDaysAgo: '{0}d ago', xWeeksAgo: '{0}w ago', xMonthsAgo: '{0} mon ago', xYearsAgo: '{0}y ago', } } var d1 = new Date(); var d2 = new Date(d); var total = parseInt((d1 - d2) / 1000 / 60); String.prototype.format = function(o) { return this.replace('{0}', o); } if (total == 0) { var text = texts.justNow; } else if (total < 90) { var text = texts.xMinutesAgo.format(total); } else if (total < 1440) { // One day var text = texts.xHoursAgo.format(Math.round(total/60)); } else if (total < 20160) { // 14 days var text = texts.xDaysAgo.format(Math.round(total / 1440)); } else if (total < 43200) { // 30 days var text = texts.xWeeksAgo.format(Math.round(total / 10080)); } else if (total < 1036800) { // 24 months var text = texts.xMonthsAgo.format(Math.round(total / 43200)); } else { // 24 months+ var text = texts.xYearsAgo.format(Math.round(total / 525600)); } return text; } jSuites.calendar.prettifyAll = function() { var elements = document.querySelectorAll('.prettydate'); for (var i = 0; i < elements.length; i++) { if (elements[i].getAttribute('data-date')) { elements[i].innerHTML = jSuites.calendar.prettify(elements[i].getAttribute('data-date')); } else { elements[i].setAttribute('data-date', elements[i].innerHTML); elements[i].innerHTML = jSuites.calendar.prettify(elements[i].innerHTML); } } } jSuites.calendar.now = function(date, dateOnly) { if (! date) { var date = new Date(); } var y = date.getFullYear(); var m = date.getMonth() + 1; var d = date.getDate(); var h = date.getHours(); var i = date.getMinutes(); var s = date.getSeconds(); if (dateOnly == true) { return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d); } else { return jSuites.two(y) + '-' + jSuites.two(m) + '-' + jSuites.two(d) + ' ' + jSuites.two(h) + ':' + jSuites.two(i) + ':' + jSuites.two(s); } } jSuites.calendar.toArray = function(value) { var date = value.split(((value.indexOf('T') !== -1) ? 'T' : ' ')); var time = date[1]; var date = date[0].split('-'); var y = parseInt(date[0]); var m = parseInt(date[1]); var d = parseInt(date[2]); if (time) { var time = time.split(':'); var h = parseInt(time[0]); var i = parseInt(time[1]); } else { var h = 0; var i = 0; } return [ y, m, d, h, i, 0 ]; } // Helper to extract date from a string jSuites.calendar.extractDateFromString = function(date, format) { if (date > 0 && Number(date) == date) { var d = new Date(Math.round((date - 25569)*86400*1000)); return d.getFullYear() + "-" + jSuites.two(d.getMonth()) + "-" + jSuites.two(d.getDate()) + ' 00:00:00'; } var v1 = '' + date; var v2 = format.replace(/[0-9]/g,''); var test = 1; // Get year var y = v2.search("YYYY"); y = v1.substr(y,4); if (parseInt(y) != y) { test = 0; } // Get month var m = v2.search("MM"); m = v1.substr(m,2); if (parseInt(m) != m || m > 12) { test = 0; } // Get day var d = v2.search("DD"); d = v1.substr(d,2); if (parseInt(d) != d || d > 31) { test = 0; } // Get hour var h = v2.search("HH"); if (h >= 0) { h = v1.substr(h,2); if (! parseInt(h) || h > 23) { h = '00'; } } else { h = '00'; } // Get minutes var i = v2.search("MI"); if (i >= 0) { i = v1.substr(i,2); if (! parseInt(i) || i > 59) { i = '00'; } } else { i = '00'; } // Get seconds var s = v2.search("SS"); if (s >= 0) { s = v1.substr(s,2); if (! parseInt(s) || s > 59) { s = '00'; } } else { s = '00'; } if (test == 1 && date.length == v2.length) { // Update source return y + '-' + m + '-' + d + ' ' + h + ':' + i + ':' + s; } return ''; } // Helper to convert date into string jSuites.calendar.getDateString = function(value, options) { if (! options) { var options = {}; } // Labels if (typeof(options) == 'string') { var format = options; } else { var format = options.format; } // Labels if (options && options.weekdays) { var weekdays = options.weekdays; } else { var weekdays = [ 'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday' ]; } // Labels if (options && options.months) { var months = options.months; } else { var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]; } // Labels if (options && options.months) { var monthsFull = options.monthsFull; } else { var monthsFull = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; } // Default date format if (! format) { format = 'DD/MM/YYYY'; } if (value) { var d = ''+value; var splitStr = (d.indexOf('T') !== -1) ? 'T' : ' '; d = d.split(splitStr); var h = ''; var m = ''; var s = ''; if (d[1]) { h = d[1].split(':'); m = h[1] ? h[1] : '00'; s = h[2] ? h[2] : '00'; h = h[0] ? h[0] : '00'; } else { h = '00'; m = '00'; s = '00'; } d = d[0].split('-'); if (d[0] && d[1] && d[2] && d[0] > 0 && d[1] > 0 && d[1] < 13 && d[2] > 0 && d[2] < 32) { var calendar = new Date(d[0], d[1]-1, d[2]); d[1] = (d[1].length < 2 ? '0' : '') + d[1]; d[2] = (d[2].length < 2 ? '0' : '') + d[2]; h = (h.length < 2 ? '0' : '') + h; m = (m.length < 2 ? '0' : '') + m; s = (s.length < 2 ? '0' : '') + s; // New value value = format; // Legacy value = value.replace('MMM', 'MON'); // Extract tokens var tokens = [ 'YYYY', 'YYY', 'YY', 'Y', 'MM', 'DD', 'DY', 'DAY', 'WD', 'D', 'Q', 'HH24', 'HH12', 'HH', 'PM', 'AM', 'MI', 'SS', 'MS', 'MONTH', 'MON']; var pieces = []; var tmp = value; while (tmp) { var t = 0; for (var i = 0; i < tokens.length; i++) { if (t == 0 && tmp.toUpperCase().indexOf(tokens[i]) === 0) { t = tokens[i].length; } } if (t == 0) { pieces.push(tmp.substr(0, 1)); tmp = tmp.substr(1); } else { pieces.push(tmp.substr(0, t)); tmp = tmp.substr(t); } } // Replace tokens per values var replace = function(k, v, c) { if (c == true) { for (var i = 0; i < pieces.length; i++) { if (pieces[i].toUpperCase() == k) { pieces[i] = v; } } } else { for (var i = 0; i < pieces.length; i++) { if (pieces[i] == k) { pieces[i] = v; } } } } replace('YYYY', d[0], true); replace('YYY', d[0].substring(1,4), true); replace('YY', d[0].substring(2,4), true); replace('Y', d[0].substring(3,4), true); replace('MM', d[1], true); replace('DD', d[2], true); replace('Q', Math.floor((calendar.getMonth() + 3) / 3), true); if (h) { replace('HH24', h); } if (h > 12) { replace('HH12', h - 12, true); replace('HH', h - 12, true); replace('AM', 'pm', true); replace('PM', 'pm', true); } else { replace('HH12', h, true); replace('HH', h, true); replace('AM', 'am', true); replace('PM', 'am', true); } replace('MI', m, true); replace('SS', s, true); replace('MS', calendar.getMilliseconds(), true); // Textual tokens replace('MONTH', monthsFull[calendar.getMonth()].toUpperCase()); replace('Month', monthsFull[calendar.getMonth()]); replace('month', monthsFull[calendar.getMonth()].toLowerCase()); replace('MON', months[calendar.getMonth()].toUpperCase()); replace('MMM', months[calendar.getMonth()].toUpperCase()); replace('Mon', months[calendar.getMonth()]); replace('mon', months[calendar.getMonth()].toLowerCase()); replace('DAY', weekdays[calendar.getDay()].toUpperCase()); replace('Day', weekdays[calendar.getDay()]); replace('day', weekdays[calendar.getDay()].toLowerCase()); replace('DY', weekdays[calendar.getDay()].substr(0,3).toUpperCase()); replace('Dy', weekdays[calendar.getDay()].substr(0,3)); replace('dy', weekdays[calendar.getDay()].substr(0,3).toLowerCase()); replace('D', weekdays[calendar.getDay()]); replace('WD', weekdays[calendar.getDay()]); // Put pieces together value = pieces.join(''); } else { value = ''; } } return value; } jSuites.calendar.isOpen = function(e) { if (jSuites.calendar.current) { if (e.target.className && e.target.className.indexOf('jcalendar') == -1) { jSuites.calendar.current.close(false, false); } } } jSuites.color = (function(el, options) { var obj = {}; obj.options = {}; obj.values = []; // Global container if (! jSuites.color.current) { jSuites.color.current = null; } /** * @typedef {Object} defaults * @property {(string|Array)} value - Initial value of the compontent * @property {string} placeholder - The default instruction text on the element * @property {requestCallback} onchange - Method to be execute after any changes on the element * @property {requestCallback} onclose - Method to be execute when the element is closed * @property {string} doneLabel - Label for button done * @property {string} resetLabel - Label for button reset * @property {string} resetValue - Value for button reset * @property {Bool} showResetButton - Active or note for button reset - default false */ var defaults = { placeholder: '', value: null, onopen: null, onclose: null, onchange: null, closeOnChange: true, palette: null, position: null, doneLabel: 'Done', resetLabel: 'Reset', fullscreen: false, }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } if (! obj.options.palette) { // Default pallete obj.options.palette = jSuites.palette(); } // Value if (obj.options.value) { el.value = obj.options.value; } // Change el.change = obj.setValue; if (el.tagName == 'INPUT') { el.classList.add('jcolor-input'); } // Table container var container = document.createElement('div'); container.className = 'jcolor'; // Table container var backdrop = document.createElement('div'); backdrop.className = 'jcolor-backdrop'; container.appendChild(backdrop); // Content var content = document.createElement('div'); content.className = 'jcolor-content'; // Controls var controls = document.createElement('div'); controls.className = 'jcolor-controls'; content.appendChild(controls); // Reset button var resetButton = document.createElement('div'); resetButton.className = 'jcolor-reset'; resetButton.innerHTML = obj.options.resetLabel; resetButton.onclick = function() { obj.setValue(''); obj.close(); } controls.appendChild(resetButton); // Close button var closeButton = document.createElement('div'); closeButton.className = 'jcolor-close'; closeButton.innerHTML = obj.options.doneLabel; closeButton.onclick = function() { obj.close(); } controls.appendChild(closeButton); // Table pallete var table = document.createElement('table'); table.setAttribute('cellpadding', '7'); table.setAttribute('cellspacing', '0'); for (var j = 0; j < obj.options.palette.length; j++) { var tr = document.createElement('tr'); for (var i = 0; i < obj.options.palette[j].length; i++) { var td = document.createElement('td'); var color = obj.options.palette[j][i]; if (color.substr(0,1) !== '#') { color = '#' + color; } td.style.backgroundColor = color; td.setAttribute('data-value', color); td.innerHTML = ''; tr.appendChild(td); // Selected color if (obj.options.value == color) { td.classList.add('jcolor-selected'); } // Possible values obj.values[color] = td; } table.appendChild(tr); } /** * Open color pallete */ obj.open = function() { if (jSuites.color.current) { if (jSuites.color.current != obj) { jSuites.color.current.close(); } } if (! jSuites.color.current) { // Persist element jSuites.color.current = obj; // Show colorpicker container.classList.add('jcolor-focus'); var rectContent = content.getBoundingClientRect(); if (jSuites.getWindowWidth() < 800 || obj.options.fullscreen == true) { content.style.top = ''; content.classList.add('jcolor-fullscreen'); jSuites.animation.slideBottom(content, 1); backdrop.style.display = 'block'; } else { if (content.classList.contains('jcolor-fullscreen')) { content.classList.remove('jcolor-fullscreen'); backdrop.style.display = ''; } var rect = el.getBoundingClientRect(); if (obj.options.position) { content.style.position = 'fixed'; if (window.innerHeight < rect.bottom + rectContent.height) { content.style.top = (rect.top - (rectContent.height + 2)) + 'px'; } else { content.style.top = (rect.top + rect.height + 2) + 'px'; } content.style.left = rect.left + 'px'; } else { if (window.innerHeight < rect.bottom + rectContent.height) { content.style.top = -1 * (rectContent.height + rect.height + 2) + 'px'; } else { content.style.top = '2px'; } } } container.focus(); if (typeof(obj.options.onopen) == 'function') { obj.options.onopen(el); } } } /** * Close color pallete */ obj.close = function(ignoreEvents) { if (jSuites.color.current) { el.focus(); jSuites.color.current = null; if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { obj.options.onclose(el); } container.classList.remove('jcolor-focus'); } // Make sure backdrop is hidden backdrop.style.display = ''; return obj.options.value; } /** * Set value */ obj.setValue = function(color) { if (! color) { color = ''; } if (color !== obj.options.value) { el.value = color; obj.options.value = color; // Remove current selecded mark var selected = container.querySelector('.jcolor-selected'); if (selected) { selected.classList.remove('jcolor-selected'); } // Mark cell as selected if (obj.values[color]) { obj.values[color].classList.add('jcolor-selected'); } if (typeof(el.onchange) == 'function') { el.onchange({ type: 'change', target: el }); } // Onchange if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, color); } } if (obj.options.closeOnChange == true) { obj.close(); } } /** * Get value */ obj.getValue = function() { return obj.options.value; } var backdropClickControl = false; /** * Focus */ el.addEventListener("focus", function(e) { if (! jSuites.color.current) { obj.open(); } }); /** * If element is focus open the picker */ el.addEventListener("mouseup", function(e) { if (! jSuites.color.current) { obj.open(); } e.preventDefault(); e.stopPropagation(); }); backdrop.addEventListener("mousedown", function(e) { backdropClickControl = true; e.preventDefault(); e.stopPropagation(); }); backdrop.addEventListener("mouseup", function(e) { if (backdropClickControl && jSuites.color.current) { obj.close(); backdropClickControl = false; } e.preventDefault(); e.stopPropagation(); }); // Select color container.addEventListener("mouseup", function(e) { if (e.target.tagName == 'TD') { jSuites.color.current.setValue(e.target.getAttribute('data-value')); if (jSuites.color.current) { jSuites.color.current.close(); } e.preventDefault(); e.stopPropagation(); } }); // Close controller document.addEventListener("mousedown", function(e) { if (jSuites.color.current) { var element = jSuites.findElement(e.target, 'jcolor'); if (! element) { jSuites.color.current.close(); } } }); // Possible to focus the container container.setAttribute('tabindex', '900'); // Placeholder if (obj.options.placeholder) { el.setAttribute('placeholder', obj.options.placeholder); } // Append to the table content.appendChild(table); container.appendChild(content); // Insert picker after the element if (el.tagName == 'INPUT') { el.parentNode.insertBefore(container, el.nextSibling); } else { el.appendChild(container); } // Keep object available from the node el.color = obj; el.change = obj.setValue; return obj; }); jSuites.contextmenu = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { items: null, onclick: null, }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Class definition el.classList.add('jcontextmenu'); // Focusable el.setAttribute('tabindex', '900'); /** * Open contextmenu */ obj.open = function(e, items) { if (items) { // Update content obj.options.items = items; // Create items obj.create(items); } // Coordinates if ((obj.options.items && obj.options.items.length > 0) || el.children.length) { if (e.target) { var x = e.clientX; var y = e.clientY; } else { var x = e.x; var y = e.y; } el.classList.add('jcontextmenu-focus'); el.focus(); var rect = el.getBoundingClientRect(); if (window.innerHeight < y + rect.height) { var h = y - rect.height; if (h < 0) { h = 0; } el.style.top = h + 'px'; } else { el.style.top = y + 'px'; } if (window.innerWidth < x + rect.width) { if (x - rect.width > 0) { el.style.left = (x - rect.width) + 'px'; } else { el.style.left = '10px'; } } else { el.style.left = x + 'px'; } } } /** * Close menu */ obj.close = function() { if (el.classList.contains('jcontextmenu-focus')) { el.classList.remove('jcontextmenu-focus'); } } /** * Create items based on the declared objectd * @param {object} items - List of object */ obj.create = function(items) { // Update content el.innerHTML = ''; // Append items for (var i = 0; i < items.length; i++) { var itemContainer = createItemElement(items[i]); el.appendChild(itemContainer); } } /** * Private function for create a new Item element * @param {type} item * @returns {jsuitesL#15.jSuites.contextmenu.createItemElement.itemContainer} */ function createItemElement(item) { if (item.type && (item.type == 'line' || item.type == 'divisor')) { var itemContainer = document.createElement('hr'); } else { var itemContainer = document.createElement('div'); var itemText = document.createElement('a'); itemText.innerHTML = item.title; if (item.icon) { itemContainer.setAttribute('data-icon', item.icon); } if (item.id) { itemContainer.id = item.id; } if (item.disabled) { itemContainer.className = 'jcontextmenu-disabled'; } else if (item.onclick) { itemContainer.method = item.onclick; itemContainer.addEventListener("mouseup", function() { // Execute method this.method(this); }); } itemContainer.appendChild(itemText); if (item.submenu) { var itemIconSubmenu = document.createElement('span'); itemIconSubmenu.innerHTML = "►"; itemContainer.appendChild(itemIconSubmenu); itemContainer.classList.add('jcontexthassubmenu'); var el_submenu = document.createElement('div'); // Class definition el_submenu.classList.add('jcontextmenu'); // Focusable el_submenu.setAttribute('tabindex', '900'); // Append items var submenu = item.submenu; for (var i = 0; i < submenu.length; i++) { var itemContainerSubMenu = createItemElement(submenu[i]); el_submenu.appendChild(itemContainerSubMenu); } itemContainer.appendChild(el_submenu); } else if (item.shortcut) { var itemShortCut = document.createElement('span'); itemShortCut.innerHTML = item.shortcut; itemContainer.appendChild(itemShortCut); } } return itemContainer; } if (typeof(obj.options.onclick) == 'function') { el.addEventListener('click', function(e) { obj.options.onclick(obj, e); }); } // Create items if (obj.options.items) { obj.create(obj.options.items); } el.addEventListener('blur', function(e) { setTimeout(function() { obj.close(); }, 120); }); if (! jSuites.contextmenu.hasEvents) { window.addEventListener("mousewheel", function() { obj.close(); }); document.addEventListener("contextmenu", function(e) { var id = jSuites.contextmenu.getElement(e.target); if (id) { var element = document.querySelector('#' + id); if (! element) { console.error('JSUITES: Contextmenu id not found'); } else { element.contextmenu.open(e); e.preventDefault(); } } }); jSuites.contextmenu.hasEvents = true; } el.contextmenu = obj; return obj; }); jSuites.contextmenu.getElement = function(element) { var foundId = 0; function path (element) { if (element.parentNode && element.getAttribute('aria-contextmenu-id')) { foundId = element.getAttribute('aria-contextmenu-id') } else { if (element.parentNode) { path(element.parentNode); } } } path(element); return foundId; } jSuites.dropdown = (function(el, options) { var obj = {}; obj.options = {}; // If the element is a SELECT tag, create a configuration object if (el.tagName == 'SELECT') { var ret = jSuites.dropdown.extractFromDom(el, options); el = ret.el; options = ret.options; } // Default configuration var defaults = { url: null, data: [], multiple: false, autocomplete: false, remoteSearch: false, lazyLoading: false, type: null, width: null, maxWidth: null, opened: false, value: null, placeholder: '', newOptions: false, position: false, onchange: null, onload: null, onopen: null, onclose: null, onfocus: null, onblur: null, oninsert: null, }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Global container if (! jSuites.dropdown.current) { jSuites.dropdown.current = null; } // Force autocomplete search if (obj.options.remoteSearch == true) { obj.options.autocomplete = true; } // Containers obj.items = []; obj.groups = []; obj.value = []; // Search options obj.search = ''; obj.results = null; obj.numOfItems = 0; // Create dropdown el.classList.add('jdropdown'); if (obj.options.type == 'searchbar') { el.classList.add('jdropdown-searchbar'); } else if (obj.options.type == 'list') { el.classList.add('jdropdown-list'); } else if (obj.options.type == 'picker') { el.classList.add('jdropdown-picker'); } else { if (jSuites.getWindowWidth() < 800) { el.classList.add('jdropdown-picker'); obj.options.type = 'picker'; } else { if (obj.options.width) { el.style.width = obj.options.width; el.style.minWidth = obj.options.width; } el.classList.add('jdropdown-default'); obj.options.type = 'default'; } } // Header container var containerHeader = document.createElement('div'); containerHeader.className = 'jdropdown-container-header'; // Header obj.header = document.createElement('input'); obj.header.className = 'jdropdown-header'; obj.header.setAttribute('autocomplete', 'off'); if (typeof(obj.options.onfocus) == 'function') { obj.header.onfocus = function() { obj.options.onfocus(el); } } if (typeof(obj.options.onblur) == 'function') { obj.header.onblur = function() { obj.options.onblur(el); } } if (obj.options.newOptions == true) { obj.header.classList.add('jdropdown-add'); } // Container var container = document.createElement('div'); container.className = 'jdropdown-container'; // Dropdown content var content = document.createElement('div'); content.className = 'jdropdown-content'; // Close button var closeButton = document.createElement('div'); closeButton.className = 'jdropdown-close'; closeButton.innerHTML = 'Done'; // Reset button var resetButton = document.createElement('div'); resetButton.className = 'jdropdown-reset'; resetButton.innerHTML = 'x'; resetButton.onclick = function() { obj.reset(); obj.close(); } // Create backdrop var backdrop = document.createElement('div'); backdrop.className = 'jdropdown-backdrop'; // Autocomplete if (obj.options.autocomplete == true) { el.setAttribute('data-autocomplete', true); // Handler var keyTimer = null; obj.header.addEventListener('keyup', function(e) { if (! keyTimer) { if (obj.search != obj.header.value.trim()) { keyTimer = setTimeout(function() { obj.find(obj.header.value.trim()); keyTimer = null; }, 400); } if (! el.classList.contains('jdropdown-focus')) { obj.open(); } } }); } else { obj.header.setAttribute('readonly', 'readonly'); } // Place holder if (! obj.options.placeholder && el.getAttribute('placeholder')) { obj.options.placeholder = el.getAttribute('placeholder'); } if (obj.options.placeholder) { obj.header.setAttribute('placeholder', obj.options.placeholder); } // Append elements containerHeader.appendChild(obj.header); if (obj.options.type == 'searchbar') { containerHeader.appendChild(closeButton); } else { container.appendChild(closeButton); } if (! obj.options.type || obj.options.type == 'default') { //containerHeader.appendChild(resetButton); } container.appendChild(content); el.appendChild(containerHeader); el.appendChild(container); el.appendChild(backdrop); var filter = function(a) { return a.filter(function(v) { return v; }); } /** * Init dropdown */ obj.init = function() { if (obj.options.url && ! obj.options.data.length) { jSuites.ajax({ url: obj.options.url, method: 'GET', dataType: 'json', success: function(data) { if (data) { // Set data obj.setData(data); // Set value if (obj.options.value != null) { obj.setValue(obj.options.value); } // Onload method if (typeof(obj.options.onload) == 'function') { obj.options.onload(el, obj, data); } } } }); } else { var data = []; if (obj.options.data.length) { for (var j = 0; j < obj.options.data.length; j++) { data.push(obj.options.data[j]); } } // Set data obj.setData(data); // Set value if (obj.options.value != null) { obj.setValue(obj.options.value); } // Onload if (typeof(obj.options.onload) == 'function') { obj.options.onload(el, obj, obj.options.data); } } // Open dropdown if (obj.options.opened == true) { obj.open(); } } obj.getUrl = function() { return obj.options.url; } obj.setUrl = function(url) { obj.options.url = url; jSuites.ajax({ url: obj.options.url, method: 'GET', dataType: 'json', success: function(data) { obj.setData(data); } }); } /** * Add a new item */ obj.add = function(title) { if (! title) { var current = obj.options.autocomplete == true ? obj.header.value : ''; var title = prompt('Text', current); if (! title) { return false; } } // Create new item var item = { value: jSuites.guid(), text: title, }; // Add item to the main list obj.options.data.push(item); var newItem = obj.createItem(item); // Append DOM to the list content.appendChild(newItem.element); // Callback if (typeof(obj.options.oninsert) == 'function') { obj.options.oninsert(obj, newItem, item) } // Show content if (content.style.display == 'none') { content.style.display = ''; } return item; } /** * Create a new item */ obj.createItem = function(data, group, groupName) { if (typeof(data.text) == 'undefined' && data.name) { data.text = data.name; } if (typeof(data.value) == 'undefined' && data.id) { data.value = data.id; } // Create item var item = {}; item.element = document.createElement('div'); item.element.className = 'jdropdown-item'; item.element.indexValue = obj.items.length; item.value = data.value; item.text = data.text; // Id if (data.id) { item.element.setAttribute('id', data.id); } // Group reference if (group) { item.group = group; item.groupName = groupName; } // Image if (data.image) { var image = document.createElement('img'); image.className = 'jdropdown-image'; image.src = data.image; if (! data.title) { image.classList.add('jdropdown-image-small'); } item.element.appendChild(image); } else if (data.color) { var color = document.createElement('div'); color.className = 'jdropdown-color'; color.style.backgroundColor = data.color; item.element.appendChild(color); } // Set content var node = document.createElement('div'); node.className = 'jdropdown-description'; node.innerHTML = data.text || ' '; // Title if (data.title) { var title = document.createElement('div'); title.className = 'jdropdown-title'; title.innerHTML = data.title; node.appendChild(title); // Keep text reference item.title = data.title; } // Value if (obj.value && obj.value[data.value]) { item.element.classList.add('jdropdown-selected'); item.selected = true; } // Keep DOM accessible obj.items.push(item); // Add node to item item.element.appendChild(node); return item; } obj.appendData = function(data) { // Create elements if (data.length) { // Reset counter obj.numOfItems = 0; // Helpers var items = []; var groups = []; // Prepare data for (var i = 0; i < data.length; i++) { // Process groups if (data[i].group) { if (! groups[data[i].group]) { groups[data[i].group] = []; } groups[data[i].group].push(i); } else { items.push(i); } } // Groups var groupNames = Object.keys(groups); // Append groups in case exists if (groupNames.length > 0) { for (var i = 0; i < groupNames.length; i++) { // Group container var group = document.createElement('div'); group.className = 'jdropdown-group'; // Group name var groupName = document.createElement('div'); groupName.className = 'jdropdown-group-name'; groupName.innerHTML = groupNames[i]; // Group arrow var groupArrow = document.createElement('i'); groupArrow.className = 'jdropdown-group-arrow jdropdown-group-arrow-down'; groupName.appendChild(groupArrow); // Group items var groupContent = document.createElement('div'); groupContent.className = 'jdropdown-group-items'; for (var j = 0; j < groups[groupNames[i]].length; j++) { var item = obj.createItem(data[groups[groupNames[i]][j]], group, groupNames[i]); if (obj.options.lazyLoading == false || obj.numOfItems < 200) { groupContent.appendChild(item.element); obj.numOfItems++; } } // Group itens group.appendChild(groupName); group.appendChild(groupContent); // Keep group DOM obj.groups.push(group); // Only add to the screen if children on the group if (groupContent.children.length > 0) { // Add DOM to the content content.appendChild(group); } } } if (items.length) { for (var i = 0; i < items.length; i++) { var item = obj.createItem(data[items[i]]); if (obj.options.lazyLoading == false || obj.numOfItems < 200) { content.appendChild(item.element); obj.numOfItems++; } } } } } obj.setData = function(data) { // Prepare data if (data.length) { for (var i = 0; i < data.length; i++) { // Compatibility if (typeof(data[i]) != 'object') { // Correct format data[i] = { value: data[i], text: data[i] } } } // Make sure the content container is blank content.innerHTML = ''; // Reset obj.reset(); // Reset items obj.items = []; // Append data obj.appendData(data); } // Update data obj.options.data = data; } /** * Get position of the item */ obj.getPosition = function(value) { for (var i = 0; i < obj.items.length; i++) { if (obj.items[i].value == value) { return i; } } return 0; } /** * Get dropdown current text */ obj.getText = function(asArray) { var v = []; var k = Object.keys(obj.value); for (var i = 0; i < k.length; i++) { v.push(obj.value[k[i]]); } if (asArray) { return v; } else { return v.join('; '); } } /** * Get dropdown current value */ obj.getValue = function(asArray) { if (asArray) { return Object.keys(obj.value); } else { return Object.keys(obj.value).join(';'); } } obj.setValue = function(value) { var setValue = function(item, value) { if (obj.items[item].value == value) { if (obj.items[item].element) { obj.items[item].element.classList.add('jdropdown-selected'); } obj.items[item].selected = true; // Push to the values container obj.value[value] = obj.items[item].text; } } // Old value var oldValue = obj.getValue(); // Remove selected for (var i = 0; i < obj.items.length; i++) { if (obj.items[i].selected == true) { if (obj.items[i].element) { obj.items[i].element.classList.remove('jdropdown-selected') } obj.items[i].selected = null; } } // Reset obj.value = []; // Set values if (value !== null) { if (! Array.isArray(value)) { for (var i = 0; i < obj.items.length; i++) { setValue(i, value); } } else { for (var i = 0; i < obj.items.length; i++) { for (var j = 0; j < value.length; j++) { setValue(i, value[j]); } } } } // New value var newValue = obj.getValue(); if (oldValue != newValue) { // Label obj.header.value = obj.getText(); // Value obj.options.value = obj.getValue(); // Element value el.value = obj.options.value; // Events if (typeof(el.onchange) == 'function') { el.onchange({ type: 'change', target: this }); } if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, null, oldValue, obj.options.value); } } } obj.resetSelected = function() { obj.setValue(null); } obj.selectIndex = function(index) { // Make sure is a number var index = parseInt(index); // Only select those existing elements if (obj.items && obj.items[index]) { // Current selection var oldValue = obj.getValue(); // Reset cursor to a new position obj.setCursor(index, false); // Behaviour if (! obj.options.multiple) { // Update value if (! obj.value[obj.items[index].value]) { obj.setValue(obj.items[index].value); } else { obj.setValue(null); } obj.close(); } else { // Toggle option if (obj.items[index].selected) { obj.items[index].element.classList.remove('jdropdown-selected'); obj.items[index].selected = false; // Remove from selected list delete obj.value[obj.items[index].value]; } else { // Select element obj.items[index].element.classList.add('jdropdown-selected'); obj.items[index].selected = true; // Add to the selected list obj.value[obj.items[index].value] = obj.items[index].text; } // Update labels for multiple dropdown if (! obj.options.autocomplete) { obj.header.value = obj.getText(); } // Events if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, index, oldValue, obj.getValue()); } } } } obj.selectItem = function(item) { if (jSuites.dropdown.current) { obj.selectIndex(item.indexValue); } } obj.find = function(str) { if (obj.search == str.trim()) { return false; } // Search term obj.search = str; // Results obj.numOfItems = 0; // Remove current items in the remote search if (obj.options.remoteSearch == true) { obj.currentIndex = null; obj.results = null; jSuites.ajax({ url: obj.options.url + '?q=' + str, method: 'GET', dataType: 'json', success: function(result) { // Reset items obj.items = []; content.innerHTML = ''; obj.appendData(result); if (! result.length) { content.style.display = 'none'; } else { content.style.display = ''; } } }); } else { // Search terms str = new RegExp(str, 'gi'); // Reset search obj.results = []; // Append options for (var i = 0; i < obj.items.length; i++) { // Item label var label = obj.items[i].text; // Item title var title = obj.items[i].title || ''; // Group name var groupName = obj.items[i].groupName || ''; if (str == null || obj.value[obj.items[i].value] != undefined || label.match(str) || title.match(str) || groupName.match(str)) { obj.results.push(obj.items[i]); if (obj.items[i].group && obj.items[i].group.children[1].children[0]) { // Remove all nodes while (obj.items[i].group.children[1].children[0]) { obj.items[i].group.children[1].removeChild(obj.items[i].group.children[1].children[0]); } } } } // Remove all nodes while (content.children[0]) { content.removeChild(content.children[0]); } // Show 200 items at once var number = obj.results.length || 0; // Lazyloading if (obj.options.lazyLoading == true && number > 200) { number = 200; } for (var i = 0; i < number; i++) { if (obj.results[i].group) { if (! obj.results[i].group.parentNode) { content.appendChild(obj.results[i].group); } obj.results[i].group.children[1].appendChild(obj.results[i].element); } else { content.appendChild(obj.results[i].element); } obj.numOfItems++; } if (! obj.results.length) { content.style.display = 'none'; } else { content.style.display = ''; } } } obj.open = function() { if (jSuites.dropdown.current != el) { if (jSuites.dropdown.current) { jSuites.dropdown.current.dropdown.close(); } jSuites.dropdown.current = el; } // Focus if (! el.classList.contains('jdropdown-focus')) { // Add focus el.classList.add('jdropdown-focus'); // Animation if (jSuites.getWindowWidth() < 800) { if (obj.options.type == null || obj.options.type == 'picker') { jSuites.animation.slideBottom(container, 1); } } // Filter if (obj.options.autocomplete == true) { obj.header.value = obj.search; obj.header.focus(); } // Set cursor for the first or first selected element var k = Object.keys(obj.value); if (k[0]) { var cursor = obj.getPosition(k[0]); if (cursor) { obj.setCursor(cursor); } } // Container Size if (! obj.options.type || obj.options.type == 'default') { var rect = el.getBoundingClientRect(); var rectContainer = container.getBoundingClientRect(); if (obj.options.position) { container.style.position = 'fixed'; if (window.innerHeight < rect.bottom + rectContainer.height) { container.style.top = ''; container.style.bottom = (window.innerHeight - rect.top ) + 1 + 'px'; } else { container.style.top = rect.bottom + 'px'; container.style.bottom = ''; } container.style.left = rect.left + 'px'; } else { if (window.innerHeight < rect.bottom + rectContainer.height) { container.style.top = ''; container.style.bottom = rect.height + 1 + 'px'; } else { container.style.top = ''; container.style.bottom = ''; } } container.style.minWidth = rect.width + 'px'; if (obj.options.maxWidth) { container.style.maxWidth = obj.options.maxWidth; } if (! obj.items.length && obj.options.autocomplete == true) { content.style.display = 'none'; } else { content.style.display = ''; } } } // Events if (typeof(obj.options.onopen) == 'function') { obj.options.onopen(el); } } obj.close = function(ignoreEvents) { if (jSuites.dropdown.current) { // Remove controller jSuites.dropdown.current = null // Remove cursor obj.setCursor(); // Update labels obj.header.value = obj.getText(); // Events if (! ignoreEvents && typeof(obj.options.onclose) == 'function') { obj.options.onclose(el); } // Blur if (obj.header.blur) { obj.header.blur(); } // Remove focus el.classList.remove('jdropdown-focus'); } return obj.getValue(); } /** * Set cursor */ obj.setCursor = function(index, setPosition) { // Remove current cursor if (obj.currentIndex != null) { // Remove visual cursor if (obj.items && obj.items[obj.currentIndex]) { obj.items[obj.currentIndex].element.classList.remove('jdropdown-cursor'); } } if (index == undefined) { obj.currentIndex = null; } else { parseInt(index); obj.items[index].element.classList.add('jdropdown-cursor'); obj.currentIndex = index; // Update scroll to the cursor element if (setPosition !== false && obj.items[obj.currentIndex].element) { var container = content.scrollTop; var element = obj.items[obj.currentIndex].element; content.scrollTop = element.offsetTop - element.scrollTop + element.clientTop - 95; } } } // Compatibility obj.resetCursor = obj.setCursor; obj.updateCursor = obj.setCursor; /** * Reset cursor and selected items */ obj.reset = function() { // Reset cursor obj.setCursor(); // Reset selected obj.setValue(null); } /** * First visible item */ obj.firstVisible = function() { var newIndex = null; for (var i = 0; i < obj.items.length; i++) { if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') { newIndex = i; break; } } if (newIndex == null) { return false; } obj.setCursor(newIndex); } /** * Navigation */ obj.first = function() { var newIndex = null; for (var i = obj.currentIndex - 1; i >= 0; i--) { if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') { newIndex = i; } } if (newIndex == null) { return false; } obj.setCursor(newIndex); } obj.last = function() { var newIndex = null; for (var i = obj.currentIndex + 1; i < obj.items.length; i++) { if (obj.items && obj.items[i] && obj.items[i].element.parentNode && obj.items[i].element.style.display != 'none') { newIndex = i; } } if (newIndex == null) { return false; } obj.setCursor(newIndex); } obj.next = function() { var newIndex = null; for (var i = obj.currentIndex + 1; i < obj.items.length; i++) { if (obj.items && obj.items[i] && obj.items[i].element.parentNode) { newIndex = i; break; } } if (newIndex == null) { return false; } obj.setCursor(newIndex); } obj.prev = function() { var newIndex = null; for (var i = obj.currentIndex - 1; i >= 0; i--) { if (obj.items && obj.items[i] && obj.items[i].element.parentNode) { newIndex = i; break; } } if (newIndex == null) { return false; } obj.setCursor(newIndex); } obj.loadUp = function() { return false; } obj.loadDown = function() { var test = false; // Search if (obj.results) { var results = obj.results; } else { var results = obj.items; } if (results.length > obj.numOfItems) { var numberOfItems = obj.numOfItems; var number = results.length - numberOfItems; if (number > 200) { number = 200; } for (var i = numberOfItems; i < numberOfItems + number; i++) { if (results[i].group) { if (! results[i].group.parentNode) { content.appendChild(results[i].group); } results[i].group.children[2].appendChild(results[i].element); } else { content.appendChild(results[i].element); } obj.numOfItems++; } // New item added test = true; } return test; } if (! jSuites.dropdown.hasEvents) { if ('ontouchsend' in document.documentElement === true) { document.addEventListener('touchsend', jSuites.dropdown.mouseup); } else { document.addEventListener('mouseup', jSuites.dropdown.mouseup); } document.addEventListener('keydown', jSuites.dropdown.onkeydown); jSuites.dropdown.hasEvents = true; } // Lazyloading if (obj.options.lazyLoading == true) { jSuites.lazyLoading(content, { loadUp: obj.loadUp, loadDown: obj.loadDown, }); } // Start dropdown obj.init(); // Keep object available from the node el.dropdown = obj; el.change = obj.setValue; return obj; }); jSuites.dropdown.hasEvents = false; jSuites.dropdown.mouseup = function(e) { var element = jSuites.findElement(e.target, 'jdropdown'); if (element) { var dropdown = element.dropdown; if (e.target.classList.contains('jdropdown-header')) { if (element.classList.contains('jdropdown-focus') && element.classList.contains('jdropdown-default')) { var rect = element.getBoundingClientRect(); if (e.changedTouches && e.changedTouches[0]) { var x = e.changedTouches[0].clientX; var y = e.changedTouches[0].clientY; } else { var x = e.clientX; var y = e.clientY; } if (rect.width - (x - rect.left) < 30) { if (e.target.classList.contains('jdropdown-add')) { dropdown.add(); } else { dropdown.close(); } } else { if (dropdown.options.autocomplete == false) { dropdown.close(); } } } else { dropdown.open(); } } else if (e.target.classList.contains('jdropdown-group-name')) { var items = e.target.nextSibling.children; if (e.target.nextSibling.style.display != 'none') { for (var i = 0; i < items.length; i++) { if (items[i].style.display != 'none') { dropdown.selectItem(items[i]); } } } } else if (e.target.classList.contains('jdropdown-group-arrow')) { if (e.target.classList.contains('jdropdown-group-arrow-down')) { e.target.classList.remove('jdropdown-group-arrow-down'); e.target.classList.add('jdropdown-group-arrow-up'); e.target.parentNode.nextSibling.style.display = 'none'; } else { e.target.classList.remove('jdropdown-group-arrow-up'); e.target.classList.add('jdropdown-group-arrow-down'); e.target.parentNode.nextSibling.style.display = ''; } } else if (e.target.classList.contains('jdropdown-item')) { dropdown.selectItem(e.target); } else if (e.target.classList.contains('jdropdown-image')) { dropdown.selectItem(e.target.parentNode); } else if (e.target.classList.contains('jdropdown-description')) { dropdown.selectItem(e.target.parentNode); } else if (e.target.classList.contains('jdropdown-title')) { dropdown.selectItem(e.target.parentNode.parentNode); } else if (e.target.classList.contains('jdropdown-close') || e.target.classList.contains('jdropdown-backdrop')) { dropdown.close(); } e.stopPropagation(); e.preventDefault(); } else { if (jSuites.dropdown.current) { jSuites.dropdown.current.dropdown.close(); } } } // Keydown controls jSuites.dropdown.onkeydown = function(e) { if (jSuites.dropdown.current) { // Element var element = jSuites.dropdown.current.dropdown; // Index var index = element.currentIndex; if (! e.shiftKey) { if (e.which == 13 || e.which == 27 || e.which == 35 || e.which == 36 || e.which == 38 || e.which == 40) { // Move cursor if (e.which == 13) { element.selectIndex(index); } else if (e.which == 38) { if (index == null) { element.firstVisible(); } else if (index > 0) { element.prev(); } } else if (e.which == 40) { if (index == null) { element.firstVisible(); } else if (index + 1 < element.items.length) { element.next(); } } else if (e.which == 36) { element.first(); } else if (e.which == 35) { element.last(); } else if (e.which == 27) { element.close(); } e.stopPropagation(); e.preventDefault(); } } } } jSuites.dropdown.extractFromDom = function(el, options) { // Keep reference var select = el; if (! options) { options = {}; } // Prepare configuration if (el.getAttribute('multiple') && (! options || options.multiple == undefined)) { options.multiple = true; } if (el.getAttribute('placeholder') && (! options || options.placeholder == undefined)) { options.placeholder = el.getAttribute('placeholder'); } if (el.getAttribute('data-autocomplete') && (! options || options.autocomplete == undefined)) { options.autocomplete = true; } if (! options || options.width == undefined) { options.width = el.offsetWidth; } if (el.value && (! options || options.value == undefined)) { options.value = el.value; } if (! options || options.data == undefined) { options.data = []; for (var j = 0; j < el.children.length; j++) { if (el.children[j].tagName == 'OPTGROUP') { for (var i = 0; i < el.children[j].children.length; i++) { options.data.push({ value: el.children[j].children[i].value, text: el.children[j].children[i].innerHTML, group: el.children[j].getAttribute('label'), }); } } else { options.data.push({ value: el.children[j].value, text: el.children[j].innerHTML, }); } } } if (! options || options.onchange == undefined) { options.onchange = function(a,b,c,d) { if (options.multiple == true) { if (obj.items[b].classList.contains('jdropdown-selected')) { select.options[b].setAttribute('selected', 'selected'); } else { select.options[b].removeAttribute('selected'); } } else { select.value = d; } } } // Create DIV var div = document.createElement('div'); el.parentNode.insertBefore(div, el); el.style.display = 'none'; el = div; return { el:el, options:options }; } /** * (c) HTML Editor * https://github.com/paulhodel/jsuites * * @author: Paul Hodel * @description: Inline simple richtext editor */ jSuites.editor = (function(el, options) { var obj = {}; obj.options = {}; // If element is textarea, then replace by div editor if (el.tagName == 'TEXTAREA' || el.tagName == 'INPUT') { // Current element var element = el; element.style.display = 'none'; // New Element el = document.createElement('div'); // Value if (! options.value) { options.value = element.value; } // Event to populate the textarea options.onblur = function(a,b,c) { element.value = b.getData() } element.insertBefore(el); } // Default configuration var defaults = { // Initial HTML content value: null, // Initial snippet snippet: null, // Add toolbar toolbar: null, // Website parser is to read websites and images from cross domain remoteParser: null, // Parse URL parseURL: false, // Accept drop files dropZone: false, dropAsAttachment: false, acceptImages: false, acceptFiles: false, maxFileSize: 5000000, allowImageResize: true, // Style border: true, padding: true, maxHeight: null, focus: false, // Events onclick: null, onfocus: null, onblur: null, onload: null, onkeyup: null, onkeydown: null, onchange: null, }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Private controllers var imageResize = 0; var editorTimer = null; var editorAction = null; // Make sure element is empty el.innerHTML = ''; // Change method el.change = obj.setValue; if (typeof(obj.options.onclick) == 'function') { el.onclick = function(e) { obj.options.onclick(el, obj, e); } } // Prepare container el.classList.add('jeditor-container'); // Padding if (obj.options.padding == true) { el.classList.add('jeditor-padding'); } // Border if (obj.options.border == false) { el.style.border = '0px'; } // Snippet var snippet = document.createElement('div'); snippet.className = 'jsnippet'; snippet.setAttribute('contenteditable', false); // Toolbar var toolbar = document.createElement('div'); toolbar.className = 'jeditor-toolbar'; // Create editor var editor = document.createElement('div'); editor.setAttribute('contenteditable', true); editor.setAttribute('spellcheck', false); editor.className = 'jeditor'; // Max height if (obj.options.maxHeight) { editor.style.overflowY = 'auto'; editor.style.maxHeight = obj.options.maxHeight; } // Set editor initial value if (obj.options.value) { var value = obj.options.value; } else { var value = el.innerHTML ? el.innerHTML : ''; } if (! value) { var value = '
'; } /** * Onchange event controllers */ var change = function() { // Events if (typeof(el.onchange) == 'function') { el.onchange({ type: 'change', target: el }); } if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, obj, e); } } /** * Extract images from a HTML string */ var extractImageFromHtml = function(html) { // Create temp element var div = document.createElement('div'); div.innerHTML = html; // Extract images var img = div.querySelectorAll('img'); if (img.length) { for (var i = 0; i < img.length; i++) { obj.addImage(img[i].src); } } } /** * Insert node at caret */ var insertNodeAtCaret = function(newNode) { var sel, range; if (window.getSelection) { sel = window.getSelection(); if (sel.rangeCount) { range = sel.getRangeAt(0); var selectedText = range.toString(); range.deleteContents(); range.insertNode(newNode); // move the cursor after element range.setStartAfter(newNode); range.setEndAfter(newNode); sel.removeAllRanges(); sel.addRange(range); } } } /** * Append snippet or thumbs in the editor * @Param object data */ var appendElement = function(data) { // Reset snippet snippet.innerHTML = ''; if (data.image) { var div = document.createElement('div'); div.className = 'jsnippet-image'; div.setAttribute('data-k', 'image'); snippet.appendChild(div); var image = document.createElement('img'); image.src = data.image; div.appendChild(image); } var div = document.createElement('div'); div.className = 'jsnippet-title'; div.setAttribute('data-k', 'title'); div.innerHTML = data.title; snippet.appendChild(div); var div = document.createElement('div'); div.className = 'jsnippet-description'; div.setAttribute('data-k', 'description'); div.innerHTML = data.description; snippet.appendChild(div); var div = document.createElement('div'); div.className = 'jsnippet-host'; div.setAttribute('data-k', 'host'); div.innerHTML = data.host; snippet.appendChild(div); var div = document.createElement('div'); div.className = 'jsnippet-url'; div.setAttribute('data-k', 'url'); div.innerHTML = data.url; snippet.appendChild(div); editor.appendChild(snippet); } var verifyEditor = function() { clearTimeout(editorTimer); editorTimer = setTimeout(function() { var snippet = editor.querySelector('.jsnippet'); var thumbsContainer = el.querySelector('.jeditor-thumbs-container'); if (! snippet && ! thumbsContainer) { var html = editor.innerHTML.replace(/\n/g, ' '); var container = document.createElement('div'); container.innerHTML = html; var thumbsContainer = container.querySelector('.jeditor-thumbs-container'); if (thumbsContainer) { thumbsContainer.remove(); } var text = container.innerText; var url = jSuites.editor.detectUrl(text); if (url) { if (url[0].substr(-3) == 'jpg' || url[0].substr(-3) == 'png' || url[0].substr(-3) == 'gif') { if (jSuites.editor.getDomain(url[0]) == window.location.hostname) { obj.importImage(url[0], ''); } else { obj.importImage(obj.options.remoteParser + url[0], ''); } } else { var id = jSuites.editor.youtubeParser(url[0]); obj.parseWebsite(url[0], id); } } } }, 1000); } obj.parseContent = function() { verifyEditor(); } obj.parseWebsite = function(url, youtubeId) { if (! obj.options.remoteParser) { console.log('The remoteParser is not defined'); } else { // Youtube definitions if (youtubeId) { var url = 'https://www.youtube.com/watch?v=' + youtubeId; } var p = { title: '', description: '', image: '', host: url.split('/')[2], url: url, } jSuites.ajax({ url: obj.options.remoteParser + encodeURI(url.trim()), method: 'GET', dataType: 'json', success: function(result) { // Get title if (result.title) { p.title = result.title; } // Description if (result.description) { p.description = result.description; } // Image if (result.image) { p.image = result.image; } else if (result['og:image']) { p.image = result['og:image']; } // Host if (result.host) { p.host = result.host; } // Url if (result.url) { p.url = result.url; } appendElement(p); } }); } } /** * Set editor value */ obj.setData = function(html) { editor.innerHTML = html; jSuites.editor.setCursor(editor, true); } obj.setValue = obj.setData; obj.getText = function() { return editor.innerText; } /** * Get editor data */ obj.getData = function(json) { if (! json) { var data = editor.innerHTML; } else { var data = { content : '', } // Get tag users var tagged = editor.querySelectorAll('.post-tag'); if (tagged.length) { data.users = []; for (var i = 0; i < tagged.length; i++) { var userId = tagged[i].getAttribute('data-user'); if (userId) { data.users.push(userId); } } data.users = data.users.join(','); } if (snippet.innerHTML) { var index = 0; data.snippet = {}; for (var i = 0; i < snippet.children.length; i++) { // Get key from element var key = snippet.children[i].getAttribute('data-k'); if (key) { if (key == 'image') { data.snippet.image = snippet.children[i].children[0].getAttribute('src'); } else { data.snippet[key] = snippet.children[i].innerHTML; } } } snippet.innerHTML = ''; snippet.remove(); } var text = editor.innerHTML; text = text.replace(/
/g, "\n"); text = text.replace(/<\/div>/g, "<\/div>\n"); text = text.replace(/<(?:.|\n)*?>/gm, ""); data.content = text.trim(); data = JSON.stringify(data); } return data; } // Reset obj.reset = function() { editor.innerHTML = ''; } obj.addPdf = function(data) { if (data.result.substr(0,4) != 'data') { console.error('Invalid source'); } else { var canvas = document.createElement('canvas'); canvas.width = 60; canvas.height = 60; var img = new Image(); var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); canvas.toBlob(function(blob) { var newImage = document.createElement('img'); newImage.src = window.URL.createObjectURL(blob); newImage.setAttribute('data-extension', 'pdf'); if (data.name) { newImage.setAttribute('data-name', data.name); } if (data.size) { newImage.setAttribute('data-size', data.size); } if (data.date) { newImage.setAttribute('data-date', data.date); } newImage.className = 'jfile pdf'; insertNodeAtCaret(newImage); // Image content newImage.content = data.result.substr(data.result.indexOf(',') + 1); }); } } obj.getFiles = function() { return jSuites.files(editor).get(); } obj.addImage = function(src, name, size, date) { if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) { console.error('remoteParser not defined in your initialization'); } else { // This is to process cross domain images if (src.substr(0,4) == 'data') { var extension = src.split(';') extension = extension[0].split('/'); extension = extension[1]; } else { var extension = src.substr(src.lastIndexOf('.') + 1); // Work for cross browsers src = obj.options.remoteParser + src; } var img = new Image(); img.onload = function onload() { var canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); canvas.toBlob(function(blob) { var newImage = document.createElement('img'); newImage.src = window.URL.createObjectURL(blob); newImage.setAttribute('tabindex', '900'); newImage.setAttribute('data-extension', extension); if (name) { newImage.setAttribute('data-name', name); } if (size) { newImage.setAttribute('data-size', size); } if (date) { newImage.setAttribute('data-date', date); } newImage.className = 'jfile'; var content = canvas.toDataURL(); insertNodeAtCaret(newImage); // Image content newImage.content = content.substr(content.indexOf(',') + 1); change(); }); }; img.src = src; } } obj.addFile = function(files) { var reader = []; for (var i = 0; i < files.length; i++) { if (files[i].size > obj.options.maxFileSize) { alert('The file is too big'); } else { // Only PDF or Images var type = files[i].type.split('/'); if (type[0] == 'image') { type = 1; } else if (type[1] == 'pdf') { type = 2; } else { type = 0; } if (type) { // Create file reader[i] = new FileReader(); reader[i].index = i; reader[i].type = type; reader[i].name = files[i].name; reader[i].date = files[i].lastModified; reader[i].size = files[i].size; reader[i].addEventListener("load", function (data) { // Get result if (data.target.type == 2) { if (obj.options.acceptFiles == true) { obj.addPdf(data.target); } } else { obj.addImage(data.target.result, data.target.name, data.total, data.target.lastModified); } }, false); reader[i].readAsDataURL(files[i]) } else { alert('The extension is not allowed'); } } } } // Destroy obj.destroy = function() { editor.removeEventListener('mouseup', editorMouseUp); editor.removeEventListener('mousedown', editorMouseDown); editor.removeEventListener('mousemove', editorMouseMove); editor.removeEventListener('keyup', editorKeyUp); editor.removeEventListener('keydown', editorKeyDown); editor.removeEventListener('dragstart', editorDragStart); editor.removeEventListener('dragenter', editorDragEnter); editor.removeEventListener('dragover', editorDragOver); editor.removeEventListener('drop', editorDrop); editor.removeEventListener('paste', editorPaste); if (typeof(obj.options.onblur) == 'function') { editor.removeEventListener('blur', editorBlur); } if (typeof(obj.options.onfocus) == 'function') { editor.removeEventListener('focus', editorFocus); } el.editor = null; el.classList.remove('jeditor-container'); toolbar.remove(); snippet.remove(); editor.remove(); } var isLetter = function (str) { var regex = /([\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]+)/g; return str.match(regex) ? 1 : 0; } // Event handlers var editorMouseUp = function(e) { editorAction = false; } var editorMouseDown = function(e) { var close = function(snippet) { var rect = snippet.getBoundingClientRect(); if (rect.width - (e.clientX - rect.left) < 40 && e.clientY - rect.top < 40) { snippet.innerHTML = ''; snippet.remove(); } } if (e.target.tagName == 'IMG') { if (e.target.style.cursor) { var rect = e.target.getBoundingClientRect(); editorAction = { e: e.target, x: e.clientX, y: e.clientY, w: rect.width, h: rect.height, d: e.target.style.cursor, } if (! e.target.style.width) { e.target.style.width = rect.width + 'px'; } if (! e.target.style.height) { e.target.style.height = rect.height + 'px'; } var s = window.getSelection(); if (s.rangeCount) { for (var i = 0; i < s.rangeCount; i++) { s.removeRange(s.getRangeAt(i)); } } } else { editorAction = true; } } else { if (e.target.classList.contains('jsnippet')) { close(e.target); } else if (e.target.parentNode.classList.contains('jsnippet')) { close(e.target.parentNode); } editorAction = true; } } var editorMouseMove = function(e) { if (e.target.tagName == 'IMG' && obj.options.allowImageResize == true) { if (e.target.getAttribute('tabindex')) { var rect = e.target.getBoundingClientRect(); if (e.clientY - rect.top < 5) { if (rect.width - (e.clientX - rect.left) < 5) { e.target.style.cursor = 'ne-resize'; } else if (e.clientX - rect.left < 5) { e.target.style.cursor = 'nw-resize'; } else { e.target.style.cursor = 'n-resize'; } } else if (rect.height - (e.clientY - rect.top) < 5) { if (rect.width - (e.clientX - rect.left) < 5) { e.target.style.cursor = 'se-resize'; } else if (e.clientX - rect.left < 5) { e.target.style.cursor = 'sw-resize'; } else { e.target.style.cursor = 's-resize'; } } else if (rect.width - (e.clientX - rect.left) < 5) { e.target.style.cursor = 'e-resize'; } else if (e.clientX - rect.left < 5) { e.target.style.cursor = 'w-resize'; } else { e.target.style.cursor = ''; } } } // Move if (e.which == 1 && editorAction && editorAction.d) { if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') { editorAction.e.style.width = (editorAction.w + (e.clientX - editorAction.x)) + 'px'; if (e.shiftKey) { var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w); editorAction.e.style.height = editorAction.h + newHeight + 'px'; } else { var newHeight = null; } } if (! newHeight) { if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') { if (! e.shiftKey) { editorAction.e.style.height = editorAction.h + (e.clientY - editorAction.y) + 'px'; } } } } } var editorKeyUp = function(e) { if (! editor.innerHTML) { editor.innerHTML = '

'; } if (typeof(obj.options.onkeyup) == 'function') { obj.options.onkeyup(el, obj, e); } change(e); } var editorKeyDown = function(e) { // Check for URL if (obj.options.parseURL == true) { verifyEditor(); } if (typeof(obj.options.onkeydown) == 'function') { obj.options.onkeydown(el, obj, e); } } var editorPaste = function(e) { if (e.clipboardData || e.originalEvent.clipboardData) { var html = (e.originalEvent || e).clipboardData.getData('text/html'); var text = (e.originalEvent || e).clipboardData.getData('text/plain'); var file = (e.originalEvent || e).clipboardData.files } else if (window.clipboardData) { var html = window.clipboardData.getData('Html'); var text = window.clipboardData.getData('Text'); var file = window.clipboardData.files } if (file.length) { // Paste a image from the clipboard obj.addFile(file); } else { // Paste text text = text.split('\r\n'); var str = ''; if (e.target.nodeName == 'DIV' && e.target.classList.contains('jeditor')) { for (var i = 0; i < text.length; i++) { var tmp = document.createElement('div'); if (text[i]) { tmp.innerHTML = text[i]; } else { tmp.innerHTML = '
'; } e.target.appendChild(tmp); } } else { for (var i = 0; i < text.length; i++) { if (text[i]) { str += '
' + text[i] + "
\r\n"; } } // Insert text document.execCommand('insertHtml', false, str); } // Extra images from the paste if (obj.options.acceptImages == true) { extractImageFromHtml(html); } } e.preventDefault(); } var editorDragStart = function(e) { if (editorAction && editorAction.e) { e.preventDefault(); } } var editorDragEnter = function(e) { if (editorAction || obj.options.dropZone == false) { // Do nothing } else { el.classList.add('jeditor-dragging'); } } var editorDragOver = function(e) { if (editorAction || obj.options.dropZone == false) { // Do nothing } else { if (editorTimer) { clearTimeout(editorTimer); } editorTimer = setTimeout(function() { el.classList.remove('jeditor-dragging'); }, 100); } } var editorDrop = function(e) { if (editorAction || obj.options.dropZone == false) { // Do nothing } else { // Position caret on the drop var range = null; if (document.caretRangeFromPoint) { range=document.caretRangeFromPoint(e.clientX, e.clientY); } else if (e.rangeParent) { range=document.createRange(); range.setStart(e.rangeParent,e.rangeOffset); } var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); sel.anchorNode.parentNode.focus(); var html = (e.originalEvent || e).dataTransfer.getData('text/html'); var text = (e.originalEvent || e).dataTransfer.getData('text/plain'); var file = (e.originalEvent || e).dataTransfer.files; if (file.length) { obj.addFile(file); } else if (text) { extractImageFromHtml(html); } el.classList.remove('jeditor-dragging'); e.preventDefault(); } } var editorBlur = function(e) { obj.options.onblur(el, obj, e); } var editorFocus = function(e) { obj.options.onfocus(el, obj, e); } editor.addEventListener('mouseup', editorMouseUp); editor.addEventListener('mousedown', editorMouseDown); editor.addEventListener('mousemove', editorMouseMove); editor.addEventListener('keyup', editorKeyUp); editor.addEventListener('keydown', editorKeyDown); editor.addEventListener('dragstart', editorDragStart); editor.addEventListener('dragenter', editorDragEnter); editor.addEventListener('dragover', editorDragOver); editor.addEventListener('drop', editorDrop); editor.addEventListener('paste', editorPaste); // Blur if (typeof(obj.options.onblur) == 'function') { editor.addEventListener('blur', editorBlur); } // Focus if (typeof(obj.options.onfocus) == 'function') { editor.addEventListener('focus', editorFocus); } // Onload if (typeof(obj.options.onload) == 'function') { obj.options.onload(el, obj, editor); } // Set value to the editor editor.innerHTML = value; // Append editor to the containre el.appendChild(editor); // Snippet if (obj.options.snippet) { appendElement(obj.options.snippet); } // Default toolbar if (obj.options.toolbar == null) { obj.options.toolbar = jSuites.editor.getDefaultToolbar(); } // Add toolbar if (obj.options.toolbar) { // Create toolbar jSuites.toolbar(toolbar, { container: true, items: obj.options.toolbar }); // Append to the DOM el.appendChild(toolbar); } // Focus to the editor if (obj.options.focus) { jSuites.editor.setCursor(editor, obj.options.focus == 'initial' ? true : false); } el.editor = obj; return obj; }); jSuites.editor.setCursor = function(element, first) { element.focus(); document.execCommand('selectAll'); var sel = window.getSelection(); var range = sel.getRangeAt(0); if (first == true) { var node = range.startContainer; var size = 0; } else { var node = range.endContainer; var size = node.length; } range.setStart(node, size); range.setEnd(node, size); sel.removeAllRanges(); sel.addRange(range); } jSuites.editor.getDomain = function(url) { return url.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0].split(/:/g)[0]; } jSuites.editor.detectUrl = function(text) { var expression = /(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig; var links = text.match(expression); if (links) { if (links[0].substr(0,3) == 'www') { links[0] = 'http://' + links[0]; } } return links; } jSuites.editor.youtubeParser = function(url) { var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/; var match = url.match(regExp); return (match && match[7].length == 11) ? match[7] : false; } jSuites.editor.getDefaultToolbar = function() { return [ { content: 'undo', onclick: function() { document.execCommand('undo'); } }, { content: 'redo', onclick: function() { document.execCommand('redo'); } }, { type:'divisor' }, { content: 'format_bold', onclick: function(a,b,c) { document.execCommand('bold'); if (document.queryCommandState("bold")) { c.classList.add('selected'); } else { c.classList.remove('selected'); } } }, { content: 'format_italic', onclick: function(a,b,c) { document.execCommand('italic'); if (document.queryCommandState("italic")) { c.classList.add('selected'); } else { c.classList.remove('selected'); } } }, { content: 'format_underline', onclick: function(a,b,c) { document.execCommand('underline'); if (document.queryCommandState("underline")) { c.classList.add('selected'); } else { c.classList.remove('selected'); } } }, { type:'divisor' }, { content: 'format_list_bulleted', onclick: function(a,b,c) { document.execCommand('insertUnorderedList'); if (document.queryCommandState("insertUnorderedList")) { c.classList.add('selected'); } else { c.classList.remove('selected'); } } }, { content: 'format_list_numbered', onclick: function(a,b,c) { document.execCommand('insertOrderedList'); if (document.queryCommandState("insertOrderedList")) { c.classList.add('selected'); } else { c.classList.remove('selected'); } } }, { content: 'format_indent_increase', onclick: function(a,b,c) { document.execCommand('indent', true, null); if (document.queryCommandState("indent")) { c.classList.add('selected'); } else { c.classList.remove('selected'); } } }, { content: 'format_indent_decrease', onclick: function() { document.execCommand('outdent'); if (document.queryCommandState("outdent")) { this.classList.add('selected'); } else { this.classList.remove('selected'); } } }/*, { icon: ['format_align_left', 'format_align_right', 'format_align_center'], onclick: function() { document.execCommand('justifyCenter'); if (document.queryCommandState("justifyCenter")) { this.classList.add('selected'); } else { this.classList.remove('selected'); } } } { type:'select', items: ['Verdana','Arial','Courier New'], onchange: function() { } }, { type:'select', items: ['10px','12px','14px','16px','18px','20px','22px'], onchange: function() { } }, { icon:'format_align_left', onclick: function() { document.execCommand('JustifyLeft'); if (document.queryCommandState("JustifyLeft")) { this.classList.add('selected'); } else { this.classList.remove('selected'); } } }, { icon:'format_align_center', onclick: function() { document.execCommand('justifyCenter'); if (document.queryCommandState("justifyCenter")) { this.classList.add('selected'); } else { this.classList.remove('selected'); } } }, { icon:'format_align_right', onclick: function() { document.execCommand('justifyRight'); if (document.queryCommandState("justifyRight")) { this.classList.add('selected'); } else { this.classList.remove('selected'); } } }, { icon:'format_align_justify', onclick: function() { document.execCommand('justifyFull'); if (document.queryCommandState("justifyFull")) { this.classList.add('selected'); } else { this.classList.remove('selected'); } } }, { icon:'format_list_bulleted', onclick: function() { document.execCommand('insertUnorderedList'); if (document.queryCommandState("insertUnorderedList")) { this.classList.add('selected'); } else { this.classList.remove('selected'); } } }*/ ]; } jSuites.isNumeric = (function (num) { return !isNaN(num) && num != null && num != ''; }); jSuites.guid = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } jSuites.getWindowWidth = function() { var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0], x = w.innerWidth || e.clientWidth || g.clientWidth; return x; } jSuites.getWindowHeight = function() { var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0], y = w.innerHeight|| e.clientHeight|| g.clientHeight; return y; } jSuites.getPosition = function(e) { if (e.changedTouches && e.changedTouches[0]) { var x = e.changedTouches[0].pageX; var y = e.changedTouches[0].pageY; } else { var x = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); var y = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); } return [ x, y ]; } jSuites.click = function(el) { if (el.click) { el.click(); } else { var evt = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); el.dispatchEvent(evt); } } jSuites.findElement = function(element, condition) { var foundElement = false; function path (element) { if (element && ! foundElement) { if (typeof(condition) == 'function') { foundElement = condition(element) } else if (typeof(condition) == 'string') { if (element.classList && element.classList.contains(condition)) { foundElement = element; } } } if (element.parentNode && ! foundElement) { path(element.parentNode); } } path(element); return foundElement; } // Two digits jSuites.two = function(value) { value = '' + value; if (value.length == 1) { value = '0' + value; } return value; } jSuites.sha512 = (function(str) { function int64(msint_32, lsint_32) { this.highOrder = msint_32; this.lowOrder = lsint_32; } var H = [new int64(0x6a09e667, 0xf3bcc908), new int64(0xbb67ae85, 0x84caa73b), new int64(0x3c6ef372, 0xfe94f82b), new int64(0xa54ff53a, 0x5f1d36f1), new int64(0x510e527f, 0xade682d1), new int64(0x9b05688c, 0x2b3e6c1f), new int64(0x1f83d9ab, 0xfb41bd6b), new int64(0x5be0cd19, 0x137e2179)]; var K = [new int64(0x428a2f98, 0xd728ae22), new int64(0x71374491, 0x23ef65cd), new int64(0xb5c0fbcf, 0xec4d3b2f), new int64(0xe9b5dba5, 0x8189dbbc), new int64(0x3956c25b, 0xf348b538), new int64(0x59f111f1, 0xb605d019), new int64(0x923f82a4, 0xaf194f9b), new int64(0xab1c5ed5, 0xda6d8118), new int64(0xd807aa98, 0xa3030242), new int64(0x12835b01, 0x45706fbe), new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, 0xd5ffb4e2), new int64(0x72be5d74, 0xf27b896f), new int64(0x80deb1fe, 0x3b1696b1), new int64(0x9bdc06a7, 0x25c71235), new int64(0xc19bf174, 0xcf692694), new int64(0xe49b69c1, 0x9ef14ad2), new int64(0xefbe4786, 0x384f25e3), new int64(0x0fc19dc6, 0x8b8cd5b5), new int64(0x240ca1cc, 0x77ac9c65), new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), new int64(0x5cb0a9dc, 0xbd41fbd4), new int64(0x76f988da, 0x831153b5), new int64(0x983e5152, 0xee66dfab), new int64(0xa831c66d, 0x2db43210), new int64(0xb00327c8, 0x98fb213f), new int64(0xbf597fc7, 0xbeef0ee4), new int64(0xc6e00bf3, 0x3da88fc2), new int64(0xd5a79147, 0x930aa725), new int64(0x06ca6351, 0xe003826f), new int64(0x14292967, 0x0a0e6e70), new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, 0x9d95b3df), new int64(0x650a7354, 0x8baf63de), new int64(0x766a0abb, 0x3c77b2a8), new int64(0x81c2c92e, 0x47edaee6), new int64(0x92722c85, 0x1482353b), new int64(0xa2bfe8a1, 0x4cf10364), new int64(0xa81a664b, 0xbc423001), new int64(0xc24b8b70, 0xd0f89791), new int64(0xc76c51a3, 0x0654be30), new int64(0xd192e819, 0xd6ef5218), new int64(0xd6990624, 0x5565a910), new int64(0xf40e3585, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), new int64(0x19a4c116, 0xb8d2d0c8), new int64(0x1e376c08, 0x5141ab53), new int64(0x2748774c, 0xdf8eeb99), new int64(0x34b0bcb5, 0xe19b48a8), new int64(0x391c0cb3, 0xc5c95a63), new int64(0x4ed8aa4a, 0xe3418acb), new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, 0xd6b2b8a3), new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), new int64(0x84c87814, 0xa1f0ab72), new int64(0x8cc70208, 0x1a6439ec), new int64(0x90befffa, 0x23631e28), new int64(0xa4506ceb, 0xde82bde9), new int64(0xbef9a3f7, 0xb2c67915), new int64(0xc67178f2, 0xe372532b), new int64(0xca273ece, 0xea26619c), new int64(0xd186b8c7, 0x21c0c207), new int64(0xeada7dd6, 0xcde0eb1e), new int64(0xf57d4f7f, 0xee6ed178), new int64(0x06f067aa, 0x72176fba), new int64(0x0a637dc5, 0xa2c898a6), new int64(0x113f9804, 0xbef90dae), new int64(0x1b710b35, 0x131c471b), new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, 0x9c100d4c), new int64(0x4cc5d4be, 0xcb3e42b6), new int64(0x597f299c, 0xfc657e2a), new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)]; var W = new Array(64); var a, b, c, d, e, f, g, h, i, j; var T1, T2; var charsize = 8; function utf8_encode(str) { return unescape(encodeURIComponent(str)); } function str2binb(str) { var bin = []; var mask = (1 << charsize) - 1; var len = str.length * charsize; for (var i = 0; i < len; i += charsize) { bin[i >> 5] |= (str.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32)); } return bin; } function binb2hex(binarray) { var hex_tab = "0123456789abcdef"; var str = ""; var length = binarray.length * 4; var srcByte; for (var i = 0; i < length; i += 1) { srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8); str += hex_tab.charAt((srcByte >> 4) & 0xF) + hex_tab.charAt(srcByte & 0xF); } return str; } function safe_add_2(x, y) { var lsw, msw, lowOrder, highOrder; lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF); msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16); lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16); msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16); highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); return new int64(highOrder, lowOrder); } function safe_add_4(a, b, c, d) { var lsw, msw, lowOrder, highOrder; lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF); msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16); lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16); msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16); highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); return new int64(highOrder, lowOrder); } function safe_add_5(a, b, c, d, e) { var lsw, msw, lowOrder, highOrder; lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + (e.lowOrder & 0xFFFF); msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + (lsw >>> 16); lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (e.highOrder & 0xFFFF) + (msw >>> 16); msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (e.highOrder >>> 16) + (lsw >>> 16); highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF); return new int64(highOrder, lowOrder); } function maj(x, y, z) { return new int64( (x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder), (x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder) ); } function ch(x, y, z) { return new int64( (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder), (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder) ); } function rotr(x, n) { if (n <= 32) { return new int64( (x.highOrder >>> n) | (x.lowOrder << (32 - n)), (x.lowOrder >>> n) | (x.highOrder << (32 - n)) ); } else { return new int64( (x.lowOrder >>> n) | (x.highOrder << (32 - n)), (x.highOrder >>> n) | (x.lowOrder << (32 - n)) ); } } function sigma0(x) { var rotr28 = rotr(x, 28); var rotr34 = rotr(x, 34); var rotr39 = rotr(x, 39); return new int64( rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder, rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder ); } function sigma1(x) { var rotr14 = rotr(x, 14); var rotr18 = rotr(x, 18); var rotr41 = rotr(x, 41); return new int64( rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder, rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder ); } function gamma0(x) { var rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7); return new int64( rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder, rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder ); } function gamma1(x) { var rotr19 = rotr(x, 19); var rotr61 = rotr(x, 61); var shr6 = shr(x, 6); return new int64( rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder, rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder ); } function shr(x, n) { if (n <= 32) { return new int64( x.highOrder >>> n, x.lowOrder >>> n | (x.highOrder << (32 - n)) ); } else { return new int64( 0, x.highOrder << (32 - n) ); } } var str = utf8_encode(str); var strlen = str.length*charsize; str = str2binb(str); str[strlen >> 5] |= 0x80 << (24 - strlen % 32); str[(((strlen + 128) >> 10) << 5) + 31] = strlen; for (var i = 0; i < str.length; i += 32) { a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4]; f = H[5]; g = H[6]; h = H[7]; for (var j = 0; j < 80; j++) { if (j < 16) { W[j] = new int64(str[j*2 + i], str[j*2 + i + 1]); } else { W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]); } T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]); T2 = safe_add_2(sigma0(a), maj(a, b, c)); h = g; g = f; f = e; e = safe_add_2(d, T1); d = c; c = b; b = a; a = safe_add_2(T1, T2); } H[0] = safe_add_2(a, H[0]); H[1] = safe_add_2(b, H[1]); H[2] = safe_add_2(c, H[2]); H[3] = safe_add_2(d, H[3]); H[4] = safe_add_2(e, H[4]); H[5] = safe_add_2(f, H[5]); H[6] = safe_add_2(g, H[6]); H[7] = safe_add_2(h, H[7]); } var binarray = []; for (var i = 0; i < H.length; i++) { binarray.push(H[i].highOrder); binarray.push(H[i].lowOrder); } return binb2hex(binarray); }); if (! jSuites.login) { jSuites.login = {}; jSuites.login.sha512 = jSuites.sha512; } jSuites.image = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { input: false, minWidth: false, maxWidth: null, maxHeight: null, maxJpegSizeBytes: null, // For example, 350Kb would be 350000 onchange: null, singleFile: true, remoteParser: null, text:{ extensionNotAllowed:'The extension is not allowed', imageTooSmall:'The resolution is too low, try a image with a better resolution. width > 800px', } }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Upload icon el.classList.add('jupload'); if (obj.options.input == true) { el.classList.add('input'); } // Add image obj.addImage = function(file) { if (! file.date) { file.date = ''; } var img = document.createElement('img'); img.setAttribute('data-date', file.lastmodified ? file.lastmodified : file.date); img.setAttribute('data-name', file.name); img.setAttribute('data-size', file.size); img.setAttribute('data-small', file.small ? file.small : ''); img.setAttribute('data-cover', file.cover ? 1 : 0); img.setAttribute('data-extension', file.extension); img.setAttribute('src', file.file); img.className = 'jfile'; img.style.width = '100%'; return img; } // Add image obj.addImages = function(files) { if (obj.options.singleFile == true) { el.innerHTML = ''; } for (var i = 0; i < files.length; i++) { el.appendChild(obj.addImage(files[i])); } } obj.addFromFile = function(file) { var type = file.type.split('/'); if (type[0] == 'image') { if (obj.options.singleFile == true) { el.innerHTML = ''; } var imageFile = new FileReader(); imageFile.addEventListener("load", function (v) { var img = new Image(); img.onload = function onload() { var canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); var data = { file: obj.getDataURL(canvas, file.type), extension: file.name.substr(file.name.lastIndexOf('.') + 1), name: file.name, size: file.size, lastmodified: file.lastModified, } var newImage = obj.addImage(data); el.appendChild(newImage); // Onchange if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(newImage); } }; img.src = v.srcElement.result; }); imageFile.readAsDataURL(file); } else { alert(text.extentionNotAllowed); } } obj.addFromUrl = function(src) { if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) { console.error('remoteParser not defined in your initialization'); } else { // This is to process cross domain images if (src.substr(0,4) == 'data') { var extension = src.split(';') extension = extension[0].split('/'); extension = extension[1]; } else { var extension = src.substr(src.lastIndexOf('.') + 1); // Work for cross browsers src = obj.options.remoteParser + src; } var img = new Image(); img.onload = function onload() { var canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); canvas.toBlob(function(blob) { var data = { file: window.URL.createObjectURL(blob), extension: extension } var newImage = obj.addImage(data); el.appendChild(newImage); // Keep base64 ready to go var content = canvas.toDataURL(); // Onchange if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(newImage); } }); }; img.src = src; } } obj.getCanvas = function(img) { var canvas = document.createElement('canvas'); var r1 = (obj.options.maxWidth || img.width ) / img.width; var r2 = (obj.options.maxHeight || img.height) / img.height; var r = Math.min(r1, r2, 1); canvas.width = img.width * r; canvas.height = img.height * r; return canvas; } obj.getDataURL = function(canvas, type) { var compression = 0.92; var lastContentLength = null; var content = canvas.toDataURL(type, compression); while (obj.options.maxJpegSizeBytes && type === 'image/jpeg' && content.length > obj.options.maxJpegSizeBytes && content.length !== lastContentLength) { // Apply the compression compression *= 0.9; lastContentLength = content.length; content = canvas.toDataURL(type, compression); } return content; } var attachmentInput = document.createElement('input'); attachmentInput.type = 'file'; attachmentInput.setAttribute('accept', 'image/*'); attachmentInput.onchange = function() { for (var i = 0; i < this.files.length; i++) { obj.addFromFile(this.files[i]); } } el.addEventListener("click", function(e) { jSuites.click(attachmentInput); }); el.addEventListener('dragenter', function(e) { el.style.border = '1px dashed #000'; }); el.addEventListener('dragleave', function(e) { el.style.border = '1px solid #eee'; }); el.addEventListener('dragstop', function(e) { el.style.border = '1px solid #eee'; }); el.addEventListener('dragover', function(e) { e.preventDefault(); }); el.addEventListener('drop', function(e) { e.preventDefault(); e.stopPropagation(); var html = (e.originalEvent || e).dataTransfer.getData('text/html'); var file = (e.originalEvent || e).dataTransfer.files; if (file.length) { for (var i = 0; i < e.dataTransfer.files.length; i++) { obj.addFromFile(e.dataTransfer.files[i]); } } else if (html) { if (obj.options.singleFile == true) { el.innerHTML = ''; } // Create temp element var div = document.createElement('div'); div.innerHTML = html; // Extract images var img = div.querySelectorAll('img'); if (img.length) { for (var i = 0; i < img.length; i++) { obj.addFromUrl(img[i].src); } } } el.style.border = '1px solid #eee'; return false; }); el.image = obj; return obj; }); jSuites.lazyLoading = (function(el, options) { var obj = {} // Mandatory options if (! options.loadUp || typeof(options.loadUp) != 'function') { options.loadUp = function() { return false; } } if (! options.loadDown || typeof(options.loadDown) != 'function') { options.loadDown = function() { return false; } } // Timer ms if (! options.timer) { options.timer = 100; } // Timer var timeControlLoading = null; // Controls var scrollControls = function(e) { if (timeControlLoading == null) { var scrollTop = el.scrollTop; if (el.scrollTop + (el.clientHeight * 2) >= el.scrollHeight) { if (options.loadDown()) { if (scrollTop == el.scrollTop) { el.scrollTop = el.scrollTop - (el.clientHeight); } } } else if (el.scrollTop <= el.clientHeight) { if (options.loadUp()) { if (scrollTop == el.scrollTop) { el.scrollTop = el.scrollTop + (el.clientHeight); } } } timeControlLoading = setTimeout(function() { timeControlLoading = null; }, options.timer); } } // Onscroll el.onscroll = function(e) { scrollControls(e); } el.onwheel = function(e) { scrollControls(e); } return obj; }); jSuites.loading = (function() { var obj = {}; var loading = null; obj.show = function() { if (! loading) { loading = document.createElement('div'); loading.className = 'jloading'; } document.body.appendChild(loading); } obj.hide = function() { if (loading) { document.body.removeChild(loading); } } return obj; })(); jSuites.mask = (function() { var obj = {}; var index = 0; var values = [] var pieces = []; /** * Apply a mask over a value considering a custom decimal representation. Default: '.' */ obj.run = function(value, mask, decimal) { if (value.toString().length && mask.toString().length) { // Default decimal separator if (typeof(decimal) == 'undefined') { decimal = '.'; } if (jSuites.isNumeric(value)) { var number = (''+value).split(decimal); var value = number[0]; var valueDecimal = number[1]; } else { value = '' + value; } // Helpers index = 0; values = []; // Create mask token obj.prepare(mask); // Current value var currentValue = value; if (currentValue) { // Checking current value for (var i = 0; i < currentValue.length; i++) { if (currentValue[i] != null) { obj.process(currentValue[i]); } } } if (valueDecimal) { obj.process(decimal); var currentValue = valueDecimal; if (currentValue) { // Checking current value for (var i = 0; i < currentValue.length; i++) { if (currentValue[i] != null) { obj.process(currentValue[i]); } } } } // Formatted value return values.join(''); } else { return ''; } } obj.apply = function(e) { if (e.target && ! e.target.getAttribute('readonly')) { var mask = e.target.getAttribute('data-mask'); if (mask) { index = 0; values = []; // Create mask token obj.prepare(mask); // Current value if (e.target.selectionStart < e.target.selectionEnd) { var currentValue = e.target.value.substring(0, e.target.selectionStart); } else { var currentValue = e.target.value; } if (currentValue) { // Checking current value for (var i = 0; i < currentValue.length; i++) { if (currentValue[i] != null) { obj.process(currentValue[i]); } } } // New input if (e.keyCode > 46) { obj.process(obj.fromKeyCode(e)); // Prevent default e.preventDefault(); } // Update value to the element e.target.value = values.join(''); if (pieces.length == values.length && pieces[pieces.length-1].length == values[values.length-1].length) { e.target.setAttribute('data-completed', 'true'); } else { e.target.setAttribute('data-completed', 'false'); } } } } /** * Process inputs and save to values */ obj.process = function(input) { do { if (pieces[index] == 'mm') { if (values[index] == null || values[index] == '') { if (parseInt(input) > 1 && parseInt(input) < 10) { values[index] = '0' + input; index++; return true; } else if (parseInt(input) < 10) { values[index] = input; return true; } else { return false; } } else { if (values[index] == 1 && values[index] < 2 && parseInt(input) < 3) { values[index] += input; index++; return true; } else if (values[index] == 0 && values[index] < 10) { values[index] += input; index++; return true; } else { return false } } } else if (pieces[index] == 'dd') { if (values[index] == null || values[index] == '') { if (parseInt(input) > 3 && parseInt(input) < 10) { values[index] = '0' + input; index++; return true; } else if (parseInt(input) < 10) { values[index] = input; return true; } else { return false; } } else { if (values[index] == 3 && parseInt(input) < 2) { values[index] += input; index++; return true; } else if (values[index] < 3 && parseInt(input) < 10) { values[index] += input; index++; return true; } else { return false } } } else if (pieces[index] == 'hh24') { if (values[index] == null || values[index] == '') { if (parseInt(input) > 2 && parseInt(input) < 10) { values[index] = '0' + input; index++; return true; } else if (parseInt(input) < 10) { values[index] = input; return true; } else { return false; } } else { if (values[index] == 2 && parseInt(input) < 4) { values[index] += input; index++; return true; } else if (values[index] < 2 && parseInt(input) < 10) { values[index] += input; index++; return true; } else { return false } } } else if (pieces[index] == 'hh') { if (values[index] == null || values[index] == '') { if (parseInt(input) > 1 && parseInt(input) < 10) { values[index] = '0' + input; index++; return true; } else if (parseInt(input) < 10) { values[index] = input; return true; } else { return false; } } else { if (values[index] == 1 && parseInt(input) < 3) { values[index] += input; index++; return true; } else if (values[index] < 1 && parseInt(input) < 10) { values[index] += input; index++; return true; } else { return false } } } else if (pieces[index] == 'mi' || pieces[index] == 'ss') { if (values[index] == null || values[index] == '') { if (parseInt(input) > 5 && parseInt(input) < 10) { values[index] = '0' + input; index++; return true; } else if (parseInt(input) < 10) { values[index] = input; return true; } else { return false; } } else { if (parseInt(input) < 10) { values[index] += input; index++; return true; } else { return false } } } else if (pieces[index] == 'yy' || pieces[index] == 'yyyy') { if (parseInt(input) < 10) { if (values[index] == null || values[index] == '') { values[index] = input; } else { values[index] += input; } if (values[index].length == pieces[index].length) { index++; } return true; } else { return false; } } else if (pieces[index] == '#' || pieces[index] == '#.##' || pieces[index] == '#,##' || pieces[index] == '# ##') { if (input.match(/[0-9]/g)) { if (pieces[index] == '#.##') { var separator = '.'; } else if (pieces[index] == '#,##') { var separator = ','; } else if (pieces[index] == '# ##') { var separator = ' '; } else { var separator = ''; } if (values[index] == null || values[index] == '') { values[index] = input; } else { values[index] += input; if (separator) { values[index] = values[index].match(/[0-9]/g).join(''); var t = []; var s = 0; for (var j = values[index].length - 1; j >= 0 ; j--) { t.push(values[index][j]); s++; if (! (s % 3)) { t.push(separator); } } t = t.reverse(); values[index] = t.join(''); if (values[index].substr(0,1) == separator) { values[index] = values[index].substr(1); } } } return true; } else { if (pieces[index] == '#.##' && input == '.') { // Do nothing } else if (pieces[index] == '#,##' && input == ',') { // Do nothing } else if (pieces[index] == '# ##' && input == ' ') { // Do nothing } else { if (values[index]) { index++; if (pieces[index]) { if (pieces[index] == input) { values[index] = input; return true; } else { if (pieces[index] == '0' && pieces[index+1] == input) { index++; values[index] = input; return true; } } } } } return false; } } else if (pieces[index] == '0') { if (input.match(/[0-9]/g)) { values[index] = input; index++; return true; } else { return false; } } else if (pieces[index] == 'a') { if (input.match(/[a-zA-Z]/g)) { values[index] = input; index++; return true; } else { return false; } } else { if (pieces[index] != null) { if (pieces[index] == '\\a') { var v = 'a'; } else if (pieces[index] == '\\0') { var v = '0'; } else if (pieces[index] == '[-]') { if (input == '-' || input == '+') { var v = input; } else { var v = ' '; } } else { var v = pieces[index]; } values[index] = v; if (input == v) { index++; return true; } } } index++; } while (pieces[index]); } /** * Create tokens for the mask */ obj.prepare = function(mask) { pieces = []; for (var i = 0; i < mask.length; i++) { if (mask[i].match(/[0-9]|[a-z]|\\/g)) { if (mask[i] == 'y' && mask[i+1] == 'y' && mask[i+2] == 'y' && mask[i+3] == 'y') { pieces.push('yyyy'); i += 3; } else if (mask[i] == 'y' && mask[i+1] == 'y') { pieces.push('yy'); i++; } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm' && mask[i+3] == 'm') { pieces.push('mmmm'); i += 3; } else if (mask[i] == 'm' && mask[i+1] == 'm' && mask[i+2] == 'm') { pieces.push('mmm'); i += 2; } else if (mask[i] == 'm' && mask[i+1] == 'm') { pieces.push('mm'); i++; } else if (mask[i] == 'd' && mask[i+1] == 'd') { pieces.push('dd'); i++; } else if (mask[i] == 'h' && mask[i+1] == 'h' && mask[i+2] == '2' && mask[i+3] == '4') { pieces.push('hh24'); i += 3; } else if (mask[i] == 'h' && mask[i+1] == 'h') { pieces.push('hh'); i++; } else if (mask[i] == 'm' && mask[i+1] == 'i') { pieces.push('mi'); i++; } else if (mask[i] == 's' && mask[i+1] == 's') { pieces.push('ss'); i++; } else if (mask[i] == 'a' && mask[i+1] == 'm') { pieces.push('am'); i++; } else if (mask[i] == 'p' && mask[i+1] == 'm') { pieces.push('pm'); i++; } else if (mask[i] == '\\' && mask[i+1] == '0') { pieces.push('\\0'); i++; } else if (mask[i] == '\\' && mask[i+1] == 'a') { pieces.push('\\a'); i++; } else { pieces.push(mask[i]); } } else { if (mask[i] == '#' && mask[i+1] == '.' && mask[i+2] == '#' && mask[i+3] == '#') { pieces.push('#.##'); i += 3; } else if (mask[i] == '#' && mask[i+1] == ',' && mask[i+2] == '#' && mask[i+3] == '#') { pieces.push('#,##'); i += 3; } else if (mask[i] == '#' && mask[i+1] == ' ' && mask[i+2] == '#' && mask[i+3] == '#') { pieces.push('# ##'); i += 3; } else if (mask[i] == '[' && mask[i+1] == '-' && mask[i+2] == ']') { pieces.push('[-]'); i += 2; } else { pieces.push(mask[i]); } } } } /** * Thanks for the collaboration */ obj.fromKeyCode = function(e) { var _to_ascii = { '188': '44', '109': '45', '190': '46', '191': '47', '192': '96', '220': '92', '222': '39', '221': '93', '219': '91', '173': '45', '187': '61', //IE Key codes '186': '59', //IE Key codes '189': '45' //IE Key codes } var shiftUps = { "96": "~", "49": "!", "50": "@", "51": "#", "52": "$", "53": "%", "54": "^", "55": "&", "56": "*", "57": "(", "48": ")", "45": "_", "61": "+", "91": "{", "93": "}", "92": "|", "59": ":", "39": "\"", "44": "<", "46": ">", "47": "?" }; var c = e.which; if (_to_ascii.hasOwnProperty(c)) { c = _to_ascii[c]; } if (!e.shiftKey && (c >= 65 && c <= 90)) { c = String.fromCharCode(c + 32); } else if (e.shiftKey && shiftUps.hasOwnProperty(c)) { c = shiftUps[c]; } else if (96 <= c && c <= 105) { c = String.fromCharCode(c - 48); } else { c = String.fromCharCode(c); } return c; } if (typeof document !== 'undefined') { document.addEventListener('keydown', function(e) { if (jSuites.mask) { jSuites.mask.apply(e); } }); } return obj; })(); jSuites.notification = (function(options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { icon: null, name: 'Notification', date: null, error: null, title: null, message: null, timeout: 4000, autoHide: true, closeable: true, }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } var notification = document.createElement('div'); notification.className = 'jnotification'; if (obj.options.error) { notification.classList.add('jnotification-error'); } var notificationContainer = document.createElement('div'); notificationContainer.className = 'jnotification-container'; notification.appendChild(notificationContainer); var notificationHeader = document.createElement('div'); notificationHeader.className = 'jnotification-header'; notificationContainer.appendChild(notificationHeader); var notificationImage = document.createElement('div'); notificationImage.className = 'jnotification-image'; notificationHeader.appendChild(notificationImage); if (obj.options.icon) { var notificationIcon = document.createElement('img'); notificationIcon.src = obj.options.icon; notificationImage.appendChild(notificationIcon); } var notificationName = document.createElement('div'); notificationName.className = 'jnotification-name'; notificationName.innerHTML = obj.options.name; notificationHeader.appendChild(notificationName); if (obj.options.closeable == true) { var notificationClose = document.createElement('div'); notificationClose.className = 'jnotification-close'; notificationClose.onclick = function() { obj.hide(); } notificationHeader.appendChild(notificationClose); } var notificationDate = document.createElement('div'); notificationDate.className = 'jnotification-date'; notificationHeader.appendChild(notificationDate); var notificationContent = document.createElement('div'); notificationContent.className = 'jnotification-content'; notificationContainer.appendChild(notificationContent); if (obj.options.title) { var notificationTitle = document.createElement('div'); notificationTitle.className = 'jnotification-title'; notificationTitle.innerHTML = obj.options.title; notificationContent.appendChild(notificationTitle); } var notificationMessage = document.createElement('div'); notificationMessage.className = 'jnotification-message'; notificationMessage.innerHTML = obj.options.message; notificationContent.appendChild(notificationMessage); obj.show = function() { document.body.appendChild(notification); if (jSuites.getWindowWidth() > 800) { jSuites.animation.fadeIn(notification); } else { jSuites.animation.slideTop(notification, 1); } } obj.hide = function() { if (jSuites.getWindowWidth() > 800) { jSuites.animation.fadeOut(notification, function() { if (notification.parentNode) { notification.parentNode.removeChild(notification); if (notificationTimeout) { clearTimeout(notificationTimeout); } } }); } else { jSuites.animation.slideTop(notification, 0, function() { if (notification.parentNode) { notification.parentNode.removeChild(notification); if (notificationTimeout) { clearTimeout(notificationTimeout); } } }); } }; obj.show(); if (obj.options.autoHide == true) { var notificationTimeout = setTimeout(function() { obj.hide(); }, obj.options.timeout); } if (jSuites.getWindowWidth() < 800) { notification.addEventListener("swipeup", function(e) { obj.hide(); e.preventDefault(); e.stopPropagation(); }); } return obj; }); jSuites.notification.isVisible = function() { var j = document.querySelector('.jnotification'); return j && j.parentNode ? true : false; } jSuites.picker = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { value: null, data: null, render: null, onchange: null, width: null, header: true, right: false, content: false, }; // Loop through the initial configuration for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Legacy purpose only if (options.options) { obj.options.data = options.options; } // Default value if (obj.options.value === null) { obj.options.value = Object.keys(obj.options.data)[0]; } var dropdownHeader = null; var dropdownContent = null; // Class el.classList.add('jpicker'); el.setAttribute('tabindex', '900'); /** * Create floating picker */ obj.init = function() { // Dropdown Header dropdownHeader = document.createElement('div'); dropdownHeader.classList.add('jpicker-header'); if (obj.options.header === false) { dropdownHeader.style.display = 'none'; } // Width if (obj.options.width) { dropdownHeader.style.width = parseInt(obj.options.width) + 'px'; } // Start value dropdownHeader.innerHTML = obj.options.value && obj.options.data[obj.options.value] ? obj.options.data[obj.options.value] : '

'; // Dropdown content dropdownContent = document.createElement('div'); dropdownContent.classList.add('jpicker-content'); el.appendChild(dropdownHeader); el.appendChild(dropdownContent); // Create items var keys = Object.keys(obj.options.data); // Go though all options for (var i = 0; i < keys.length; i++) { // Item var dropdownItem = document.createElement('div'); dropdownItem.k = keys[i]; dropdownItem.v = obj.options.data[keys[i]]; // Label dropdownItem.innerHTML = obj.getLabel(keys[i]); // Onchange dropdownItem.onclick = function() { // Update label obj.setValue(this.k); // Call method if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, obj, this.v, this.k); } } // Append dropdownContent.appendChild(dropdownItem); } // Initial value obj.setValue(obj.options.value); } obj.setValue = function(v) { if (obj.options.content) { var label = '' + obj.options.content + ''; } else { var label = obj.getLabel(v); } dropdownHeader.innerHTML = label; } obj.getLabel = function(v) { var label = obj.options.data[v]; if (typeof(obj.options.render) == 'function') { label = obj.options.render(label); } return label; } obj.open = function() { // Open picker el.classList.add('jpicker-focus'); el.focus(); var rectHeader = dropdownHeader.getBoundingClientRect(); var rectContent = dropdownContent.getBoundingClientRect(); if (window.innerHeight < rectHeader.bottom + rectContent.height) { dropdownContent.style.marginTop = -1 * (rectContent.height + 4) + 'px'; } else { dropdownContent.style.marginTop = rectHeader.height + 2 + 'px'; } if (obj.options.right === true) { dropdownContent.style.marginLeft = -1 * rectContent.width + 24 + 'px'; } } el.onclick = function() { if (! el.classList.contains('jpicker-focus')) { obj.open(); } else { el.classList.remove('jpicker-focus') } } el.onblur = function() { setTimeout(function() { el.classList.remove('jpicker-focus'); }, 250); } obj.init(); el.picker = obj; return obj; }); jSuites.rating = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { number: 5, value: 0, tooltip: [ 'Very bad', 'Bad', 'Average', 'Good', 'Very good' ], onchange: null, }; // Loop through the initial configuration for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Class el.classList.add('jrating'); // Add elements for (var i = 0; i < obj.options.number; i++) { var div = document.createElement('div'); div.setAttribute('data-index', (i + 1)) div.setAttribute('title', obj.options.tooltip[i]) el.appendChild(div); } // Set value obj.setValue = function(index) { for (var i = 0; i < obj.options.number; i++) { if (i < index) { el.children[i].classList.add('jrating-selected'); } else { el.children[i].classList.remove('jrating-over'); el.children[i].classList.remove('jrating-selected'); } } obj.options.value = index; if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, index); } } obj.getValue = function() { return obj.options.value; } if (obj.options.value) { for (var i = 0; i < obj.options.number; i++) { if (i < obj.options.value) { el.children[i].classList.add('jrating-selected'); } } } // Events el.addEventListener("click", function(e) { var index = e.target.getAttribute('data-index'); if (index != undefined) { if (index == obj.options.value) { obj.setValue(0); } else { obj.setValue(index); } } }); el.addEventListener("mouseover", function(e) { var index = e.target.getAttribute('data-index'); for (var i = 0; i < obj.options.number; i++) { if (i < index) { el.children[i].classList.add('jrating-over'); } else { el.children[i].classList.remove('jrating-over'); } } }); el.addEventListener("mouseout", function(e) { for (var i = 0; i < obj.options.number; i++) { el.children[i].classList.remove('jrating-over'); } }); el.rating = obj; return obj; }); /** * (c) jTools v1.0.1 - Element sorting * https://github.com/paulhodel/jtools * * @author: Paul Hodel * @description: Element drag and drop sorting */ jSuites.sorting = (function(el, options) { var obj = {}; obj.options = {}; var defaults = { pointer: null, direction: null, ondragstart: null, ondragend: null, ondrop: null, } var dragElement = null; // Loop through the initial configuration for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } el.classList.add('jsorting'); el.addEventListener('dragstart', function(e) { var position = Array.prototype.indexOf.call(e.target.parentNode.children, e.target); dragElement = { element: e.target, o: position, d: position } e.target.style.opacity = '0.25'; if (typeof(obj.options.ondragstart) == 'function') { obj.options.ondragstart(el, e.target, e); } }); el.addEventListener('dragover', function(e) { e.preventDefault(); if (getElement(e.target) && dragElement) { if (e.target.getAttribute('draggable') == 'true' && dragElement.element != e.target) { if (! obj.options.direction) { var condition = e.target.clientHeight / 2 > e.offsetY; } else { var condition = e.target.clientWidth / 2 > e.offsetX; } if (condition) { e.target.parentNode.insertBefore(dragElement.element, e.target); } else { e.target.parentNode.insertBefore(dragElement.element, e.target.nextSibling); } dragElement.d = Array.prototype.indexOf.call(e.target.parentNode.children, dragElement.element); } } }); el.addEventListener('dragleave', function(e) { e.preventDefault(); }); el.addEventListener('dragend', function(e) { e.preventDefault(); if (dragElement) { if (typeof(obj.options.ondragend) == 'function') { obj.options.ondragend(el, dragElement.element, e); } // Cancelled put element to the original position if (dragElement.o < dragElement.d) { e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o]); } else { e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o].nextSibling); } dragElement.element.style.opacity = ''; dragElement = null; } }); el.addEventListener('drop', function(e) { e.preventDefault(); if (dragElement && (dragElement.o != dragElement.d)) { if (typeof(obj.options.ondrop) == 'function') { obj.options.ondrop(el, dragElement.o, dragElement.d, dragElement.element, e.target, e); } } dragElement.element.style.opacity = ''; dragElement = null; }); var getElement = function(element) { var sorting = false; function path (element) { if (element.className) { if (element.classList.contains('jsorting')) { sorting = true; } } if (! sorting) { path(element.parentNode); } } path(element); return sorting; } for (var i = 0; i < el.children.length; i++) { if (! el.children[i].hasAttribute('draggable')) { el.children[i].setAttribute('draggable', 'true'); } } return el; }); jSuites.tabs = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { data: [], position: null, allowCreate: false, allowChangePosition: false, onclick: null, onload: null, onchange: null, oncreate: null, ondelete: null, onbeforecreate: null, onchangeposition: null, animation: false, hideHeaders: false, padding: null, } // Loop through the initial configuration for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Class el.classList.add('jtabs'); var prev = null; var next = null; var border = null; // Helpers var setBorder = function(index) { var rect = obj.headers.children[index].getBoundingClientRect(); border.style.width = rect.width + 'px'; border.style.left = (obj.headers.children[index].offsetLeft) + 'px'; border.style.bottom = '0px'; } var updateControls = function(x) { if (typeof(obj.headers.scrollTo) == 'function') { obj.headers.scrollTo({ left: x, behavior: 'smooth', }); } else { obj.headers.scrollLeft = x; } if (x <= 1) { prev.classList.add('disabled'); } else { prev.classList.remove('disabled'); } if (x >= obj.headers.scrollWidth - obj.headers.offsetWidth) { next.classList.add('disabled'); } else { next.classList.remove('disabled'); } if (obj.headers.scrollWidth <= obj.headers.offsetWidth) { prev.style.display = 'none'; next.style.display = 'none'; } else { prev.style.display = ''; next.style.display = ''; } } // Set value obj.open = function(index) { var previous = null; for (var i = 0; i < obj.headers.children.length; i++) { if (obj.headers.children[i].classList.contains('jtabs-selected')) { // Current one previous = i; // Remote selected obj.headers.children[i].classList.remove('jtabs-selected'); if (obj.content.children[i]) { obj.content.children[i].classList.remove('jtabs-selected'); } } } obj.headers.children[index].classList.add('jtabs-selected'); if (obj.content.children[index]) { obj.content.children[index].classList.add('jtabs-selected'); } if (previous != index && typeof(obj.options.onchange) == 'function') { if (obj.content.children[index]) { obj.options.onchange(el, obj, index, obj.headers.children[index], obj.content.children[index]); } } // Hide if (obj.options.hideHeaders == true && (obj.headers.children.length < 3 && obj.options.allowCreate == false)) { obj.headers.parentNode.style.display = 'none'; } else { obj.headers.parentNode.style.display = ''; // Set border if (obj.options.animation == true) { setBorder(index); } var x1 = obj.headers.children[index].offsetLeft; var x2 = x1 + obj.headers.children[index].offsetWidth; var r1 = obj.headers.scrollLeft; var r2 = r1 + obj.headers.offsetWidth; if (! (r1 <= x1 && r2 >= x2)) { // Out of the viewport updateControls(x1 - 1); } } } obj.selectIndex = function(a) { var index = Array.prototype.indexOf.call(obj.headers.children, a); if (index >= 0) { obj.open(index); } return index; } obj.rename = function(i, title) { if (! title) { title = prompt('New title', obj.headers.children[i].innerText); } obj.headers.children[i].innerText = title; obj.open(i); } obj.create = function(title, url) { if (typeof(obj.options.onbeforecreate) == 'function') { var ret = obj.options.onbeforecreate(el); if (ret === false) { return false; } else { title = ret; } } var div = obj.appendElement(title); if (typeof(obj.options.oncreate) == 'function') { obj.options.oncreate(el, div) } return div; } obj.remote = function(index) { return obj.deleteElement(index); } obj.nextNumber = function() { var num = 0; for (var i = 0; i < obj.headers.children.length; i++) { var tmp = obj.headers.children[i].innerText.match(/[0-9].*/); if (tmp > num) { num = parseInt(tmp); } } if (! num) { num = 1; } else { num++; } return num; } obj.deleteElement = function(index) { if (! obj.headers.children[index]) { return false; } else { obj.headers.removeChild(obj.headers.children[index]); obj.content.removeChild(obj.content.children[index]); } obj.open(0); if (typeof(obj.options.ondelete) == 'function') { obj.options.ondelete(el, index) } } obj.appendElement = function(title) { if (! title) { var title = prompt('Title?', ''); } if (title) { // Add content var div = document.createElement('div'); obj.content.appendChild(div); // Add headers var h = document.createElement('div'); h.innerHTML = title; h.content = div; obj.headers.insertBefore(h, obj.headers.lastChild); // Sortable if (obj.options.allowChangePosition) { h.setAttribute('draggable', 'true'); } // Open new tab obj.selectIndex(h); // Return element return div; } } obj.init = function() { el.innerHTML = ''; // Make sure the component is blank obj.headers = document.createElement('div'); obj.content = document.createElement('div'); obj.headers.classList.add('jtabs-headers'); obj.content.classList.add('jtabs-content'); // Padding if (obj.options.padding) { obj.content.style.padding = parseInt(obj.options.padding) + 'px'; } // Header var header = document.createElement('div'); header.className = 'jtabs-headers-container'; header.appendChild(obj.headers); // Controls var controls = document.createElement('div'); controls.className = 'jtabs-controls'; controls.setAttribute('draggable', 'false'); header.appendChild(controls); // Append DOM elements el.appendChild(header); el.appendChild(obj.content); // New button if (obj.options.allowCreate == true) { var add = document.createElement('div'); add.className = 'jtabs-add'; add.onclick = function() { obj.create(); } controls.appendChild(add); } prev = document.createElement('div'); prev.className = 'jtabs-prev'; prev.onclick = function() { updateControls(obj.headers.scrollLeft - obj.headers.offsetWidth); } controls.appendChild(prev); next = document.createElement('div'); next.className = 'jtabs-next'; next.onclick = function() { updateControls(obj.headers.scrollLeft + obj.headers.offsetWidth); } controls.appendChild(next); // Data for (var i = 0; i < obj.options.data.length; i++) { var headerItem = document.createElement('div'); var contentItem = document.createElement('div'); headerItem.innerText = obj.options.data[i].title; contentItem.innerHTML = obj.options.data[i].content; obj.headers.appendChild(headerItem); obj.content.appendChild(contentItem); } // Animation border = document.createElement('div'); border.className = 'jtabs-border'; obj.headers.appendChild(border); if (obj.options.animation) { el.classList.add('jtabs-animation'); } // Events obj.headers.addEventListener("click", function(e) { var index = obj.selectIndex(e.target); if (typeof(obj.options.onclick) == 'function') { obj.options.onclick(el, obj, index, obj.headers.children[index], obj.content.children[index]); } }); obj.headers.addEventListener("contextmenu", function(e) { obj.selectIndex(e.target); }); if (obj.headers.children.length) { // Open first tab obj.open(0); } // Update controls updateControls(0); if (obj.options.allowChangePosition == true) { jSuites.sorting(obj.headers, { direction: 1, ondrop: function(a,b,c,d,e,f) { // Ondrop update position of content if (b > c) { obj.content.insertBefore(obj.content.children[b], obj.content.children[c]); } else { obj.content.insertBefore(obj.content.children[b], obj.content.children[c].nextSibling); } // Open destination tab obj.open(c); // Call event if (typeof(obj.options.onchangeposition) == 'function') { obj.options.onchangeposition(a,b,c,d,e,f); } }, }); } if (typeof(obj.options.onload) == 'function') { obj.options.onload(el, obj); } } // Loading existing nodes as the data if (el.children[0] && el.children[1]) { // Create from existing elements for (var i = 0; i < el.children[0].children.length; i++) { if (el.children[1].children[i] && el.children[0].children[i].innerHTML) { var title = el.children[0].children[i].innerText; var content = el.children[1].children[i].innerHTML; } else { var title = 'Tab ' + (i + 1); var content = el.children[0].children[i].innerHTML; } obj.options.data.push({ title: title, content: content }); } } // Remote controller flag var loadingRemoteData = false; // Create from data if (obj.options.data) { // Append children for (var i = 0; i < obj.options.data.length; i++) { if (obj.options.data[i].url) { jSuites.ajax({ url: obj.options.data[i].url, type: 'GET', dataType: 'text/html', index: i, success: function(result) { obj.options.data[this.index].content = result; }, complete: function() { obj.init(); } }); // Flag loading loadingRemoteData = true; } } } if (! loadingRemoteData) { obj.init(); } el.tabs = obj; return obj; }); jSuites.toolbar = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { app: null, container: false, badge: false, title: false, items: [], } // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } if (! el && options.app && options.app.el) { el = document.createElement('div'); options.app.el.appendChild(el); } obj.selectItem = function(element) { var elements = toolbarContent.children; for (var i = 0; i < elements.length; i++) { if (element != elements[i]) { elements[i].classList.remove('jtoolbar-selected'); } } element.classList.add('jtoolbar-selected'); } obj.hide = function() { jSuites.animation.slideBottom(el, 0, function() { el.style.display = 'none'; }); } obj.show = function() { el.style.display = ''; jSuites.animation.slideBottom(el, 1); } obj.get = function() { return el; } obj.setBadge = function(index, value) { toolbarContent.children[index].children[1].firstChild.innerHTML = value; } obj.destroy = function() { toolbar.remove(); el.innerHTML = ''; } var toggleState = function() { if (this.classList.contains('jtoolbar-active')) { this.classList.remove('jtoolbar-active'); } else { this.classList.add('jtoolbar-active'); } } obj.create = function(items) { // Reset anything in the toolbar toolbarContent.innerHTML = ''; // Create elements in the toolbar for (var i = 0; i < items.length; i++) { var toolbarItem = document.createElement('div'); toolbarItem.classList.add('jtoolbar-item'); if (items[i].width) { toolbarItem.style.width = parseInt(items[i].width) + 'px'; } if (items[i].k) { toolbarItem.k = items[i].k; } if (items[i].tooltip) { toolbarItem.setAttribute('title', items[i].tooltip); } // Id if (items[i].id) { toolbarItem.setAttribute('id', items[i].id); } // Selected if (items[i].state) { toolbarItem.toggleState = toggleState; } if (items[i].active) { toolbarItem.classList.add('jtoolbar-active'); } if (items[i].type == 'select' || items[i].type == 'dropdown') { if (typeof(items[i].onchange) == 'function') { // Event for picker has different arguments items[i].onchange = (function(o) { return function(a,b,c,d) { o(el, obj, a, c, d); } })(items[i].onchange); } jSuites.picker(toolbarItem, items[i]); } else if (items[i].type == 'divisor') { toolbarItem.classList.add('jtoolbar-divisor'); } else if (items[i].type == 'label') { toolbarItem.classList.add('jtoolbar-label'); toolbarItem.innerHTML = items[i].content; } else { // Material icons var toolbarIcon = document.createElement('i'); if (typeof(items[i].class) === 'undefined') { toolbarIcon.classList.add('material-icons'); } else { var c = items[i].class.split(' '); for (var j = 0; j < c.length; j++) { toolbarIcon.classList.add(c[j]); } } toolbarIcon.innerHTML = items[i].content ? items[i].content : ''; toolbarItem.appendChild(toolbarIcon); // Badge options if (obj.options.badge == true) { var toolbarBadge = document.createElement('div'); toolbarBadge.classList.add('jbadge'); var toolbarBadgeContent = document.createElement('div'); toolbarBadgeContent.innerHTML = items[i].badge ? items[i].badge : ''; toolbarBadge.appendChild(toolbarBadgeContent); toolbarItem.appendChild(toolbarBadge); } // Title if (items[i].title) { if (obj.options.title == true) { var toolbarTitle = document.createElement('span'); toolbarTitle.innerHTML = items[i].title; toolbarItem.appendChild(toolbarTitle); } else { toolbarItem.setAttribute('title', items[i].title); } } if (obj.options.app && items[i].route) { // Route toolbarItem.route = items[i].route; // Onclick for route toolbarItem.onclick = function() { obj.options.app.pages(this.route); } // Create pages obj.options.app.pages(items[i].route, { toolbarItem: toolbarItem, closed: true }); } } if (items[i].onclick) { toolbarItem.onclick = (function (a) { return function () { items[a].onclick(el, obj, this); }; })(i); } toolbarContent.appendChild(toolbarItem); } } el.classList.add('jtoolbar'); if (obj.options.container == true) { el.classList.add('jtoolbar-container'); } el.innerHTML = ''; el.onclick = function(e) { var element = jSuites.findElement(e.target, 'jtoolbar-item'); if (element) { obj.selectItem(element); } } var toolbarContent = document.createElement('div'); el.appendChild(toolbarContent); if (obj.options.app) { el.classList.add('jtoolbar-mobile'); } obj.create(obj.options.items); el.toolbar = obj; return obj; }); return jSuites; })));