/** * (c) jSuites Javascript Web Components (v3.9.3) * * Website: https://jsuites.net * Description: Create amazing web based applications. * * MIT License * */ ;(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : global.jSuites = factory(); }(this, (function () { 'use strict'; jSuites.crop = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { area: [ 800, 600 ], crop: [ 200, 150 ], value: null, onload: null, onchange: null, remoteParser: null, allowResize: true, text: { extensionNotAllowed:'The extension is not allowed', 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]; } } // Default for mobile if (jSuites.getWindowWidth() < 800) { if (! obj.options.area[0]) { obj.options.area[0] = window.clientWidth * 2; } if (! obj.options.area[1]) { obj.options.area[1] = window.clientHeight * 2; } } el.classList.add('jcrop'); // Upload icon el.classList.add('jupload'); // Area el.style.width = obj.options.area[0] + 'px'; el.style.height = obj.options.area[1] + 'px'; // Area do crop var crop = document.createElement('div'); crop.classList.add('jcrop-area'); el.appendChild(crop); // Canvas editor var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); el.appendChild(canvas); // Image var drawImage = function() { if (el.clientHeight > image.height) { var pointY = (el.clientHeight - image.height) / 2; } else { var pointY = 0; } if (el.clientWidth > image.width) { var pointX = (el.clientWidth - image.width) / 2; } else { var pointX = 0; } image.left = pointX; image.top = pointY; context.translate(pointX, pointY); context.drawImage(image, 0, 0, image.width, image.height); } var image = new Image(); image.onload = function onload() { obj.resetCanvas(); var w = obj.options.area[0] / this.naturalWidth; var h = obj.options.area[1] / this.naturalHeight; // Proportion var p = this.naturalHeight > this.naturalWidth ? h : w; // Image size this.width = this.naturalWidth * p; this.height = this.naturalHeight * p; // Do adjustment canvas.width = obj.options.area[0]; canvas.height = obj.options.area[1]; if (this.width > canvas.width) { canvas.width = this.width; } if (this.height > canvas.height) { canvas.height = this.height; } drawImage(); // Edition model el.classList.add('jcrop_edition'); // Reset selection on desktop only if (jSuites.getWindowWidth() > 800) { obj.resetCropSelection(); } else { crop.classList.add('mobile'); } // Onchange if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, image); } }; // Properties var properties = { zoom: { origin: { x: null, y: null, }, scale: 1, }, contrast: 0, brightness: 0, rotate: 0, saturation: 0, }; var secondCanvas = document.createElement('canvas'); var secondContext = secondCanvas.getContext('2d'); var secondImage = document.createElement('img'); // Reload filters var refreshFilters = function() { secondCanvas.width = image.width; secondCanvas.height = image.height; secondContext.clearRect(0, 0, secondContext.width, secondContext.height); secondImage.width = secondCanvas.width; secondImage.height = secondCanvas.height; if (image) { //drawImage(); secondContext.drawImage(image, 0, 0, image.width, image.height); } // Performs the contrast, if its value is different from the initial if (properties.contrast) { runContrast(); } // Performs the brightness, if its value is different from the initial if (properties.brightness) { runBrightness(); } if (properties.greyScale) { runGreyScale(); } if (properties.saturation) { runSaturation(); } secondImage.src = secondCanvas.toDataURL(obj.getImageType); secondImage.onload = function() { context.drawImage(secondImage, 0, 0, secondImage.width, secondImage.height); } } /** * Reset crop to the initial conditions */ obj.resetCropSelection = function() { crop.style.left = (obj.options.area[0]/2 - obj.options.crop[0]/2) + 'px'; crop.style.top = (obj.options.area[1]/2 - obj.options.crop[1]/2) + 'px'; crop.style.width = obj.options.crop[0] + 'px'; crop.style.height = obj.options.crop[1] + 'px'; crop.style.zIndex = 1; } obj.getCropSelection = function() { obj.getSelectionCoordinates(); } // Reset canvas obj.resetCanvas = function() { context.setTransform(1, 0, 0, 1, 0, 0); context.clearRect(0,0,canvas.width,canvas.height); } // Reset all the properties obj.reset = function() { // Reset canvas obj.resetCanvas(); // Reset state properties = { zoom: { origin: { x: null, y: null }, scale: 1, }, contrast: 0, brightness: 0, rotate: 0, greyScale: 0, saturation: 0, } // Stop edition el.classList.remove('jcrop_edition') } // Apply the contrast on the image data var runContrast = function() { var contrast = properties.contrast; var imageData = secondContext.getImageData(0, 0, secondCanvas.width, secondCanvas.height); var data = imageData.data; // Note: original dataset modified directly! contrast *= 255; var factor = (contrast + 255) / (255.01 - contrast); //add .1 to avoid /0 error. for (var i = 0; i < data.length; i+=4) { data[i] = factor * (data[i] - 128) + 128; data[i+1] = factor * (data[i+1] - 128) + 128; data[i+2] = factor * (data[i+2] - 128) + 128; } secondContext.putImageData(imageData, 0, 0); return imageData; //optional (e.g. for filter function chaining) } // Change the contrast and apply that to the image obj.contrast = function(val) { // contrast input as percent; range [-1..1] if (! Number.isNaN(parseFloat(val))) { properties.contrast = val; } refreshFilters(); } // Apply the brightness on the image data var runBrightness = function () { // brightness input as percent; range [-1..1] var brightness = properties.brightness; var imageData = secondContext.getImageData(0, 0, secondCanvas.width, secondCanvas.height); var data = imageData.data; // Note: original dataset modified directly! brightness *= 255; for (var i = 0; i < data.length; i+=4) { data[i] += brightness; data[i+1] += brightness; data[i+2] += brightness; } secondContext.putImageData(imageData, 0, 0); return imageData; //optional (e.g. for filter function chaining) } // Change the brightness and apply that to the image obj.brightness = function(val) { if (! Number.isNaN(parseFloat(val))) { properties.brightness = val; } refreshFilters(); } /** * Returns the current image type */ obj.getImageType = function() { var dataType = image.src.substr(0,20); if(dataType.includes('data')){ return dataType.split('/')[1].split(';')[0]; } return null; } /** * Returns cropped area coordinates */ obj.getSelectionCoordinates = function() { return { left: crop.offsetLeft, top: crop.offsetTop, right: crop.offsetLeft + crop.clientWidth, bottom: crop.offsetTop + crop.clientHeight } } /** * Returns cropped image on canvas */ obj.getCroppedImage = function() { return jSuites.image.create({ extension: obj.getImageType(), file: obj.getCroppedContent(), name: '', size: '', }); } /** * Get cropped base64 content */ obj.getCroppedContent = function() { var coordinates = obj.getSelectionCoordinates(); var canvasCropped = document.createElement('canvas'); var contextCropped = canvasCropped.getContext('2d'); canvasCropped.width = crop.clientWidth; canvasCropped.height = crop.clientHeight; // Get cropped selection var imageData = context.getImageData(coordinates.left, coordinates.top, crop.clientWidth, crop.clientHeight); contextCropped.putImageData(imageData,0,0); return canvasCropped.toDataURL(obj.getImageType()); } /** * Get cropped as blob */ obj.getCroppedAsBlob = function(callback) { if (! typeof(callback) == 'function') { console.error('Callback not defined') return false; } var coordinates = obj.getSelectionCoordinates(); var canvasCropped = document.createElement('canvas'); var contextCropped = canvasCropped.getContext('2d'); canvasCropped.width = crop.clientWidth; canvasCropped.height = crop.clientHeight; // Get cropped selection var imageData = context.getImageData(coordinates.left, coordinates.top, crop.clientWidth, crop.clientHeight); contextCropped.putImageData(imageData,0,0); // Callback canvasCropped.toBlob(callback); } /** * Returns the current image on canvas */ obj.getImage = function() { return image; } /** * Returns the attachment input */ obj.getFileInput = function() { return attachmentInput; } /** * Returns the current canvas */ obj.getCanvas = function() { return canvas; } /** * Load a image from the computer */ obj.addFromFile = function(file) { var type = file.type.split('/'); if (type[0] == 'image') { var imageFile = new FileReader(); imageFile.addEventListener("load", function (v) { image.src = v.srcElement.result; }); imageFile.readAsDataURL(file); } else { alert(text.extentionNotAllowed); } } /** * Load a image from a remote URL */ obj.addFromUrl = function(src) { if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) { console.error('remoteParser not defined in your initialization'); } else { src = obj.options.remoteParser + src; image.src = src; } } // Runs image movements var runMove = function() { context.translate(image.left, image.top); } // Reload resizers and filters var refreshResizers = function() { // Clear canvas context.setTransform(1, 0, 0, 1, 0, 0); context.clearRect(0, 0, canvas.width, canvas.height); runMove(); // Performs the zoom, if its value is different from the initial if (properties.zoom.scale !== 1) { runZoom(); } // Performs the rotation, if its value is different from the initial if (properties.rotate) { runRotate(); } // Calls the filter reloader if (properties.brightness || properties.contrast) { context.drawImage(secondImage, 0, 0, secondImage.width, secondImage.height); } else { context.drawImage(image, 0, 0, image.width, image.height); } } // Apply the zoom on the image var runZoom = function() { context.translate((properties.zoom.origin.x - image.left), (properties.zoom.origin.y - image.top)); context.scale(properties.zoom.scale, properties.zoom.scale); context.translate(-(properties.zoom.origin.x - image.left), -(properties.zoom.origin.y - image.top)); } /** * Change the zoom and apply that to the image * @param mixed value / null to refresh or int for a new percentage of zoom */ obj.zoom = function(value) { if (value) { properties.zoom.scale = value; } refreshResizers(); } // Apply the rotations on the image var runRotate = function() { var value = properties.rotate; value *= 180; context.translate(image.width / 2, image.height / 2); context.rotate(value * Math.PI / 180); context.translate(- image.width / 2, - image.height / 2); } // Change the rotation and apply that to the image obj.rotate = function(val) { // rotate input as percent; range [-1..1] if (! Number.isNaN(parseFloat(val))) { properties.rotate = val; } refreshResizers(); } // HTML element to load a image from the computer var attachmentInput = document.createElement('input'); attachmentInput.type = 'file'; attachmentInput.setAttribute('accept', 'image/*'); attachmentInput.onchange = function() { for (var i = 0; i < this.files.length; i++) { obj.addFromFile(this.files[i]); } } /** Events start here **/ var editorAction = null; var editorMouseUp = function(e) { editorAction = false; } var editorMouseDown = function(e) { if (e.target.classList.contains('jcrop-area')) { var rect = e.target.getBoundingClientRect(); var offsetX = (e.target.style.left !== '') ? e.target.style.left : '0px'; var offsetY = (e.target.style.top !== '') ? e.target.style.top : '0px'; if (e.target.style.cursor) { editorAction = { e: e.target, x: e.clientX, y: e.clientY, w: rect.width, h: rect.height, d: e.target.style.cursor, xOffset: e.clientX - parseInt(offsetX.slice(0, offsetX.length - 2)), yOffset: e.clientY - parseInt(offsetY.slice(0, offsetY.length - 2)), } if (! e.target.style.width) { e.target.style.width = rect.width + 'px'; } if (! e.target.style.height) { e.target.style.height = rect.height + 'px'; } var s = window.getSelection(); if (s.rangeCount) { for (var i = 0; i < s.rangeCount; i++) { s.removeRange(s.getRangeAt(i)); } } } else { e.target.style.cursor = 'move'; // Tracking for moving editorAction = { e: e.target, x: e.clientX, y: e.clientY, w: rect.width, h: rect.height, d: e.target.style.cursor, xOffset: e.clientX - parseInt(offsetX.slice(0, offsetX.length - 2)), yOffset: e.clientY - parseInt(offsetY.slice(0, offsetY.length - 2)), } } } else { editorAction = true; } } var editorMouseMove = function(e) { if (e.target.classList.contains('jcrop-area') && obj.options.allowResize == true) { 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 { if (! e.which) { e.target.style.cursor = ''; } } } // Change position or size if (e.which == 1 && editorAction && editorAction.d) { if (editorAction.d == 'move') { // Change the position of the cropper var cropOffsetX = e.clientX - editorAction.xOffset; var cropOffsetY = e.clientY - editorAction.yOffset; if (cropOffsetX < 0) { editorAction.e.style.left = '0px'; } else if (cropOffsetX > el.offsetWidth - crop.offsetWidth - 2) { editorAction.e.style.left = el.offsetWidth - crop.offsetWidth - 2 + 'px'; } else { editorAction.e.style.left = cropOffsetX + 'px'; } if (cropOffsetY < 0) { editorAction.e.style.top = '0px'; } else if (cropOffsetY > el.offsetHeight - crop.offsetHeight - 2){ editorAction.e.style.top = el.offsetHeight - crop.offsetHeight - 2 + 'px'; } else { editorAction.e.style.top = cropOffsetY + 'px'; } } else { // Change the size of the cropper if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') { // Handles size changes involving the right side of the cropper var newWidth = editorAction.w + e.clientX - editorAction.x; var offset = editorAction.e.style.left.slice(0, editorAction.e.style.left.length - 2); if (newWidth < obj.options.crop[0]) { editorAction.e.style.width = obj.options.crop[0] + 'px'; } else if (newWidth + parseInt(offset) > el.offsetWidth - 2) { editorAction.e.style.width = el.offsetWidth - offset - 2 + 'px'; } else { editorAction.e.style.width = editorAction.w + e.clientX - editorAction.x + 'px'; } } else if (editorAction.d == 'w-resize' || editorAction.d == 'nw-resize' || editorAction.d == 'sw-resize') { // Handles size changes involving the left side of the cropper var newOffset = e.clientX - editorAction.xOffset; var newWidth = editorAction.x + editorAction.w - e.clientX; if (newWidth < obj.options.crop[0]) { editorAction.e.style.left = editorAction.x + editorAction.w - obj.options.crop[0] - editorAction.xOffset + 'px'; editorAction.e.style.width = obj.options.crop[0] + 'px'; } else if (newOffset < 0) { editorAction.e.style.left = '0px'; editorAction.e.style.width = editorAction.x + editorAction.w - editorAction.xOffset + 'px'; } else { editorAction.e.style.left = newOffset + 'px'; editorAction.e.style.width = newWidth + 'px'; } } if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') { // Handles size changes involving the top side of the cropper var newHeight = editorAction.h + e.clientY - editorAction.y; var offset = editorAction.e.style.top.slice(0, editorAction.e.style.top.length - 2); if (newHeight < obj.options.crop[1]) { editorAction.e.style.height = obj.options.crop[1] + 'px'; } else if (newHeight + parseInt(offset) > el.offsetHeight - 2) { editorAction.e.style.height = el.offsetHeight - parseInt(offset) - 2 + 'px'; } else { editorAction.e.style.height = newHeight + 'px'; } } else if (editorAction.d == 'n-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'nw-resize') { // Handles size changes involving the bottom side of the cropper var newOffset = e.clientY - editorAction.yOffset; var newHeight = editorAction.h + editorAction.y - e.clientY; if (newHeight < obj.options.crop[1]) { editorAction.e.style.top = editorAction.y + editorAction.h - obj.options.crop[1] - editorAction.yOffset + 'px'; editorAction.e.style.height = obj.options.crop[1] + 'px'; } else if (newOffset < 0) { editorAction.e.style.top = '0px'; editorAction.e.style.height = editorAction.y + editorAction.h - editorAction.yOffset + 'px'; } else { editorAction.e.style.top = newOffset + 'px'; editorAction.e.style.height = newHeight + 'px'; } } } } } // image state to change its current position in el container (mobile only) var imageState = { mousedown: false, mouseX: 0, mouseY: 0 } var touchstartListener = function(e) { if (! e.target.classList.contains('jcrop-area')) { imageState.mousedown = true; } if (e.changedTouches && e.changedTouches[0]) { imageState.mouseX = e.changedTouches[0].clientX; imageState.mouseY = e.changedTouches[0].clientY; } else { imageState.mouseX = e.clientX; imageState.mouseY = e.clientY; } } var imageMoveListener = function(e) { if (el.classList.contains('jcrop_edition')) { // Mark position if (e.changedTouches && e.changedTouches[0]) { var x = e.changedTouches[0].clientX; var y = e.changedTouches[0].clientY; } else { var x = e.clientX; var y = e.clientY; } var currentX = x; var newX = currentX - imageState.mouseX; imageState.mouseX = currentX; var currentY = y; var newY = currentY - imageState.mouseY; imageState.mouseY = currentY; if (imageState.mousedown) { image.left += newX/properties.zoom.scale; image.top += newY/properties.zoom.scale; refreshResizers(); } e.preventDefault(); } } el.addEventListener('mouseup', editorMouseUp); el.addEventListener('mousedown', editorMouseDown); el.addEventListener('mousemove', editorMouseMove); el.addEventListener('touchstart',touchstartListener); el.addEventListener('touchmove', imageMoveListener); el.addEventListener('mousedown',touchstartListener); document.addEventListener('mouseup', function(e) { imageState.mousedown = false; }); el.addEventListener('mousemove', imageMoveListener); el.addEventListener("dblclick", function(e) { jSuites.click(attachmentInput); }); el.addEventListener('dragenter', function(e) { el.style.border = '1px dashed #000'; }); el.addEventListener('dragleave', function(e) { el.style.border = '1px solid #eee'; }); el.addEventListener('dragstop', function(e) { el.style.border = '1px solid #eee'; }); el.addEventListener('dragover', function(e) { e.preventDefault(); }); el.addEventListener('drop', function(e) { e.preventDefault(); e.stopPropagation(); var html = (e.originalEvent || e).dataTransfer.getData('text/html'); var file = (e.originalEvent || e).dataTransfer.files; if (file.length) { for (var i = 0; i < e.dataTransfer.files.length; i++) { obj.addFromFile(e.dataTransfer.files[i]); } } else if (html) { // Create temp element var div = document.createElement('div'); div.innerHTML = html; // Extract images var img = div.querySelector('img'); if (img) { obj.addFromUrl(img.src); } } el.style.border = '1px solid #eee'; return false; }); el.addEventListener("wheel", function(e) { if (el.classList.contains('jcrop_edition')) { // Update scale if (e.deltaY > 0) { if (properties.zoom.scale > 0.1) { properties.zoom.scale *= 0.9; } } else { if (properties.zoom.scale < 5) { properties.zoom.scale *= 1.1; } } properties.zoom.scale = parseFloat(properties.zoom.scale.toFixed(2)); // Update coordinates var rect = el.getBoundingClientRect(); var x = e.clientX - rect.left; var y = e.clientY - rect.top; // Zoom on the image var c = context.getImageData(x, y, 1, 1).data; if (c[3] != 0) { properties.zoom.origin.x = x; properties.zoom.origin.y = y; } else { } // Apply zoom obj.zoom(); e.preventDefault(); } }); // mobile events el.addEventListener("click", function(e) { if (! el.classList.contains('jcrop_edition')) { jSuites.click(attachmentInput); } }); // Onchange if (typeof(obj.options.onload) == 'function') { obj.options.onload(el, obj); } // Initial image if (obj.options.value) { image.src = obj.options.value; } el.crop = obj; return obj; }); jSuites.login = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { url: window.location.href, prepareRequest: null, accessToken: null, deviceToken: null, facebookUrl: null, facebookAuthentication: null, maxHeight: null, onload: null, onsuccess: null, onerror: null, message: null, logo: null, newProfile: false, newProfileUrl: false, newProfileLogin: false, fullscreen: false, newPasswordValidation: null, }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Message console container if (! obj.options.message) { var messageElement = document.querySelector('.message'); if (messageElement) { obj.options.message = messageElement; } } // Action var action = null; // Container var container = document.createElement('form'); el.appendChild(container); // Logo var divLogo = document.createElement('div'); divLogo.className = 'jlogin-logo' container.appendChild(divLogo); if (obj.options.logo) { var logo = document.createElement('img'); logo.src = obj.options.logo; divLogo.appendChild(logo); } // Code var labelCode = document.createElement('label'); labelCode.innerHTML = 'Please enter here the code received'; var inputCode = document.createElement('input'); inputCode.type = 'number'; inputCode.id = 'code'; inputCode.setAttribute('maxlength', 6); var divCode = document.createElement('div'); divCode.appendChild(labelCode); divCode.appendChild(inputCode); // Hash var inputHash = document.createElement('input'); inputHash.type = 'hidden'; inputHash.name = 'h'; var divHash = document.createElement('div'); divHash.appendChild(inputHash); // Recovery var inputRecovery = document.createElement('input'); inputRecovery.type = 'hidden'; inputRecovery.name = 'recovery'; inputRecovery.value = '1'; var divRecovery = document.createElement('div'); divRecovery.appendChild(inputRecovery); // Login var labelLogin = document.createElement('label'); labelLogin.innerHTML = 'Login'; var inputLogin = document.createElement('input'); inputLogin.type = 'text'; inputLogin.name = 'login'; inputLogin.setAttribute('autocomplete', 'off'); inputLogin.onkeyup = function() { this.value = this.value.toLowerCase().replace(/[^a-zA-Z0-9_+]+/gi, ''); } var divLogin = document.createElement('div'); divLogin.appendChild(labelLogin); divLogin.appendChild(inputLogin); // Name var labelName = document.createElement('label'); labelName.innerHTML = 'Name'; var inputName = document.createElement('input'); inputName.type = 'text'; inputName.name = 'name'; var divName = document.createElement('div'); divName.appendChild(labelName); divName.appendChild(inputName); // Email var labelUsername = document.createElement('label'); labelUsername.innerHTML = 'E-mail'; var inputUsername = document.createElement('input'); inputUsername.type = 'text'; inputUsername.name = 'username'; inputUsername.setAttribute('autocomplete', 'new-username'); var divUsername = document.createElement('div'); divUsername.appendChild(labelUsername); divUsername.appendChild(inputUsername); // Password var labelPassword = document.createElement('label'); labelPassword.innerHTML = 'Password'; var inputPassword = document.createElement('input'); inputPassword.type = 'password'; inputPassword.name = 'password'; inputPassword.setAttribute('autocomplete', 'new-password'); var divPassword = document.createElement('div'); divPassword.appendChild(labelPassword); divPassword.appendChild(inputPassword); divPassword.onkeydown = function(e) { if (e.keyCode == 13) { obj.execute(); } } // Repeat password var labelRepeatPassword = document.createElement('label'); labelRepeatPassword.innerHTML = 'Repeat the new password'; var inputRepeatPassword = document.createElement('input'); inputRepeatPassword.type = 'password'; inputRepeatPassword.name = 'password'; var divRepeatPassword = document.createElement('div'); divRepeatPassword.appendChild(labelRepeatPassword); divRepeatPassword.appendChild(inputRepeatPassword); // Remember checkbox var labelRemember = document.createElement('label'); labelRemember.innerHTML = 'Remember me on this device'; var inputRemember = document.createElement('input'); inputRemember.type = 'checkbox'; inputRemember.name = 'remember'; inputRemember.value = '1'; labelRemember.appendChild(inputRemember); var divRememberButton = document.createElement('div'); divRememberButton.className = 'rememberButton'; divRememberButton.appendChild(labelRemember); // Login button var actionButton = document.createElement('input'); actionButton.type = 'button'; actionButton.value = 'Log In'; actionButton.onclick = function() { obj.execute(); } var divActionButton = document.createElement('div'); divActionButton.appendChild(actionButton); // Cancel button var cancelButton = document.createElement('div'); cancelButton.innerHTML = 'Cancel'; cancelButton.className = 'cancelButton'; cancelButton.onclick = function() { obj.requestAccess(); } var divCancelButton = document.createElement('div'); divCancelButton.appendChild(cancelButton); // Captcha var labelCaptcha = document.createElement('label'); labelCaptcha.innerHTML = 'Please type here the code below'; var inputCaptcha = document.createElement('input'); inputCaptcha.type = 'text'; inputCaptcha.name = 'captcha'; var imageCaptcha = document.createElement('img'); var divCaptcha = document.createElement('div'); divCaptcha.className = 'jlogin-captcha'; divCaptcha.appendChild(labelCaptcha); divCaptcha.appendChild(inputCaptcha); divCaptcha.appendChild(imageCaptcha); // Facebook var facebookButton = document.createElement('div'); facebookButton.innerHTML = 'Login with Facebook'; facebookButton.className = 'facebookButton'; var divFacebookButton = document.createElement('div'); divFacebookButton.appendChild(facebookButton); divFacebookButton.onclick = function() { obj.requestLoginViaFacebook(); } // Forgot password var inputRequest = document.createElement('span'); inputRequest.innerHTML = 'Request a new password'; var divRequestButton = document.createElement('div'); divRequestButton.className = 'requestButton'; divRequestButton.appendChild(inputRequest); divRequestButton.onclick = function() { obj.requestNewPassword(); } // Create a new Profile var inputNewProfile = document.createElement('span'); inputNewProfile.innerHTML = 'Create a new profile'; var divNewProfileButton = document.createElement('div'); divNewProfileButton.className = 'newProfileButton'; divNewProfileButton.appendChild(inputNewProfile); divNewProfileButton.onclick = function() { obj.newProfile(); } el.className = 'jlogin'; if (obj.options.fullscreen == true) { el.classList.add('jlogin-fullscreen'); } /** * Show message */ obj.showMessage = function(data) { var message = (typeof(data) == 'object') ? data.message : data; if (typeof(obj.options.showMessage) == 'function') { obj.options.showMessage(data); } else { jSuites.alert(data); } } /** * New profile */ obj.newProfile = function() { container.innerHTML = ''; container.appendChild(divLogo); if (obj.options.newProfileLogin) { container.appendChild(divLogin); } container.appendChild(divName); container.appendChild(divUsername); container.appendChild(divActionButton); if (obj.options.facebookAuthentication == true) { container.appendChild(divFacebookButton); } container.appendChild(divCancelButton); // Reset inputs inputLogin.value = ''; inputUsername.value = ''; inputPassword.value = ''; // Button actionButton.value = 'Create new profile'; // Action action = 'newProfile'; } /** * Request the email with the recovery instructions */ obj.requestNewPassword = function() { if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) { var captcha = true; } container.innerHTML = ''; container.appendChild(divLogo); container.appendChild(divRecovery); container.appendChild(divUsername); if (captcha) { container.appendChild(divCaptcha); } container.appendChild(divActionButton); container.appendChild(divCancelButton); actionButton.value = 'Request a new password'; inputRecovery.value = 1; // Action action = 'requestNewPassword'; } /** * Confirm recovery code */ obj.codeConfirmation = function() { container.innerHTML = ''; container.appendChild(divLogo); container.appendChild(divHash); container.appendChild(divCode); container.appendChild(divActionButton); container.appendChild(divCancelButton); actionButton.value = 'Confirm code'; inputRecovery.value = 2; // Action action = 'codeConfirmation'; } /** * Update my password */ obj.changeMyPassword = function(hash) { container.innerHTML = ''; container.appendChild(divLogo); container.appendChild(divHash); container.appendChild(divPassword); container.appendChild(divRepeatPassword); container.appendChild(divActionButton); container.appendChild(divCancelButton); actionButton.value = 'Change my password'; inputHash.value = hash; // Action action = 'changeMyPassword'; } /** * Request access default method */ obj.requestAccess = function() { container.innerHTML = ''; container.appendChild(divLogo); container.appendChild(divUsername); container.appendChild(divPassword); container.appendChild(divActionButton); if (obj.options.facebookAuthentication == true) { container.appendChild(divFacebookButton); } container.appendChild(divRequestButton); container.appendChild(divRememberButton); container.appendChild(divRequestButton); if (obj.options.newProfile == true) { container.appendChild(divNewProfileButton); } // Button actionButton.value = 'Login'; // Password inputPassword.value = ''; // Email persistence if (window.localStorage.getItem('username')) { inputUsername.value = window.localStorage.getItem('username'); inputPassword.focus(); } else { inputUsername.focus(); } // Action action = 'requestAccess'; } /** * Request login via facebook */ obj.requestLoginViaFacebook = function() { if (typeof(deviceNotificationToken) == 'undefined') { FB.getLoginStatus(function(response) { if (! response.status || response.status != 'connected') { FB.login(function(response) { if (response.authResponse) { obj.execute({ f:response.authResponse.accessToken }); } else { obj.showMessage('Not authorized by facebook'); } }, {scope: 'public_profile,email'}); } else { obj.execute({ f:response.authResponse.accessToken }); } }, true); } else { jDestroy = function() { fbLogin.removeEventListener('loadstart', jStart); fbLogin.removeEventListener('loaderror', jError); fbLogin.removeEventListener('exit', jExit); fbLogin.close(); fbLogin = null; } jStart = function(event) { var url = event.url; if (url.indexOf("access_token") >= 0) { setTimeout(function(){ var u = url.match(/=(.*?)&/); if (u[1].length > 32) { obj.execute({ f:u[1] }); } jDestroy(); },500); } if (url.indexOf("error=access_denied") >= 0) { setTimeout(jDestroy ,500); // Not authorized by facebook obj.showMessage('Not authorized by facebook'); } } jError = function(event) { jDestroy(); } jExit = function(event) { jDestroy(); } fbLogin = window.open(obj.options.facebookUrl, "_blank", "location=no,closebuttoncaption=Exit,disallowoverscroll=yes,toolbar=no"); fbLogin.addEventListener('loadstart', jStart); fbLogin.addEventListener('loaderror', jError); fbLogin.addEventListener('exit', jExit); } // Action action = 'requestLoginViaFacebook'; } // Perform request obj.execute = function(data) { // New profile if (action == 'newProfile') { var pattern = new RegExp(/^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/); if (! inputUsername.value || ! pattern.test(inputUsername.value)) { var message = 'Invalid e-mail address'; } var pattern = new RegExp(/^[a-zA-Z0-9\_\-\.\s+]+$/); if (! inputLogin.value || ! pattern.test(inputLogin.value)) { var message = 'Invalid username, please use only characters and numbers'; } if (message) { obj.showMessage(message); return false; } } else if (action == 'changeMyPassword') { if (inputPassword.value.length < 3) { var message = 'Password is too short'; } else if (inputPassword.value != inputRepeatPassword.value) { var message = 'Password should match'; } else { if (typeof(obj.options.newPasswordValidation) == 'function') { var val = obj.options.newPasswordValidation(obj, inputPassword.value, inputPassword.value); if (val != undefined) { message = val; } } } if (message) { obj.showMessage(message); return false; } } // Keep email if (inputUsername.value != '') { window.localStorage.setItem('username', inputUsername.value); } // Captcha if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) { if (inputCaptcha.value == '') { obj.showMessage('Please enter the captch code below'); return false; } } // Url var url = obj.options.url; // Device token if (obj.options.deviceToken) { url += '?token=' + obj.options.deviceToken; } // Callback var onsuccess = function(result) { if (result) { // Successfully response if (result.success == 1) { // Recovery process if (action == 'requestNewPassword') { obj.codeConfirmation(); } else if (action == 'codeConfirmation') { obj.requestAccess(); } else if (action == 'newProfile') { obj.requestAccess(); // New profile result.newProfile = true; } // Token if (result.token) { // Set token obj.options.accessToken = result.token; // Save token window.localStorage.setItem('Access-Token', result.token); } } // Show message if (result.message) { // Show message obj.showMessage(result.message) } // Request captcha code if (! result.data) { if (Array.prototype.indexOf.call(container.children, divCaptcha) >= 0) { divCaptcha.remove(); } } else { container.insertBefore(divCaptcha, divActionButton); imageCaptcha.setAttribute('src', 'data:image/png;base64,' + result.data); } // Give time to user see the message if (result.hash) { // Change password obj.changeMyPassword(result.hash); } else if (result.url) { // App initialization if (result.success == 1) { if (typeof(obj.options.onsuccess) == 'function') { obj.options.onsuccess(result); } else { if (result.message) { setTimeout(function() { window.location.href = result.url; }, 2000); } else { window.location.href = result.url; } } } else { if (typeof(obj.options.onerror) == 'function') { obj.options.onerror(result); } } } } } // Password if (! data) { var data = jSuites.form.getElements(el, true); // Encode passworfd if (data.password) { data.password = jSuites.sha512(data.password); } // Recovery code if (Array.prototype.indexOf.call(container.children, divCode) >= 0 && inputCode.value) { data.h = jSuites.sha512(inputCode.value); } } // Loading el.classList.add('jlogin-loading'); // Url var url = (action == 'newProfile' && obj.options.newProfileUrl) ? obj.options.newProfileUrl : obj.options.url; // Remote call jSuites.ajax({ url: url, method: 'POST', dataType: 'json', data: data, success: function(result) { // Remove loading el.classList.remove('jlogin-loading'); // Callback onsuccess(result); }, error: function(result) { // Error el.classList.remove('jlogin-loading'); if (typeof(obj.options.onerror) == 'function') { obj.options.onerror(result); } } }); } var queryString = window.location.href.split('?'); if (queryString[1] && queryString[1].length == 130 && queryString[1].substr(0,2) == 'h=') { obj.changeMyPassword(queryString[1].substr(2)); } else { obj.requestAccess(); } return obj; }); jSuites.login.sha512 = jSuites.sha512; jSuites.menu = (function(el, options) { var obj = {}; obj.show = function() { el.style.display = 'block'; jSuites.animation.slideLeft(el, 1); } obj.hide = function() { jSuites.animation.slideLeft(el, 0, function() { el.style.display = ''; }); } obj.load = function() { if (localStorage) { var menu = el.querySelectorAll('nav'); for (var i = 0; i < menu.length; i++) { menu[i].classList.remove('selected'); if (menu[i].getAttribute('data-id')) { var state = localStorage.getItem('jmenu-' + menu[i].getAttribute('data-id')); if (state === null || state == 1) { menu[i].classList.add('selected'); } } } var href = localStorage.getItem('jmenu-href'); if (href) { var menu = document.querySelector('.jmenu a[href="'+ href +'"]'); if (menu) { menu.classList.add('selected'); } } } } obj.select = function(o) { var menu = el.querySelectorAll('nav a'); for (var i = 0; i < menu.length; i++) { menu[i].classList.remove('selected'); } o.classList.add('selected'); } var actionDown = function(e) { if (e.target.tagName == 'H2') { if (e.target.parentNode.classList.contains('selected')) { e.target.parentNode.classList.remove('selected'); localStorage.setItem('jmenu-' + e.target.parentNode.getAttribute('data-id'), 0); } else { e.target.parentNode.classList.add('selected'); localStorage.setItem('jmenu-' + e.target.parentNode.getAttribute('data-id'), 1); } } else if (e.target.tagName == 'A') { // Mark link as selected obj.select(e.target); // Keep the refernce in case load the page again localStorage.setItem('jmenu-href', e.target.getAttribute('href')); // Close menu if is oped obj.hide(); } } if ('ontouchstart' in document.documentElement === true) { el.addEventListener('touchstart', actionDown); } else { el.addEventListener('mousedown', actionDown); } // Add close action var i = document.createElement('i'); i.className = 'material-icons small-screen-only close'; i.innerText = 'close'; i.onclick = function() { obj.hide(); } el.appendChild(i); // Add menu class el.classList.add('jmenu'); /*var h1 = window.innerHeight; var h2 = el.offsetTop; // Add the scroll jSuites.scroll(el, { //height: (h1 - h2) + 'px' height: '1000px', });*/ // Load state obj.load(); // Keep reference el.menu = obj; return obj; }); jSuites.signature = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { width: '100%', height: '120px', lineWidth: 3, onchange: null, value: null, readonly: 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]; } } el.style.width = obj.options.width; el.style.height = obj.options.height; el.classList.add('jsignature'); var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); el.appendChild(canvas); // Position var x = null; var y = null; // Coordinates var coordinates = []; obj.setValue = function(c) { obj.reset(); ctx.beginPath(); ctx.lineWidth = obj.options.lineWidth; ctx.lineCap = 'round'; ctx.strokeStyle = '#000'; ctx.moveTo(c[0][0], c[0][1]); for (var i = 1; i < c.length; i++) { ctx.lineTo(c[i][0], c[i][1]); ctx.stroke(); } } obj.getValue = function() { return coordinates; } obj.reset = function() { coordinates = []; ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); } var setPosition = function(e) { // Mark position if (e.changedTouches && e.changedTouches[0]) { var rect = e.target.getBoundingClientRect(); x = e.changedTouches[0].clientX - rect.x; y = e.changedTouches[0].clientY - rect.y; } else { x = e.offsetX; y = e.offsetY; } } var resize = function() { ctx.canvas.width = el.offsetWidth; ctx.canvas.height = el.offsetHeight; } var draw = function(e) { if (x == null || obj.options.readonly == true) { return false; } else { e = e || window.event; if (e.buttons) { var mouseButton = e.buttons; } else if (e.button) { var mouseButton = e.button; } else { var mouseButton = e.which; } coordinates.push([ x, y ]); ctx.beginPath(); ctx.lineWidth = obj.options.lineWidth; ctx.lineCap = 'round'; ctx.strokeStyle = '#000'; ctx.moveTo(x, y); setPosition(e); ctx.lineTo(x, y); ctx.stroke(); e.preventDefault(); e.stopPropagation(); } } var finalize = function() { x = null; y = null; } window.addEventListener('resize', resize); if ('ontouchmove' in document.documentElement === true) { el.addEventListener('touchstart', setPosition); el.addEventListener('touchmove', draw); el.addEventListener('touchend', finalize); } else { el.addEventListener('mousedown', setPosition); el.addEventListener('mousemove', draw); el.addEventListener('mouseup', finalize); } resize(); if (obj.options.value) { obj.setValue(obj.options.value); } el.signature = obj; return obj; }); jSuites.template = (function(el, options) { var obj = {}; obj.options = {}; // Default configuration var defaults = { url: null, data: null, filter: null, pageNumber: 0, numberOfPages: 0, template: null, render: null, noRecordsFound: 'No records found', containerClass: null, // Searchable search: null, searchInput: true, searchPlaceHolder: '', searchValue: '', // Remote search remoteData: null, // Pagination page number of items pagination: null, onload: null, onchange: null, onsearch: 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]; } } // Reset content el.innerHTML = ''; // Input search if (obj.options.search && obj.options.searchInput == true) { // Timer var searchTimer = null; // Search container var searchContainer = document.createElement('div'); searchContainer.className = 'jtemplate-results'; obj.searchInput = document.createElement('input'); obj.searchInput.value = obj.options.searchValue; obj.searchInput.onkeyup = function(e) { // Clear current trigger if (searchTimer) { clearTimeout(searchTimer); } // Prepare search searchTimer = setTimeout(function() { obj.search(obj.searchInput.value.toLowerCase()); searchTimer = null; }, 300) } searchContainer.appendChild(obj.searchInput); el.appendChild(searchContainer); if (obj.options.searchPlaceHolder) { obj.searchInput.setAttribute('placeholder', obj.options.searchPlaceHolder); } } // Pagination container if (obj.options.pagination) { var pagination = document.createElement('div'); pagination.className = 'jtemplate-pagination'; el.appendChild(pagination); } // Content var container = document.createElement('div'); if (obj.options.containerClass) { container.className = obj.options.containerClass; } container.classList.add ('jtemplate-content'); el.appendChild(container); // Data container var searchResults = null; obj.updatePagination = function() { // Reset pagination container if (pagination) { pagination.innerHTML = ''; } // Create pagination if (obj.options.pagination > 0 && obj.options.numberOfPages > 1) { // Number of pages var numberOfPages = obj.options.numberOfPages; // Controllers if (obj.options.pageNumber < 6) { var startNumber = 1; var finalNumber = numberOfPages < 10 ? numberOfPages : 10; } else if (numberOfPages - obj.options.pageNumber < 5) { var startNumber = numberOfPages - 9; var finalNumber = numberOfPages; if (startNumber < 1) { startNumber = 1; } } else { var startNumber = obj.options.pageNumber - 4; var finalNumber = obj.options.pageNumber + 5; } // First if (startNumber > 1) { var paginationItem = document.createElement('div'); paginationItem.innerHTML = '<'; paginationItem.title = 1; pagination.appendChild(paginationItem); } // Get page links for (var i = startNumber; i <= finalNumber; i++) { var paginationItem = document.createElement('div'); paginationItem.innerHTML = i; pagination.appendChild(paginationItem); if (obj.options.pageNumber == i - 1) { paginationItem.style.fontWeight = 'bold'; } } // Last if (finalNumber < numberOfPages) { var paginationItem = document.createElement('div'); paginationItem.innerHTML = '>'; paginationItem.title = numberOfPages - 1; pagination.appendChild(paginationItem); } } } /** * Append data to the template and add to the DOMContainer * @param data * @param contentDOMContainer */ obj.setContent = function(a, b) { var c = obj.options.template[Object.keys(obj.options.template)[0]](a); if ((c instanceof Element || c instanceof HTMLDocument)) { b.appendChild(c); } else { b.innerHTML = c; } } obj.addItem = function(data, beginOfDataSet) { // Append itens var content = document.createElement('div'); // Append data if (beginOfDataSet) { obj.options.data.unshift(data); } else { obj.options.data.push(data); } // If is empty remove indication if (container.classList.contains('jtemplate-empty')) { container.classList.remove('jtemplate-empty'); container.innerHTML = ''; } // Get content obj.setContent(data, content); // Add animation jSuites.animation.fadeIn(content.children[0]); // Add and do the animation if (beginOfDataSet) { container.prepend(content.children[0]); } else { container.append(content.children[0]); } // Onchange method if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, obj.options.data); } } obj.removeItem = function(element) { if (Array.prototype.indexOf.call(container.children, element) > -1) { // Remove data from array var index = obj.options.data.indexOf(element.dataReference); if (index > -1) { obj.options.data.splice(index, 1); } // Remove element from DOM jSuites.animation.fadeOut(element, function() { element.parentNode.removeChild(element); if (! container.innerHTML) { container.classList.add('jtemplate-empty'); container.innerHTML = obj.options.noRecordsFound; } }); } else { console.error('Element not found'); } } obj.setData = function(data) { if (data) { obj.options.pageNumber = 1; obj.options.searchValue = ''; // Set data obj.options.data = data; // Reset any search results searchResults = null; // Render new data obj.render(); // Onchange method if (typeof(obj.options.onchange) == 'function') { obj.options.onchange(el, obj.options.data); } } } obj.appendData = function(data, pageNumber) { if (pageNumber) { obj.options.pageNumber = pageNumber; } var execute = function(data) { // Concat data obj.options.data.concat(data); // Number of pages if (obj.options.pagination > 0) { obj.options.numberOfPages = Math.ceil(obj.options.data.length / obj.options.pagination); } var startNumber = 0; var finalNumber = data.length; // Append itens var content = document.createElement('div'); for (var i = startNumber; i < finalNumber; i++) { obj.setContent(data[i], content) content.children[0].dataReference = data[i]; // TODO: data[i] or i? container.appendChild(content.children[0]); } } if (obj.options.url && obj.options.remoteData == true) { // URL var url = obj.options.url; // Data var ajaxData = {}; // Options for backend search if (obj.options.remoteData) { // Search value if (obj.options.searchValue) { ajaxData.q = obj.options.searchValue; } // Page number if (obj.options.pageNumber) { ajaxData.p = obj.options.pageNumber; } // Number items per page if (obj.options.pagination) { ajaxData.t = obj.options.pagination; } } // Remote loading jSuites.ajax({ url: url, method: 'GET', data: ajaxData, dataType: 'json', success: function(data) { execute(data); } }); } else { if (! obj.options.data) { console.log('TEMPLATE: no data or external url defined'); } else { execute(data); } } } obj.renderTemplate = function() { // Data container var data = searchResults ? searchResults : obj.options.data; // Data filtering if (typeof(obj.options.filter) == 'function') { data = obj.options.filter(data); } // Reset pagination obj.updatePagination(); if (! data.length) { container.innerHTML = obj.options.noRecordsFound; container.classList.add('jtemplate-empty'); } else { // Reset content container.classList.remove('jtemplate-empty'); // Create pagination if (obj.options.pagination && data.length > obj.options.pagination) { var startNumber = (obj.options.pagination * obj.options.pageNumber); var finalNumber = (obj.options.pagination * obj.options.pageNumber) + obj.options.pagination; if (data.length < finalNumber) { var finalNumber = data.length; } } else { var startNumber = 0; var finalNumber = data.length; } // Append itens var content = document.createElement('div'); for (var i = startNumber; i < finalNumber; i++) { // Get content obj.setContent(data[i], content); content.children[0].dataReference = data[i]; container.appendChild(content.children[0]); } } } obj.render = function(pageNumber, forceLoad) { // Update page number if (pageNumber != undefined) { obj.options.pageNumber = pageNumber; } else { if (! obj.options.pageNumber && obj.options.pagination > 0) { obj.options.pageNumber = 0; } } // Render data into template var execute = function() { // Render new content if (typeof(obj.options.render) == 'function') { container.innerHTML = obj.options.render(obj); } else { container.innerHTML = ''; } // Load data obj.renderTemplate(); // Onload if (typeof(obj.options.onload) == 'function') { obj.options.onload(el, obj); } } if (obj.options.url && (obj.options.remoteData == true || forceLoad)) { // URL var url = obj.options.url; // Data var ajaxData = {}; // Options for backend search if (obj.options.remoteData) { // Search value if (obj.options.searchValue) { ajaxData.q = obj.options.searchValue; } // Page number if (obj.options.pageNumber) { ajaxData.p = obj.options.pageNumber; } // Number items per page if (obj.options.pagination) { ajaxData.t = obj.options.pagination; } } // Remote loading jSuites.ajax({ url: url, method: 'GET', dataType: 'json', data: ajaxData, success: function(data) { // Search and keep data in the client side if (data.hasOwnProperty("total")) { obj.options.numberOfPages = Math.ceil(data.total / obj.options.pagination); obj.options.data = data.data; } else { // Number of pages if (obj.options.pagination > 0) { obj.options.numberOfPages = Math.ceil(data.length / obj.options.pagination); } obj.options.data = data; } // Load data for the user execute(); } }); } else { if (! obj.options.data) { console.log('TEMPLATE: no data or external url defined'); } else { // Number of pages if (obj.options.pagination > 0) { if (searchResults) { obj.options.numberOfPages = Math.ceil(searchResults.length / obj.options.pagination); } else { obj.options.numberOfPages = Math.ceil(obj.options.data.length / obj.options.pagination); } } // Load data for the user execute(); } } } obj.search = function(query) { obj.options.pageNumber = 0; obj.options.searchValue = query ? query : ''; // Filter data if (obj.options.remoteData == true || ! query) { searchResults = null; } else { var test = function(o, query) { for (var key in o) { var value = o[key]; if ((''+value).toLowerCase().search(query) >= 0) { return true; } } return false; } searchResults = obj.options.data.filter(function(item) { return test(item, query); }); } obj.render(); if (typeof(obj.options.onsearch) == 'function') { obj.options.onsearch(el, obj, query); } } obj.refresh = function() { obj.render(); } obj.reload = function() { obj.render(0, true); } el.addEventListener('mousedown', function(e) { if (e.target.parentNode.classList.contains('jtemplate-pagination')) { var index = e.target.innerText; if (index == '<') { obj.render(0); } else if (index == '>') { obj.render(e.target.getAttribute('title')); } else { obj.render(parseInt(index)-1); } e.preventDefault(); } }); el.addEventListener('click', function(e) { if (typeof(obj.options.onclick) == 'function') { obj.options.onclick(el, obj, e); } }); el.template = obj; // Render data obj.render(0, true); return obj; }); jSuites.timeline = (function(el, options) { var obj = {}; obj.options = {}; // Two digits var two = function(value) { value = '' + value; if (value.length == 1) { value = '0' + value; } return value; } // Default date format if (! options.date) { var date = new Date(); var y = date.getFullYear(); var m = two(date.getMonth() + 1); date = y + '-' + m; } // Default configurations var defaults = { url: null, data: [], date: date, months: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], monthsFull: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ], onaction: null, text: { noInformation: '
', } }; // Loop through our object for (var property in defaults) { if (options && options.hasOwnProperty(property)) { obj.options[property] = options[property]; } else { obj.options[property] = defaults[property]; } } // Add class el.classList.add('jtimeline'); // Header var timelineHeader = document.createElement('div'); timelineHeader.className = 'jtimeline-header'; var timelineLabel = document.createElement('div'); timelineLabel.className = 'jtimeline-label'; var timelineNavigation = document.createElement('div'); timelineNavigation.className = 'jtimeline-navigation'; // Labels var timelineMonth = document.createElement('div'); timelineMonth.className = 'jtimeline-month'; timelineMonth.innerHTML = ''; timelineLabel.appendChild(timelineMonth); var timelineYear = document.createElement('div'); timelineYear.className = 'jtimeline-year'; timelineYear.innerHTML = ''; timelineLabel.appendChild(timelineYear); // Navigation var timelinePrev = document.createElement('div'); timelinePrev.className = 'jtimeline-prev'; timelinePrev.innerHTML = 'keyboard_arrow_left'; timelineNavigation.appendChild(timelinePrev); var timelineNext = document.createElement('div'); timelineNext.className = 'jtimeline-next'; timelineNext.innerHTML = 'keyboard_arrow_right'; timelineNavigation.appendChild(timelineNext); timelineHeader.appendChild(timelineLabel); timelineHeader.appendChild(timelineNavigation); // Data container var timelineContainer = document.createElement('div'); timelineContainer.className = 'jtimeline-container'; // Append headers el.appendChild(timelineHeader); el.appendChild(timelineContainer); // Date if (obj.options.date.length > 7) { obj.options.date = obj.options.date.substr(0, 7) } // Action var action = function(o) { // Get item var item = o.parentNode.parentNode.parentNode.parentNode; // Get id var id = item.getAttribute('data-id'); } obj.setData = function(rows) { var data = []; for (var i = 0; i < rows.length; i++) { var d = rows[i].date.substr(0,7); // Create the object if not exists if (! data[d]) { data[d] = []; } // Create array data[d].push(rows[i]); }; obj.options.data = data; obj.render(obj.options.date); } obj.add = function(data) { var date = data.date.substr(0,7); // Create the object if not exists if (! obj.options.data[date]) { obj.options.data[date] = []; } // Format date data.date = data.date.substr(0,10); // Append data obj.options.data[date].push(data); // Reorder obj.options.data[date] = obj.options.data[date].order(); // Render obj.render(date); } obj.remove = function(item) { var index = item.getAttribute('data-index'); var date = item.getAttribute('data-date'); jSuites.animation.fadeOut(item, function() { item.remove(); }); obj.options.data[date].splice(index, 1); } obj.reload = function() { var date = obj.options.date obj.render(date); } obj.render = function(date) { // Filter if (date.length > 7) { var date = date.substr(0,7); } // Update current date obj.options.date = date; // Reset data timelineContainer.innerHTML = ''; // Days var timelineDays = []; // Itens if (! obj.options.data[date]) { timelineContainer.innerHTML = obj.options.text.noInformation; } else { for (var i = 0; i < obj.options.data[date].length; i++) { var v = obj.options.data[date][i]; var d = v.date.split('-'); // Item container var timelineItem = document.createElement('div'); timelineItem.className = 'jtimeline-item'; timelineItem.setAttribute('data-id', v.id); timelineItem.setAttribute('data-index', i); timelineItem.setAttribute('data-date', date); // Date var timelineDateContainer = document.createElement('div'); timelineDateContainer.className = 'jtimeline-date-container'; var timelineDate = document.createElement('div'); if (! timelineDays[d[2]]) { timelineDate.className = 'jtimeline-date jtimeline-date-bullet'; timelineDate.innerHTML = d[2]; } else { timelineDate.className = 'jtimeline-date'; timelineDate.innerHTML = ''; } timelineDateContainer.appendChild(timelineDate); var timelineContent = document.createElement('div'); timelineContent.className = 'jtimeline-content'; // Title if (! v.title) { v.title = v.subtitle ? v.subtitle : 'Information'; } var timelineTitleContainer = document.createElement('div'); timelineTitleContainer.className = 'jtimeline-title-container'; timelineContent.appendChild(timelineTitleContainer); var timelineTitle = document.createElement('div'); timelineTitle.className = 'jtimeline-title'; timelineTitle.innerHTML = v.title; timelineTitleContainer.appendChild(timelineTitle); var timelineControls = document.createElement('div'); timelineControls.className = 'jtimeline-controls'; timelineTitleContainer.appendChild(timelineControls); var timelineEdit = document.createElement('i'); timelineEdit.className = 'material-icons timeline-edit'; timelineEdit.innerHTML = 'edit'; timelineEdit.onclick = function() { if (typeof(obj.options.onaction) == 'function') { obj.options.onaction(obj, this); } } if (v.author == 1) { timelineControls.appendChild(timelineEdit); } var timelineSubtitle = document.createElement('div'); timelineSubtitle.className = 'jtimeline-subtitle'; timelineSubtitle.innerHTML = v.subtitle ? v.subtitle : ''; timelineContent.appendChild(timelineSubtitle); // Text var timelineText = document.createElement('div'); timelineText.className = 'jtimeline-text'; timelineText.innerHTML = v.text; timelineContent.appendChild(timelineText); // Tag var timelineTags = document.createElement('div'); timelineTags.className = 'jtimeline-tags'; timelineContent.appendChild(timelineTags); if (v.tags) { var createTag = function(name, color) { var timelineTag = document.createElement('div'); timelineTag.className = 'jtimeline-tag'; timelineTag.innerHTML = name; if (color) { timelineTag.style.backgroundColor = color; } return timelineTag; } if (typeof(v.tags) == 'string') { var t = createTag(v.tags); timelineTags.appendChild(t); } else { for (var j = 0; j < v.tags.length; j++) { var t = createTag(v.tags[j].text, v.tags[j].color); timelineTags.appendChild(t); } } } // Day timelineDays[d[2]] = true; // Append Item timelineItem.appendChild(timelineDateContainer); timelineItem.appendChild(timelineContent); timelineContainer.appendChild(timelineItem); }; } // Update labels var d = date.split('-'); timelineYear.innerHTML = d[0]; timelineMonth.innerHTML = obj.options.monthsFull[parseInt(d[1]) - 1]; } obj.next = function() { // Update current date var d = obj.options.date.split('-'); // Next month d[1]++; // Next year if (d[1] > 12) { d[0]++; d[1] = 1; } date = d[0] + '-' + (d[1] < 10 ? '0' + d[1] : d[1]); // Animation jSuites.animation.slideLeft(timelineContainer, 0, function() { obj.render(date); jSuites.animation.slideRight(timelineContainer, 1); }); } obj.prev = function() { // Update current date var d = obj.options.date.split('-'); // Next month d[1]--; // Next year if (d[1] < 1) { d[0]--; d[1] = 12; } date = d[0] + '-' + (d[1] < 10 ? '0' + d[1] : d[1]); // Animation jSuites.animation.slideRight(timelineContainer, 0, function() { obj.render(date); jSuites.animation.slideLeft(timelineContainer, 1); }); } obj.load = function() { // Init if (obj.options.url) { jSuites.ajax({ url: obj.options.url, type: 'GET', dataType:'json', success: function(data) { // Timeline data obj.setData(data); } }); } else { // Timeline data obj.setData(obj.options.data); } } obj.reload = function() { obj.load(); } obj.load(); var timelineMouseUpControls = function(e) { if (e.target.classList.contains('jtimeline-next') || e.target.parentNode.classList.contains('jtimeline-next')) { obj.next(); } else if (e.target.classList.contains('jtimeline-prev') || e.target.parentNode.classList.contains('jtimeline-prev')) { obj.prev(); } } if ('ontouchend' in document.documentElement === true) { el.addEventListener("touchend", timelineMouseUpControls); } else { el.addEventListener("mouseup", timelineMouseUpControls); } // Add global events el.addEventListener("swipeleft", function(e) { obj.next(); e.preventDefault(); e.stopPropagation(); }); el.addEventListener("swiperight", function(e) { obj.prev(); e.preventDefault(); e.stopPropagation(); }); // Orderby Array.prototype.order = function() { return this.slice(0).sort(function(a, b) { var valueA = a.date; var valueB = b.date; return (valueA > valueB) ? 1 : (valueA < valueB) ? -1 : 0; }); } el.timeline = obj; return obj; }); return jSuites; })));